Skip to content

Commit 9bd2604

Browse files
committed
Fix drift and update failures for adopted edge transport nodes
node_id-adoption ConflictsWith advanced_configuration, credentials, form_factor and management_interface, so config for an adopted node never sets them. Read still populated all of them unconditionally from the API, showing permanent spurious drift on every plan; form_factor additionally carries a static schema Default that would keep re-asserting itself even with Read fixed, so it needs a DiffSuppressFunc instead. More seriously, Update always rebuilt the request body from config via policyEdgeTransportNodePatch, same as a freshly created node. For an adopted node that sends an empty management_interface, which NSX rejects as missing required fields on any update - including one only triggered by the spurious drift above. Route Update through the same GET-then-merge policyEdgeTransportNodePredeployedPatch that Create already uses for adoption.
1 parent 9f907c7 commit 9bd2604

1 file changed

Lines changed: 34 additions & 6 deletions

File tree

nsxt/resource_nsxt_policy_edge_transport_node.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,13 @@ func resourceNsxtPolicyEdgeTransportNode() *schema.Resource {
469469
Default: model.PolicyEdgeTransportNode_FORM_FACTOR_MEDIUM,
470470
Optional: true,
471471
ValidateFunc: validation.StringInSlice(policyEdgeNodeFormFactorValues, false),
472+
// form_factor conflicts with node_id, so it can never be set in
473+
// config for an adopted (pre-existing) node. Without this, the
474+
// schema Default would still apply and perpetually plan to force
475+
// the adopted node's real form factor back to the default value.
476+
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
477+
return d.Get("node_id").(string) != ""
478+
},
472479
},
473480
"hostname": {
474481
Type: schema.TypeString,
@@ -1549,6 +1556,12 @@ func resourceNsxtPolicyEdgeTransportNodeRead(d *schema.ResourceData, m interface
15491556
return handleReadError(d, "EdgeTransportNode", id, err)
15501557
}
15511558

1559+
// advanced_configuration, credentials and management_interface all
1560+
// conflict with node_id, so an adopted (pre-existing) node's config never
1561+
// declares them. Populating them from the API anyway would show up as
1562+
// permanent, spurious drift wanting to null them back out on every plan.
1563+
adopted := d.Get("node_id").(string) != ""
1564+
15521565
d.Set("site_path", sitePath)
15531566
d.Set("enforcement_point", epID)
15541567
d.Set("display_name", obj.DisplayName)
@@ -1557,23 +1570,27 @@ func resourceNsxtPolicyEdgeTransportNodeRead(d *schema.ResourceData, m interface
15571570
d.Set("nsx_id", id)
15581571
d.Set("path", obj.Path)
15591572
d.Set("revision", obj.Revision)
1560-
d.Set("advanced_configuration", setPolicyKeyValueListForSchema(obj.AdvancedConfiguration))
1573+
if !adopted {
1574+
d.Set("advanced_configuration", setPolicyKeyValueListForSchema(obj.AdvancedConfiguration))
1575+
}
15611576

15621577
err = setApplianceConfigInSchema(d, obj.ApplianceConfig)
15631578
if err != nil {
15641579
return handleReadError(d, "EdgeTransportNode", id, err)
15651580
}
15661581

1567-
err = setCredentialsInSchema(d, obj.Credentials)
1568-
if err != nil {
1569-
return handleReadError(d, "EdgeTransportNode", id, err)
1582+
if !adopted {
1583+
err = setCredentialsInSchema(d, obj.Credentials)
1584+
if err != nil {
1585+
return handleReadError(d, "EdgeTransportNode", id, err)
1586+
}
15701587
}
15711588

15721589
d.Set("failure_domain_path", obj.FailureDomainPath)
15731590
d.Set("form_factor", obj.FormFactor)
15741591
d.Set("hostname", obj.Hostname)
15751592

1576-
if obj.ManagementInterface != nil {
1593+
if !adopted && obj.ManagementInterface != nil {
15771594
mgtInterface := make(map[string]interface{})
15781595
mgtInterface["ip_assignment"], err = setPolicyIPAssignmentsInSchema(obj.ManagementInterface.IpAssignmentSpecs)
15791596
if err != nil {
@@ -1687,7 +1704,18 @@ func resourceNsxtPolicyEdgeTransportNodeUpdate(d *schema.ResourceData, m interfa
16871704
}
16881705

16891706
log.Printf("[INFO] Updating PolicyEdgeTransportNode with ID %s", id)
1690-
err = policyEdgeTransportNodePatch(siteID, epID, id, d, m)
1707+
if d.Get("node_id").(string) != "" {
1708+
// This node was adopted via node_id: management_interface, credentials,
1709+
// form_factor, vm_deployment_config and advanced_configuration all
1710+
// conflict with node_id and are never present in config, so building
1711+
// the request body from config alone (policyEdgeTransportNodePatch)
1712+
// would send an empty management_interface, which NSX rejects as
1713+
// missing required fields. Use the same GET-then-merge patch Create
1714+
// uses for adoption instead.
1715+
err = policyEdgeTransportNodePredeployedPatch(siteID, epID, id, d, m)
1716+
} else {
1717+
err = policyEdgeTransportNodePatch(siteID, epID, id, d, m)
1718+
}
16911719
if err != nil {
16921720
return handleUpdateError("PolicyEdgeTransportNode", id, err)
16931721
}

0 commit comments

Comments
 (0)