1
// Copyright 2012-2016 Canonical Ltd.
2
// Licensed under the LGPLv3, see LICENCE file for details.
15
type MAASObjectSuite struct{}
17
var _ = Suite(&MAASObjectSuite{})
19
func makeFakeResourceURI() string {
20
return "http://example.com/" + fmt.Sprint(rand.Int31())
23
// JSONObjects containing MAAS objects convert only to map or to MAASObject.
24
func (suite *MAASObjectSuite) TestConversionsMAASObject(c *C) {
25
input := map[string]interface{}{resourceURI: "someplace"}
26
obj := maasify(Client{}, input)
28
mp, err := obj.GetMap()
30
text, err := mp[resourceURI].GetString()
32
c.Check(text, Equals, "someplace")
34
var maasobj MAASObject
35
maasobj, err = obj.GetMAASObject()
37
c.Check(maasobj, NotNil)
39
_, err = obj.GetString()
41
_, err = obj.GetFloat64()
43
_, err = obj.GetArray()
45
_, err = obj.GetBool()
49
func (suite *MAASObjectSuite) TestNewJSONMAASObjectPanicsIfNoResourceURI(c *C) {
51
recoveredError := recover()
52
c.Check(recoveredError, NotNil)
53
msg := recoveredError.(error).Error()
54
c.Check(msg, Matches, ".*no 'resource_uri' key.*")
57
input := map[string]interface{}{"test": "test"}
58
newJSONMAASObject(input, Client{})
61
func (suite *MAASObjectSuite) TestNewJSONMAASObjectPanicsIfResourceURINotString(c *C) {
63
recoveredError := recover()
64
c.Check(recoveredError, NotNil)
65
msg := recoveredError.(error).Error()
66
c.Check(msg, Matches, ".*invalid resource_uri.*")
69
input := map[string]interface{}{resourceURI: 77.77}
70
newJSONMAASObject(input, Client{})
73
func (suite *MAASObjectSuite) TestNewJSONMAASObjectPanicsIfResourceURINotURL(c *C) {
75
recoveredError := recover()
76
c.Check(recoveredError, NotNil)
77
msg := recoveredError.(error).Error()
78
c.Check(msg, Matches, ".*resource_uri.*valid URL.*")
81
input := map[string]interface{}{resourceURI: "%z"}
82
newJSONMAASObject(input, Client{})
85
func (suite *MAASObjectSuite) TestNewJSONMAASObjectSetsUpURI(c *C) {
86
URI, err := url.Parse("http://example.com/a/resource")
88
attrs := map[string]interface{}{resourceURI: URI.String()}
89
obj := newJSONMAASObject(attrs, Client{})
90
c.Check(obj.uri, DeepEquals, URI)
93
func (suite *MAASObjectSuite) TestURL(c *C) {
94
baseURL, err := url.Parse("http://example.com/")
96
uri := "http://example.com/a/resource"
97
resourceURL, err := url.Parse(uri)
99
input := map[string]interface{}{resourceURI: uri}
100
client := Client{APIURL: baseURL}
101
obj := newJSONMAASObject(input, client)
105
c.Check(URL, DeepEquals, resourceURL)
108
// makeFakeMAASObject creates a MAASObject for some imaginary resource.
109
// There is no actual HTTP service or resource attached.
110
// serviceURL is the base URL of the service, and resourceURI is the path for
111
// the object, relative to serviceURL.
112
func makeFakeMAASObject(serviceURL, resourcePath string) MAASObject {
113
baseURL, err := url.Parse(serviceURL)
115
panic(fmt.Errorf("creation of fake object failed: %v", err))
117
uri := serviceURL + resourcePath
118
input := map[string]interface{}{resourceURI: uri}
119
client := Client{APIURL: baseURL}
120
return newJSONMAASObject(input, client)
123
// Passing GetSubObject a relative path effectively concatenates that path to
124
// the original object's resource URI.
125
func (suite *MAASObjectSuite) TestGetSubObjectRelative(c *C) {
126
obj := makeFakeMAASObject("http://example.com/", "a/resource/")
128
subObj := obj.GetSubObject("test")
129
subURL := subObj.URL()
131
// uri ends with a slash and subName starts with one, but the two paths
132
// should be concatenated as "http://example.com/a/resource/test/".
133
expectedSubURL, err := url.Parse("http://example.com/a/resource/test/")
135
c.Check(subURL, DeepEquals, expectedSubURL)
138
// Passing GetSubObject an absolute path effectively substitutes that path for
139
// the path component in the original object's resource URI.
140
func (suite *MAASObjectSuite) TestGetSubObjectAbsolute(c *C) {
141
obj := makeFakeMAASObject("http://example.com/", "a/resource/")
143
subObj := obj.GetSubObject("/b/test")
144
subURL := subObj.URL()
146
expectedSubURL, err := url.Parse("http://example.com/b/test/")
148
c.Check(subURL, DeepEquals, expectedSubURL)
151
// An absolute path passed to GetSubObject is rooted at the server root, not
152
// at the service root. So every absolute resource URI must repeat the part
153
// of the path that leads to the service root. This does not double that part
155
func (suite *MAASObjectSuite) TestGetSubObjectAbsoluteDoesNotDoubleServiceRoot(c *C) {
156
obj := makeFakeMAASObject("http://example.com/service", "a/resource/")
158
subObj := obj.GetSubObject("/service/test")
159
subURL := subObj.URL()
161
// The "/service" part is not repeated; it must be included.
162
expectedSubURL, err := url.Parse("http://example.com/service/test/")
164
c.Check(subURL, DeepEquals, expectedSubURL)
167
// The argument to GetSubObject is a relative path, not a URL. So it won't
168
// take a query part. The special characters that mark a query are escaped
169
// so they are recognized as parts of the path.
170
func (suite *MAASObjectSuite) TestGetSubObjectTakesPathNotURL(c *C) {
171
obj := makeFakeMAASObject("http://example.com/", "x/")
173
subObj := obj.GetSubObject("/y?z")
175
c.Check(subObj.URL().String(), Equals, "http://example.com/y%3Fz/")
178
func (suite *MAASObjectSuite) TestGetField(c *C) {
179
uri := "http://example.com/a/resource"
180
fieldName := "field name"
181
fieldValue := "a value"
182
input := map[string]interface{}{
183
resourceURI: uri, fieldName: fieldValue,
185
obj := newJSONMAASObject(input, Client{})
186
value, err := obj.GetField(fieldName)
188
c.Check(value, Equals, fieldValue)
191
func (suite *MAASObjectSuite) TestSerializesToJSON(c *C) {
192
attrs := map[string]interface{}{
193
resourceURI: "http://maas.example.com/",
196
"macs": map[string]interface{}{"eth0": "AA:BB:CC:DD:EE:FF"},
198
obj := maasify(Client{}, attrs)
199
output, err := json.Marshal(obj)
202
var deserialized map[string]interface{}
203
err = json.Unmarshal(output, &deserialized)
205
c.Check(deserialized, DeepEquals, attrs)