diff --git a/nsxt/resource_nsxt_policy_host_transport_node_collection.go b/nsxt/resource_nsxt_policy_host_transport_node_collection.go index b7dfdcd9f..a96f82db4 100644 --- a/nsxt/resource_nsxt_policy_host_transport_node_collection.go +++ b/nsxt/resource_nsxt_policy_host_transport_node_collection.go @@ -6,14 +6,19 @@ package nsxt import ( "fmt" "log" + "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp/nsx/fabric/compute_collections" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/sites/enforcement_points" "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" ) +const removeOnDestroyDefault = false + func resourceNsxtPolicyHostTransportNodeCollection() *schema.Resource { return &schema.Resource{ Create: resourceNsxtPolicyHostTransportNodeCollectionCreate, @@ -89,6 +94,12 @@ func resourceNsxtPolicyHostTransportNodeCollection() *schema.Resource { Optional: true, Description: "Transport Node Profile Path", }, + "remove_nsx_on_destroy": { + Type: schema.TypeBool, + Optional: true, + Description: "Indicate whether NSX service should be removed from hypervisors during resource deletion", + Default: removeOnDestroyDefault, + }, }, } } @@ -115,7 +126,7 @@ func resourceNsxtPolicyHostTransportNodeCollectionExists(siteID, epID, id string return false, logAPIError("Error retrieving resource", err) } -func policyHostTransportNodeCollectionUpdate(siteID, epID, id string, applyProfileParam bool, d *schema.ResourceData, m interface{}) error { +func policyHostTransportNodeCollectionUpdate(siteID, epID, id string, setRevision, applyProfileParam bool, d *schema.ResourceData, m interface{}) error { connector := getPolicyConnector(m) displayName := d.Get("display_name").(string) @@ -154,6 +165,10 @@ func policyHostTransportNodeCollectionUpdate(siteID, epID, id string, applyProfi SubClusterConfig: subClusterConfigs, } + if setRevision { + revision := int64(d.Get("revision").(int)) + obj.Revision = &revision + } client := enforcement_points.NewTransportNodeCollectionsClient(connector) _, err := client.Update(siteID, epID, id, obj, &applyProfileParam, nil) @@ -186,7 +201,7 @@ func resourceNsxtPolicyHostTransportNodeCollectionCreate(d *schema.ResourceData, // Create the resource using PATCH log.Printf("[INFO] Creating HostTransportNodeCollection with ID %s under site %s enforcement point %s", id, siteID, epID) - err = policyHostTransportNodeCollectionUpdate(siteID, epID, id, true, d, m) + err = policyHostTransportNodeCollectionUpdate(siteID, epID, id, false, true, d, m) if err != nil { return handleCreateError("HostTransportNodeCollection", id, err) } @@ -250,7 +265,7 @@ func resourceNsxtPolicyHostTransportNodeCollectionUpdate(d *schema.ResourceData, } log.Printf("[INFO] Updating HostTransportNodeCollection with ID %s", id) - err = policyHostTransportNodeCollectionUpdate(siteID, epID, id, false, d, m) + err = policyHostTransportNodeCollectionUpdate(siteID, epID, id, true, false, d, m) if err != nil { return handleUpdateError("HostTransportNodeCollection", id, err) @@ -259,6 +274,29 @@ func resourceNsxtPolicyHostTransportNodeCollectionUpdate(d *schema.ResourceData, return resourceNsxtPolicyHostTransportNodeCollectionRead(d, m) } +func getComputeCollectionMemberStateConf(connector client.Connector, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{"notyet"}, + Target: []string{"success", "failed"}, + Refresh: func() (interface{}, string, error) { + client := compute_collections.NewMemberStatusClient(connector) + statuses, err := client.List(id) + if err != nil { + log.Printf("[DEBUG]: NSX Failed to retrieve compute collection member statuses: %v", err) + return nil, "failed", err + } + + if *statuses.ResultCount > 0 { + return nil, "notyet", nil + } + return nil, "success", nil + }, + Delay: time.Duration(5) * time.Second, + Timeout: time.Duration(5) * time.Second, + PollInterval: time.Duration(5) * time.Second, + } +} + func resourceNsxtPolicyHostTransportNodeCollectionDelete(d *schema.ResourceData, m interface{}) error { connector := getPolicyConnector(m) client := enforcement_points.NewTransportNodeCollectionsClient(connector) @@ -267,6 +305,22 @@ func resourceNsxtPolicyHostTransportNodeCollectionDelete(d *schema.ResourceData, return err } + removeNsxOnDestroy := d.Get("remove_nsx_on_destroy").(bool) + if removeNsxOnDestroy { + log.Printf("[INFO] Removing NSX from hosts associated with HostTransportNodeCollection with ID %s", id) + err = client.Removensx(siteID, epID, id) + if err != nil { + return handleDeleteError("HostTransportNodeCollection", id, err) + } + + // Busy-wait until removal is complete + ccId := d.Get("compute_collection_id").(string) + stateConf := getComputeCollectionMemberStateConf(connector, ccId) + _, err := stateConf.WaitForState() + if err != nil { + return fmt.Errorf("failed to remove NSX bits from hosts") + } + } log.Printf("[INFO] Deleting HostTransportNodeCollection with ID %s", id) err = client.Delete(siteID, epID, id) if err != nil { @@ -293,5 +347,7 @@ func resourceNsxtPolicyHostTransportNodeCollectionImporter(d *schema.ResourceDat return rd, err } d.Set("site_path", sitePath) + d.Set("remove_nsx_on_destroy", removeOnDestroyDefault) + return rd, nil } diff --git a/website/docs/r/policy_host_transport_node_collection.html.markdown b/website/docs/r/policy_host_transport_node_collection.html.markdown index 3838a0b3a..808e74cd4 100644 --- a/website/docs/r/policy_host_transport_node_collection.html.markdown +++ b/website/docs/r/policy_host_transport_node_collection.html.markdown @@ -44,6 +44,7 @@ The following arguments are supported: * `transport_node_profile_sub_config_name` - (Required) Name of the TransportNodeProfile sub configuration to be used. * `sub_cluster_id` - (Required) sub-cluster ID. * `transport_node_profile_path` - (Optional) Transport Node Profile Path. +* `remove_nsx_on_destroy` - (Optional) Upon deletion, uninstall NSX from Transport Node Collection member hosts. Default is false. ## Attributes Reference @@ -60,3 +61,4 @@ An existing policy Host Transport Node Collection can be [imported][docs-import] terraform import nsxt_policy_host_transport_node_collection.test POLICY_PATH The above command imports Policy Host Transport Node Collection named test with NSX policy path POLICY_PATH. +Note: `remove_nsx_on_destroy` will be set to default value upon import. To enforce the intent value, reapply the plan. \ No newline at end of file