Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit bbb77bb

Browse files
YujiOshimaDavid Chung
authored andcommitted
Use MaaS tag api for instance tag instead of file. (#434)
Signed-off-by: Yuji Oshima <[email protected]>
1 parent 0155bad commit bbb77bb

File tree

2 files changed

+222
-58
lines changed

2 files changed

+222
-58
lines changed

examples/instance/maas/instance.go

Lines changed: 136 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,79 @@ func (m maasPlugin) convertSpecToMaasParam(spec map[string]interface{}) url.Valu
4545
return param
4646
}
4747

48+
func (m maasPlugin) addTagsToNode(systemID string, tags map[string]string) error {
49+
tagListing := m.MaasObj.GetSubObject("tags")
50+
for tag, value := range tags {
51+
tagObj, err := tagListing.GetSubObject(tag).Get()
52+
if err != nil {
53+
_, err = tagListing.CallPost("new", url.Values{"name": {tag}, "comment": {value}})
54+
if err != nil {
55+
return err
56+
}
57+
tagObj, err = tagListing.GetSubObject(tag).Get()
58+
if err != nil {
59+
return err
60+
}
61+
}
62+
_, err = tagObj.CallPost("update_nodes", url.Values{"add": {systemID}})
63+
if err != nil {
64+
return err
65+
}
66+
}
67+
return nil
68+
}
69+
70+
func (m maasPlugin) deleteTagsFromNode(systemID string, tags []maas.MAASObject) error {
71+
for _, tag := range tags {
72+
_, err := tag.CallPost("update_nodes", url.Values{"remove": {systemID}})
73+
if err != nil {
74+
return err
75+
}
76+
}
77+
return nil
78+
79+
}
80+
81+
func (m maasPlugin) getTagsFromNode(systemID string) (map[string]string, error) {
82+
ret := map[string]string{}
83+
nodeListing := m.MaasObj.GetSubObject("nodes")
84+
listNodeObjects, err := nodeListing.CallGet("list", url.Values{})
85+
if err != nil {
86+
return nil, err
87+
}
88+
listNodes, err := listNodeObjects.GetArray()
89+
for _, nodeObj := range listNodes {
90+
node, err := nodeObj.GetMAASObject()
91+
if err != nil {
92+
return nil, err
93+
}
94+
id, err := node.GetField("system_id")
95+
if id == systemID {
96+
tags, err := node.GetMap()["tag_names"].GetArray()
97+
if err != nil {
98+
return nil, err
99+
}
100+
for _, tagObj := range tags {
101+
tag, err := tagObj.GetMAASObject()
102+
if err != nil {
103+
return nil, err
104+
}
105+
tagname, err := tag.GetField("name")
106+
if err != nil {
107+
return nil, err
108+
}
109+
tagcomment, err := tag.GetField("comment")
110+
if err != nil {
111+
return nil, err
112+
}
113+
ret[tagname] = tagcomment
114+
}
115+
return ret, nil
116+
}
117+
}
118+
return ret, nil
119+
}
120+
48121
func (m maasPlugin) checkDuplicate(systemID string) (bool, error) {
49122
files, err := ioutil.ReadDir(m.MaasfilesDir)
50123
if err != nil {
@@ -72,9 +145,7 @@ func (m maasPlugin) checkDuplicate(systemID string) (bool, error) {
72145

73146
// Provision creates a new instance.
74147
func (m maasPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
75-
76148
var properties map[string]interface{}
77-
78149
if spec.Properties != nil {
79150
if err := spec.Properties.Decode(&properties); err != nil {
80151
return nil, fmt.Errorf("Invalid instance properties: %s", err)
@@ -149,13 +220,10 @@ func (m maasPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
149220
if err := ioutil.WriteFile(path.Join(machineDir, "MachineID"), []byte(systemID), 0755); err != nil {
150221
return nil, err
151222
}
152-
tagData, err := types.AnyValue(spec.Tags)
223+
err = m.addTagsToNode(systemID, spec.Tags)
153224
if err != nil {
154225
return nil, err
155226
}
156-
if err := ioutil.WriteFile(path.Join(machineDir, "tags"), tagData.Bytes(), 0666); err != nil {
157-
return nil, err
158-
}
159227
if spec.LogicalID != nil {
160228
if err := ioutil.WriteFile(path.Join(machineDir, "ip"), []byte(*spec.LogicalID), 0666); err != nil {
161229
return nil, err
@@ -166,45 +234,36 @@ func (m maasPlugin) Provision(spec instance.Spec) (*instance.ID, error) {
166234

167235
// Label labels the instance
168236
func (m maasPlugin) Label(id instance.ID, labels map[string]string) error {
169-
files, err := ioutil.ReadDir(m.MaasfilesDir)
237+
nodeListing := m.MaasObj.GetSubObject("nodes")
238+
listNodeObjects, err := nodeListing.CallGet("list", url.Values{})
170239
if err != nil {
171240
return err
172241
}
173-
for _, file := range files {
174-
if !file.IsDir() {
175-
continue
176-
}
177-
machineDir := path.Join(m.MaasfilesDir, file.Name())
178-
systemID, err := ioutil.ReadFile(path.Join(machineDir, "MachineID"))
242+
listNodes, err := listNodeObjects.GetArray()
243+
for _, nodeObj := range listNodes {
244+
node, err := nodeObj.GetMAASObject()
179245
if err != nil {
180246
return err
181247
}
182-
if id == instance.ID(systemID) {
183-
184-
tagFile := path.Join(machineDir, "tags")
185-
buff, err := ioutil.ReadFile(tagFile)
186-
if err != nil {
187-
return err
188-
}
189-
190-
tags := map[string]string{}
191-
err = types.AnyBytes(buff).Decode(&tags)
248+
systemID, err := node.GetField("system_id")
249+
if string(id) == systemID {
250+
tagObjs, err := node.GetMap()["tag_names"].GetArray()
192251
if err != nil {
193252
return err
194253
}
195-
196-
for k, v := range labels {
197-
tags[k] = v
254+
tags := make([]maas.MAASObject, len(tagObjs))
255+
for i, tagObj := range tagObjs {
256+
tag, err := tagObj.GetMAASObject()
257+
if err != nil {
258+
return err
259+
}
260+
tags[i] = tag
198261
}
199262

200-
encoded, err := types.AnyValue(tags)
201-
if err != nil {
202-
return err
203-
}
204-
return ioutil.WriteFile(tagFile, encoded.Bytes(), 0666)
263+
m.deleteTagsFromNode(systemID, tags)
205264
}
206265
}
207-
return nil
266+
return m.addTagsToNode(string(id), labels)
208267
}
209268

210269
// Destroy terminates an existing instance.
@@ -218,8 +277,24 @@ func (m maasPlugin) Destroy(id instance.ID) error {
218277
listNodes, err := listNodeObjects.GetArray()
219278
for _, nodeObj := range listNodes {
220279
node, err := nodeObj.GetMAASObject()
280+
if err != nil {
281+
return err
282+
}
221283
systemID, err := node.GetField("system_id")
284+
if err != nil {
285+
return err
286+
}
222287
if systemID == string(id) {
288+
tagObjs, err := node.GetMap()["tag_names"].GetArray()
289+
tags := make([]maas.MAASObject, len(tagObjs))
290+
for i, tagObj := range tagObjs {
291+
tag, err := tagObj.GetMAASObject()
292+
if err != nil {
293+
return err
294+
}
295+
tags[i] = tag
296+
}
297+
m.deleteTagsFromNode(string(id), tags)
223298
if state, _ := node.GetField("substatus_name"); state == "Deploying" {
224299
params := url.Values{}
225300
if _, err = node.CallPost("abort_operation", params); err != nil {
@@ -258,48 +333,55 @@ func (m maasPlugin) Destroy(id instance.ID) error {
258333

259334
// DescribeInstances returns descriptions of all instances matching all of the provided tags.
260335
func (m maasPlugin) DescribeInstances(tags map[string]string) ([]instance.Description, error) {
261-
files, err := ioutil.ReadDir(m.MaasfilesDir)
336+
var ret []instance.Description
337+
nodeListing := m.MaasObj.GetSubObject("nodes")
338+
listNodeObjects, err := nodeListing.CallGet("list", url.Values{})
262339
if err != nil {
263340
return nil, err
264341
}
265-
descriptions := []instance.Description{}
266-
for _, file := range files {
267-
if !file.IsDir() {
268-
continue
269-
}
270-
machineDir := path.Join(m.MaasfilesDir, file.Name())
271-
tagData, err := ioutil.ReadFile(path.Join(machineDir, "tags"))
342+
listNodes, err := listNodeObjects.GetArray()
343+
for _, nodeObj := range listNodes {
344+
node, err := nodeObj.GetMAASObject()
272345
if err != nil {
273-
if os.IsNotExist(err) {
274-
continue
275-
}
276346
return nil, err
277347
}
278-
machineTags := map[string]string{}
279-
if err := types.AnyBytes(tagData).Decode(&machineTags); err != nil {
348+
nodeTags, err := node.GetMap()["tag_names"].GetArray()
349+
if err != nil {
280350
return nil, err
281351
}
282352
allMatched := true
353+
machineTags := make(map[string]string)
283354
for k, v := range tags {
355+
for _, tagObj := range nodeTags {
356+
tag, err := tagObj.GetMAASObject()
357+
if err != nil {
358+
return nil, err
359+
}
360+
tagname, err := tag.GetField("name")
361+
if err != nil {
362+
return nil, err
363+
}
364+
tagcomment, err := tag.GetField("comment")
365+
if err != nil {
366+
return nil, err
367+
}
368+
machineTags[tagname] = tagcomment
369+
}
284370
value, exists := machineTags[k]
285371
if !exists || v != value {
286372
allMatched = false
287-
break
288373
}
289374
}
290375
if allMatched {
291-
systemID, err := ioutil.ReadFile(path.Join(machineDir, "MachineID"))
292-
if err == nil {
293-
} else {
294-
if !os.IsNotExist(err) {
295-
return nil, err
296-
}
376+
systemID, err := node.GetField("system_id")
377+
if err != nil {
378+
return nil, err
297379
}
298-
descriptions = append(descriptions, instance.Description{
380+
ret = append(ret, instance.Description{
299381
ID: instance.ID(systemID),
300382
Tags: machineTags,
301383
})
302384
}
303385
}
304-
return descriptions, nil
386+
return ret, nil
305387
}

examples/instance/maas/instance_test.go

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,92 @@ import (
44
"github.com/docker/infrakit/pkg/spi/instance"
55
maas "github.com/juju/gomaasapi"
66
"github.com/stretchr/testify/require"
7+
"net/url"
78
"os"
89
"testing"
910
)
1011

12+
func TestAddansDelTags(t *testing.T) {
13+
testServer := maas.NewTestServer("1.0")
14+
defer testServer.Close()
15+
input := `{"system_id": "test", "hostname":"test", "status": ` + maas.NodeStatusReady + `}`
16+
testnode := testServer.NewNode(input)
17+
dir, _ := os.Getwd()
18+
m := NewMaasPlugin(dir, "", testServer.URL, "1.0")
19+
//Add Tags Test
20+
addTags := map[string]string{
21+
"newlabel1": "newvalue1",
22+
"newlabel2": "newvalue2",
23+
}
24+
requiredTags := addTags
25+
err := m.(*maasPlugin).addTagsToNode("test", addTags)
26+
require.NoError(t, err)
27+
tagObjs, err := testnode.GetMap()["tag_names"].GetArray()
28+
require.NoError(t, err)
29+
testNodeTags := map[string]string{}
30+
for _, tagObj := range tagObjs {
31+
tag, err := tagObj.GetMAASObject()
32+
require.NoError(t, err)
33+
tagname, err := tag.GetField("name")
34+
require.NoError(t, err)
35+
tagcomments, err := tag.GetField("comment")
36+
require.NoError(t, err)
37+
testNodeTags[tagname] = tagcomments
38+
}
39+
require.Equal(t, requiredTags, testNodeTags)
40+
41+
//Delete Tags Test
42+
targettags := m.(*maasPlugin).MaasObj.GetSubObject("tags").GetSubObject("newlabel2")
43+
delTags := []maas.MAASObject{targettags}
44+
require.NoError(t, err)
45+
err = m.(*maasPlugin).deleteTagsFromNode("test", delTags)
46+
require.NoError(t, err)
47+
delete(requiredTags, "newlabel2")
48+
tagObjs, err = testnode.GetMap()["tag_names"].GetArray()
49+
testNodeTags = map[string]string{}
50+
for _, tagObj := range tagObjs {
51+
tag, err := tagObj.GetMAASObject()
52+
require.NoError(t, err)
53+
tagname, err := tag.GetField("name")
54+
require.NoError(t, err)
55+
tagcomments, err := tag.GetField("comment")
56+
require.NoError(t, err)
57+
testNodeTags[tagname] = tagcomments
58+
}
59+
require.Equal(t, requiredTags, testNodeTags)
60+
}
61+
62+
func TestDelTagsWithoutNode(t *testing.T) {
63+
testServer := maas.NewTestServer("1.0")
64+
defer testServer.Close()
65+
input := `{"system_id": "test", "hostname":"test", "status": ` + maas.NodeStatusReady + `}`
66+
testnode := testServer.NewNode(input)
67+
dir, _ := os.Getwd()
68+
m := NewMaasPlugin(dir, "", testServer.URL, "1.0")
69+
tagListing := m.(*maasPlugin).MaasObj.GetSubObject("tags")
70+
tagListing.CallPost("new", url.Values{"name": {"wolabel"}, "comment": {"value"}})
71+
72+
//Delete Without Tags Test
73+
targettags, err := m.(*maasPlugin).MaasObj.GetSubObject("tags").GetSubObject("wolabel").Get()
74+
require.NoError(t, err)
75+
delTags := []maas.MAASObject{targettags}
76+
err = m.(*maasPlugin).deleteTagsFromNode("test", delTags)
77+
require.NoError(t, err)
78+
tagObjs, err := testnode.GetMap()["tag_names"].GetArray()
79+
requiredTags := map[string]string{}
80+
testNodeTags := map[string]string{}
81+
for _, tagObj := range tagObjs {
82+
tag, err := tagObj.GetMAASObject()
83+
require.NoError(t, err)
84+
tagname, err := tag.GetField("name")
85+
require.NoError(t, err)
86+
tagcomments, err := tag.GetField("comment")
87+
require.NoError(t, err)
88+
testNodeTags[tagname] = tagcomments
89+
}
90+
require.Equal(t, requiredTags, testNodeTags)
91+
}
92+
1193
func TestProvision_and_Destroy(t *testing.T) {
1294
testServer := maas.NewTestServer("1.0")
1395
defer testServer.Close()
@@ -39,7 +121,7 @@ func TestProvision_and_Destroy(t *testing.T) {
39121
}, list)
40122
err = maasPlugin.Label(*id, map[string]string{
41123
"label1": "value1",
42-
"label2": "changed",
124+
"label3": "changed",
43125
})
44126
require.NoError(t, err)
45127

@@ -50,19 +132,19 @@ func TestProvision_and_Destroy(t *testing.T) {
50132
ID: *id,
51133
Tags: map[string]string{
52134
"label1": "value1",
53-
"label2": "changed",
135+
"label3": "changed",
54136
},
55137
},
56138
}, list)
57139

58-
list, err = maasPlugin.DescribeInstances(map[string]string{"label2": "changed"})
140+
list, err = maasPlugin.DescribeInstances(map[string]string{"label3": "changed"})
59141
require.NoError(t, err)
60142
require.Equal(t, []instance.Description{
61143
{
62144
ID: *id,
63145
Tags: map[string]string{
64146
"label1": "value1",
65-
"label2": "changed",
147+
"label3": "changed",
66148
},
67149
},
68150
}, list)

0 commit comments

Comments
 (0)