Skip to content

Commit c0c75b3

Browse files
Fix a crash when handling un-specified project ids (#31)
1 parent 904c586 commit c0c75b3

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

provider/resource_edgenode.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,15 @@ func rdDeviceConfig(cfg *swagger_models.DeviceConfig, d *schema.ResourceData, cr
304304
}
305305
cfg.ProjectID = projectIdPtr
306306
} else {
307-
if cfg.ProjectID != nil && *cfg.ProjectID != *projectIdPtr {
307+
// Change of Project for a device is NOT supported with Update operation.
308+
// Check if the configured project is different from the config we got
309+
// from Cloud. If different - error out.
310+
// If project_id is not configured, ignore the check. We cannot verify
311+
// the case of device created with project_id set to non-default project,
312+
// but changed to remove set the project_id to empty, though this also is
313+
// not supported. Such an update request would be rejected by ZEDCloud.
314+
if projectIdPtr != nil && cfg.ProjectID != nil &&
315+
*cfg.ProjectID != *projectIdPtr {
308316
// Update. Project cannot be changed
309317
return fmt.Errorf("project_id cannot be changed after EdgeNode is "+
310318
"created. Current: %s, New: %s", *cfg.ProjectID, *projectIdPtr)

provider/resource_edgenode_test.go

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ import (
1111
"testing"
1212
)
1313

14+
func copyMap(originalMap map[string]interface{}) map[string]interface{} {
15+
newMap := make(map[string]interface{})
16+
for k, v := range originalMap {
17+
newMap[k] = v
18+
}
19+
return newMap
20+
}
21+
1422
var rdEdgeNodeEmptyOutput = map[string]interface{}{
1523
"adminstate": "",
1624
"adminstate_config": "",
@@ -145,11 +153,49 @@ var efoEdgeNodeFullCfg = map[string]interface{}{
145153
"utype": "",
146154
}
147155

156+
var rdEdgeNodeNilProjectId = map[string]interface{}{
157+
"name": "sample-EdgeNode",
158+
"id": "SAMPLE-EdgeNode-ID",
159+
"adminstate": "",
160+
"adminstate_config": "ADMIN_STATE_ACTIVE",
161+
"eve_image_version": "6.8.2-kvm-amd64",
162+
"interface": []interface{}{},
163+
"model_id": "Test Model",
164+
}
165+
166+
func rdEdgeNodeNilProjectIdOutput() map[string]interface{} {
167+
newMap := copyMap(rdEdgeNodeEmptyOutput)
168+
newMap["eve_image_version"] = rdEdgeNodeNilProjectId["eve_image_version"]
169+
newMap["id"] = rdEdgeNodeNilProjectId["id"]
170+
newMap["interface"] = rdEdgeNodeNilProjectId["interface"]
171+
newMap["name"] = rdEdgeNodeNilProjectId["name"]
172+
return newMap
173+
}
174+
175+
var rdEdgeNodeEmptyProjectId = map[string]interface{}{
176+
"name": "sample-EdgeNode",
177+
"id": "SAMPLE-EdgeNode-ID",
178+
"adminstate": "",
179+
"adminstate_config": "ADMIN_STATE_ACTIVE",
180+
"eve_image_version": "6.8.2-kvm-amd64",
181+
"interface": []interface{}{},
182+
"model_id": "Test Model",
183+
"project_id": "",
184+
}
185+
186+
func rdEdgeNodeUpdateProjectIdToNilOutput() map[string]interface{} {
187+
newMap := copyMap(rdEdgeNodeNilProjectIdOutput())
188+
newMap["project_id"] = "SampleProjectID"
189+
return newMap
190+
}
191+
148192
// In each test case, call rdXXX to get the appropriate config struct,
149193
// feed it to flattenXXX, verify output of flattenXXX is same as input
150194
func TestRDEdgeNodeConfig(t *testing.T) {
151195
cases := []struct {
152196
input map[string]interface{}
197+
update bool
198+
update_project_id bool
153199
description string
154200
expectError bool
155201
expectedFlattenedOutput map[string]interface{}
@@ -167,6 +213,27 @@ func TestRDEdgeNodeConfig(t *testing.T) {
167213
expectError: false,
168214
expectedFlattenedOutput: efoEdgeNodeFullCfg,
169215
},
216+
{
217+
input: rdEdgeNodeNilProjectId,
218+
description: "Nil Project Create",
219+
expectError: true,
220+
expectedFlattenedOutput: rdEdgeNodeNilProjectIdOutput(),
221+
},
222+
{
223+
input: rdEdgeNodeNilProjectId,
224+
description: "Update non-nil project id to Nil",
225+
expectError: false,
226+
update: true,
227+
update_project_id: true,
228+
expectedFlattenedOutput: rdEdgeNodeUpdateProjectIdToNilOutput(),
229+
},
230+
{
231+
input: rdEdgeNodeEmptyProjectId,
232+
description: "Empty Project Update",
233+
expectError: false,
234+
update: true,
235+
expectedFlattenedOutput: rdEdgeNodeNilProjectIdOutput(),
236+
},
170237
}
171238

172239
for _, c := range cases {
@@ -179,18 +246,23 @@ func TestRDEdgeNodeConfig(t *testing.T) {
179246
cfg.Name = &name
180247
cfg.ID, ok = c.input["id"].(string)
181248
cfg.BaseImage = cfgBaseosForEveVersionStr(rdEntryStr(rd, "eve_image_version"))
182-
err := rdDeviceConfig(cfg, rd, true)
249+
if c.update_project_id {
250+
project_id := "SampleProjectID"
251+
cfg.ProjectID = &project_id
252+
}
253+
err := rdDeviceConfig(cfg, rd, !c.update)
183254
if err != nil {
184255
if !c.expectError {
185256
t.Fatalf("Test Failed: %s\n"+
186257
"Unexpected error from updateEdgeNodeCfgFromResourceData.\n"+
187258
"Error: %+v\n", c.description, err.Error())
188259
}
189-
} else {
190-
if c.expectError {
191-
t.Fatalf("Test Failed: %s. Expecting Error, but did not get one",
192-
c.description)
193-
}
260+
// No point in continuing cfg is invalid
261+
continue
262+
}
263+
if c.expectError {
264+
t.Fatalf("Test Failed: %s. Expecting Error, but did not get one",
265+
c.description)
194266
}
195267
out := flattenDeviceConfig(cfg, false)
196268
err = verifyFlattenOutput(zschemas.EdgeNodeSchema, out, c.expectAllSchemaKeys)
@@ -202,7 +274,7 @@ func TestRDEdgeNodeConfig(t *testing.T) {
202274
t.Fatalf("Test Failed: %s\n"+
203275
"Error matching Flattened output and input.\n"+
204276
"Output: %#v\n"+
205-
"Input : %#v\n"+
277+
"expectedFlattenedOutput : %#v\n"+
206278
"Diff: %#v", c.description, out, c.expectedFlattenedOutput, diff)
207279
}
208280
}

0 commit comments

Comments
 (0)