From ad6ed410f7b22c920686e343cddb8dc4dfc3c541 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Tue, 11 Feb 2025 06:33:45 +0000 Subject: [PATCH 01/39] LCM config and inventory changes --- go.mod | 1 + go.sum | 3 + nutanix/config.go | 7 ++ nutanix/sdks/v4/lcm/lcm.go | 42 +++++++ nutanix/sdks/v4/lcm/lcm_structs.go | 11 ++ .../services/lcmv2/data_source_lcm_config.go | 114 ++++++++++++++++++ .../lcmv2/resource_lcm_inventory_v2.go | 54 +++++++++ .../lcmv2/resource_lcm_prechecks_v2.go | 100 +++++++++++++++ 8 files changed, 332 insertions(+) create mode 100644 nutanix/sdks/v4/lcm/lcm.go create mode 100644 nutanix/sdks/v4/lcm/lcm_structs.go create mode 100644 nutanix/services/lcmv2/data_source_lcm_config.go create mode 100644 nutanix/services/lcmv2/resource_lcm_inventory_v2.go create mode 100644 nutanix/services/lcmv2/resource_lcm_prechecks_v2.go diff --git a/go.mod b/go.mod index 1bf61b0e8..5ba550a67 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1 + github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1 github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4 v4.0.1 diff --git a/go.sum b/go.sum index f33583c3c..63caa49a4 100644 --- a/go.sum +++ b/go.sum @@ -303,6 +303,7 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -462,6 +463,8 @@ github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1 h1 github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1/go.mod h1:S07bx9/6uUbMOY/OUJsaIUdvZ/LDaE46Kx9VX7Pt7Ek= github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1 h1:zWbA2qtSJt0WsBcEhqqv6FQTSz8pIwBnHA5etaQg4qo= github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1/go.mod h1:+HvW0f4QGDRZ3/1jcXvF7xA/gQsvQc4XtZy6OUobaO4= +github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1 h1:3E60KZUGwt60gq271b/py6t6fUC6cFDZdo//+Oj/RZg= +github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1/go.mod h1:WUw8WEwQAIOTHJITcyEOrUpKyBoOygiMssbJdQxAETU= github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1 h1:9SC9PsLQjvkuo0MyL2HMDXQ/dQl1a57RDR4OS22so/U= github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1/go.mod h1:75Ro+aFIepNAkf2eWjFrFR7m+Ct36EVrD9n9pwAYBrc= github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.1 h1:2D2ZJd5Cn0fMeWYnTEHsR1Fcv2G1BSrOAl1fVURtfn4= diff --git a/nutanix/config.go b/nutanix/config.go index 03e5eb49a..f9ad9c0ac 100644 --- a/nutanix/config.go +++ b/nutanix/config.go @@ -12,6 +12,7 @@ import ( "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/clusters" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/dataprotection" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/iam" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/lcm" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/microseg" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/networking" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" @@ -111,6 +112,10 @@ func (c *Config) Client() (*Client, error) { if err != nil { return nil, err } + LcmClient, err := lcm.NewLcmClient(configCreds) + if err != nil { + return nil, err + } return &Client{ WaitTimeout: c.WaitTimeout, API: v3Client, @@ -126,6 +131,7 @@ func (c *Config) Client() (*Client, error) { VolumeAPI: volumeClient, DataProtectionAPI: dataprotectionClient, VmmAPI: vmmClient, + LcmAPI: LcmClient, }, nil } @@ -145,4 +151,5 @@ type Client struct { VolumeAPI *volumes.Client DataProtectionAPI *dataprotection.Client VmmAPI *vmm.Client + LcmAPI *lcm.Client } diff --git a/nutanix/sdks/v4/lcm/lcm.go b/nutanix/sdks/v4/lcm/lcm.go new file mode 100644 index 000000000..3743145b6 --- /dev/null +++ b/nutanix/sdks/v4/lcm/lcm.go @@ -0,0 +1,42 @@ +package lcm + +import ( + "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/api" + lcm "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/client" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/client" +) + +type Client struct { + LcmConfigAPIInstance *api.ConfigApi + LcmInventoryAPIInstance *api.InventoryApi + LcmPreChecksAPIInstance *api.PrecheckApi + LcmStatusAPIInstance *api.StatusApi + LcmEntitiesAPIInstance *api.EntityApi +} + +func NewLcmClient(credentials client.Credentials) (*Client, error) { + var baseClient *lcm.ApiClient + + // check if all required fields are present. Else create an empty client + if credentials.Username != "" && credentials.Password != "" && credentials.Endpoint != "" { + pcClient := lcm.NewApiClient() + + pcClient.Host = credentials.Endpoint + pcClient.Password = credentials.Password + pcClient.Username = credentials.Username + pcClient.Port = 9440 + pcClient.VerifySSL = false + + baseClient = pcClient + } + + f := &Client{ + LcmInventoryAPIInstance: api.NewInventoryApi(baseClient), + LcmConfigAPIInstance: api.NewConfigApi(baseClient), + LcmPreChecksAPIInstance: api.NewPrecheckApi(baseClient), + LcmStatusAPIInstance: api.NewStatusApi(baseClient), + LcmEntitiesAPIInstance: api.NewEntityApi(baseClient), + } + + return f, nil +} diff --git a/nutanix/sdks/v4/lcm/lcm_structs.go b/nutanix/sdks/v4/lcm/lcm_structs.go new file mode 100644 index 000000000..763b5f9cd --- /dev/null +++ b/nutanix/sdks/v4/lcm/lcm_structs.go @@ -0,0 +1,11 @@ +type struct { + Mode *string `json:"mode,omitempty"` + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` + TimeUnit *string `json:"timeUnit,omitempty"` + TimeUnitNumber *string `json:"timeUnitNumber,omitempty"` + DatabaseIds []*string `json:"databaseIds,omitempty"` + Snapshots *ListSnapshots `json:"snapshots,omitempty"` + ContinuousRegion *ContinuousRegion `json:"continuousRegion,omitempty"` + DatabasesContinuousRegion interface{} `json:"databasesContinuousRegion,omitempty"` +} \ No newline at end of file diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go new file mode 100644 index 000000000..1f2b9fd0b --- /dev/null +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -0,0 +1,114 @@ +package lcmv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/resources" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" +) + +func DatasourceLcmConfig() *schema.Resource { + return &schema.Resource{ + ReadContext: DatasourceLcmConfigRead, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Optional: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "url": { + Type: schema.TypeString, + Computed: true, + }, + "is_auto_inventory_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "auto_inventory_schedule": { + Type: schema.TypeString, + Computed: true, + }, + "version": { + Type: schema.TypeString, + Computed: true, + }, + "display_version": { + Type: schema.TypeString, + Computed: true, + }, + "connectivity_type": { + Type: schema.TypeString, + Computed: true, + }, + "is_https_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "supported_software_entities": { + Type: schema.TypeList, + Computed: true, + }, + "deprecated_software_entities": { + Type: schema.TypeList, + Computed: true, + }, + "is_framework_bundle_uploaded": { + Type: schema.TypeBool, + Computed: true, + }, + "has_module_auto_upgrade_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + }, + } +} + +func DatasourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + + args := make(map[string]interface{}) + args["X-Cluster-Id"] = clusterId + + resp, err := conn.LcmConfigAPIInstance.GetConfig(args) + if err != nil { + return diag.Errorf("error while fetching the Lcm config : %v", err) + } + + lcmConfig := resp.Data.GetValue().(lcmconfigimport1.LcmConfig) + if err := d.Set("is_auto_inventory_enabled", lcmConfig.AutoInventoryEnabled); err != nil { + return diag.FromErr(err) + }, + + return +} + +func schemaForLinks() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rel": { + Type: schema.TypeString, + Computed: true, + }, + "href": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + } +} diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go new file mode 100644 index 000000000..5705d9921 --- /dev/null +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -0,0 +1,54 @@ +package lcmv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" + lcmInventoryResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" +) + +func ResourceLcmInventoryV2() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ntnx_request_id": { + Type: schema.TypeString, + Required: true, + }, + "x_cluster_id": { + Type: schema.TypeString, + Optional: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + ntnxRequestId, ok := d.Get("ntnx_request_id").(string) + if !ok || ntnxRequestId == "" { + return diag.Errorf("ntnx_request_id is required and cannot be null or empty") + } + + args := make(map[string]interface{}) + args["X-Cluster-Id"] = clusterId + args["NTNX-Request-Id"] = ntnxRequestId + + resp, err := conn.LcmInventoryAPIInstance.Inventory(args) + if err != nil { + return diag.Errorf("error while performing the inventory: %v", err) + } + getResp := resp.Data.GetValue().(lcmInventoryResp.InventoryApiResponse) + TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + d.Set("ext_id", taskUUID) + return nil +} diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go new file mode 100644 index 000000000..ab0c06951 --- /dev/null +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -0,0 +1,100 @@ +package lcmv2 + +import ( + "container/list" + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" + preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/common" + lcmPreCheckResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" +) + +func ResourcePreChecksV2() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ntnx_request_id": { + Type: schema.TypeString, + Required: true, + }, + "x_cluster_id": { + Type: schema.TypeString, + Optional: true, + }, + "management_server": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hypervisor_type": { + Type: schema.TypeString, + Required: true, + }, + "ip": { + Type: schema.TypeString, + Required: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + }, + "password": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "entity_update_specs": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "entity_uuid": { + Type: schema.TypeString, + Required: true, + }, + "to_version": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Required: true, + }, + "skipped_precheck_flags": { + Type: schema.TypeList, + Optional: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + ntnxRequestId, ok := d.Get("ntnx_request_id").(string) + if !ok || ntnxRequestId == "" { + return diag.Errorf("ntnx_request_id is required and cannot be null or empty") + } + + args := make(map[string]interface{}) + args["X-Cluster-Id"] = clusterId + args["NTNX-Request-Id"] = ntnxRequestId + + resp, err := conn.LcmPreChecksAPIInstance.Precheck(body, args) + if err != nil { + return diag.Errorf("error while performing the inventory: %v", err) + } + getResp := resp.Data.GetValue().(lcmPreCheckResp.PrecheckApiResponse) + TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + d.Set("ext_id", taskUUID) + return nil +} From 0caf8846b6b6e615c214e637bb8473ce28b3b2b2 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 17 Feb 2025 04:33:38 +0000 Subject: [PATCH 02/39] LCM config and inventory changes --- nutanix/sdks/v4/lcm/lcm_structs.go | 11 --- .../lcmv2/resource_lcm_inventory_v2.go | 63 ++++++++++++++++- .../lcmv2/resource_lcm_prechecks_v2.go | 70 +++++++++++++++++-- 3 files changed, 128 insertions(+), 16 deletions(-) delete mode 100644 nutanix/sdks/v4/lcm/lcm_structs.go diff --git a/nutanix/sdks/v4/lcm/lcm_structs.go b/nutanix/sdks/v4/lcm/lcm_structs.go deleted file mode 100644 index 763b5f9cd..000000000 --- a/nutanix/sdks/v4/lcm/lcm_structs.go +++ /dev/null @@ -1,11 +0,0 @@ -type struct { - Mode *string `json:"mode,omitempty"` - From *string `json:"from,omitempty"` - To *string `json:"to,omitempty"` - TimeUnit *string `json:"timeUnit,omitempty"` - TimeUnitNumber *string `json:"timeUnitNumber,omitempty"` - DatabaseIds []*string `json:"databaseIds,omitempty"` - Snapshots *ListSnapshots `json:"snapshots,omitempty"` - ContinuousRegion *ContinuousRegion `json:"continuousRegion,omitempty"` - DatabasesContinuousRegion interface{} `json:"databasesContinuousRegion,omitempty"` -} \ No newline at end of file diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index 5705d9921..25a876ffb 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -2,12 +2,17 @@ package lcmv2 import ( "context" + "fmt" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" lcmInventoryResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" + import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" + "github.com/terraform-providers/terraform-provider-nutanix/utils" ) func ResourceLcmInventoryV2() *schema.Resource { @@ -49,6 +54,62 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId - d.Set("ext_id", taskUUID) + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + // Wait for the inventorty to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroupFunc(ctx, taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("Perform inventory task failed: %s", errWaitTask) + } return nil } + +func taskStateRefreshPrismTaskGroupFunc(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + // data := base64.StdEncoding.EncodeToString([]byte("ergon")) + // encodeUUID := data + ":" + taskUUID + vresp, err := client.TaskRefAPI.GetTaskById(utils.StringPtr(taskUUID), nil) + if err != nil { + return "", "", (fmt.Errorf("error while polling prism task: %v", err)) + } + + // get the group results + + v := vresp.Data.GetValue().(import1.Task) + + if getTaskStatus(v.Status) == "CANCELED" || getTaskStatus(v.Status) == "FAILED" { + return v, getTaskStatus(v.Status), + fmt.Errorf("error_detail: %s, progress_message: %d", utils.StringValue(v.ErrorMessages[0].Message), utils.IntValue(v.ProgressPercentage)) + } + return v, getTaskStatus(v.Status), nil + } +} + +func getTaskStatus(pr *import1.TaskStatus) string { + const two, three, five, six, seven = 2, 3, 5, 6, 7 + if pr != nil { + if *pr == import1.TaskStatus(six) { + return "FAILED" + } + if *pr == import1.TaskStatus(seven) { + return "CANCELED" + } + if *pr == import1.TaskStatus(two) { + return "QUEUED" + } + if *pr == import1.TaskStatus(three) { + return "RUNNING" + } + if *pr == import1.TaskStatus(five) { + return "SUCCEEDED" + } + } + return "UNKNOWN" +} diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go index ab0c06951..6c6ae74a2 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -1,15 +1,19 @@ package lcmv2 import ( - "container/list" "context" + "fmt" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/common" lcmPreCheckResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" + import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" + "github.com/terraform-providers/terraform-provider-nutanix/utils" ) func ResourcePreChecksV2() *schema.Resource { @@ -86,15 +90,73 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in args := make(map[string]interface{}) args["X-Cluster-Id"] = clusterId args["NTNX-Request-Id"] = ntnxRequestId + body := preCheckConfig.PrecheckSpec{} - resp, err := conn.LcmPreChecksAPIInstance.Precheck(body, args) + resp, err := conn.LcmPreChecksAPIInstance.Precheck(&body, args) if err != nil { - return diag.Errorf("error while performing the inventory: %v", err) + return diag.Errorf("error while performing the prechecs: %v", err) } getResp := resp.Data.GetValue().(lcmPreCheckResp.PrecheckApiResponse) TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId - d.Set("ext_id", taskUUID) + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + // Wait for the inventorty to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroupFun(ctx, taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("Prechecks task failed: %s", errWaitTask) + } return nil + +} + +func taskStateRefreshPrismTaskGroupFun(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + // data := base64.StdEncoding.EncodeToString([]byte("ergon")) + // encodeUUID := data + ":" + taskUUID + vresp, err := client.TaskRefAPI.GetTaskById(utils.StringPtr(taskUUID), nil) + if err != nil { + return "", "", (fmt.Errorf("error while polling prism task: %v", err)) + } + + // get the group results + + v := vresp.Data.GetValue().(import1.Task) + + if getTaskStat(v.Status) == "CANCELED" || getTaskStat(v.Status) == "FAILED" { + return v, getTaskStat(v.Status), + fmt.Errorf("error_detail: %s, progress_message: %d", utils.StringValue(v.ErrorMessages[0].Message), utils.IntValue(v.ProgressPercentage)) + } + return v, getTaskStat(v.Status), nil + } +} + +func getTaskStat(pr *import1.TaskStatus) string { + const two, three, five, six, seven = 2, 3, 5, 6, 7 + if pr != nil { + if *pr == import1.TaskStatus(six) { + return "FAILED" + } + if *pr == import1.TaskStatus(seven) { + return "CANCELED" + } + if *pr == import1.TaskStatus(two) { + return "QUEUED" + } + if *pr == import1.TaskStatus(three) { + return "RUNNING" + } + if *pr == import1.TaskStatus(five) { + return "SUCCEEDED" + } + } + return "UNKNOWN" } From 3664b9bd70dece88ef6691b19d4b78339f44cd44 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 17 Feb 2025 13:15:02 +0530 Subject: [PATCH 03/39] utilise lifecycle client --- go.mod | 2 +- go.sum | 5 +- nutanix/sdks/v4/lcm/lcm.go | 14 +- .../services/lcmv2/data_source_lcm_config.go | 47 ++++- .../lcmv2/data_source_lcm_status_v2.go | 160 ++++++++++++++++++ .../lcmv2/resource_lcm_inventory_v2.go | 8 +- .../lcmv2/resource_lcm_prechecks_v2.go | 59 +------ 7 files changed, 221 insertions(+), 74 deletions(-) create mode 100644 nutanix/services/lcmv2/data_source_lcm_status_v2.go diff --git a/go.mod b/go.mod index 5ba550a67..4f50692d8 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1 - github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1 + github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.1 github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4 v4.0.1 diff --git a/go.sum b/go.sum index 63caa49a4..e291bc8e8 100644 --- a/go.sum +++ b/go.sum @@ -303,7 +303,6 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= github.com/hashicorp/go-plugin v1.4.1 h1:6UltRQlLN9iZO513VveELp5xyaFxVD2+1OVylE+2E+w= github.com/hashicorp/go-plugin v1.4.1/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= -github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -463,8 +462,8 @@ github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1 h1 github.com/nutanix/ntnx-api-golang-clients/dataprotection-go-client/v4 v4.0.1/go.mod h1:S07bx9/6uUbMOY/OUJsaIUdvZ/LDaE46Kx9VX7Pt7Ek= github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1 h1:zWbA2qtSJt0WsBcEhqqv6FQTSz8pIwBnHA5etaQg4qo= github.com/nutanix/ntnx-api-golang-clients/iam-go-client/v4 v4.0.1/go.mod h1:+HvW0f4QGDRZ3/1jcXvF7xA/gQsvQc4XtZy6OUobaO4= -github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1 h1:3E60KZUGwt60gq271b/py6t6fUC6cFDZdo//+Oj/RZg= -github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4 v4.0.1-alpha.1/go.mod h1:WUw8WEwQAIOTHJITcyEOrUpKyBoOygiMssbJdQxAETU= +github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4 v4.0.1 h1:JBSalV1dvI+5YjZzzE9E/tz8V4A7CbSA7wl4C3L8iYs= +github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4 v4.0.1/go.mod h1:fQTNQlfh5g4SavaQn+sDoMn29K+Lur5lHWtnbq3uA28= github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1 h1:9SC9PsLQjvkuo0MyL2HMDXQ/dQl1a57RDR4OS22so/U= github.com/nutanix/ntnx-api-golang-clients/microseg-go-client/v4 v4.0.1/go.mod h1:75Ro+aFIepNAkf2eWjFrFR7m+Ct36EVrD9n9pwAYBrc= github.com/nutanix/ntnx-api-golang-clients/networking-go-client/v4 v4.0.1 h1:2D2ZJd5Cn0fMeWYnTEHsR1Fcv2G1BSrOAl1fVURtfn4= diff --git a/nutanix/sdks/v4/lcm/lcm.go b/nutanix/sdks/v4/lcm/lcm.go index 3743145b6..b6ec2c633 100644 --- a/nutanix/sdks/v4/lcm/lcm.go +++ b/nutanix/sdks/v4/lcm/lcm.go @@ -1,17 +1,18 @@ package lcm import ( - "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/api" - lcm "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/client" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/api" + lcm "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/client" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/client" ) type Client struct { LcmConfigAPIInstance *api.ConfigApi LcmInventoryAPIInstance *api.InventoryApi - LcmPreChecksAPIInstance *api.PrecheckApi + LcmPreChecksAPIInstance *api.PrechecksApi LcmStatusAPIInstance *api.StatusApi - LcmEntitiesAPIInstance *api.EntityApi + LcmEntitiesAPIInstance *api.EntitiesApi + LcmUpgradeAPIInstance *api.UpgradesApi } func NewLcmClient(credentials client.Credentials) (*Client, error) { @@ -33,9 +34,10 @@ func NewLcmClient(credentials client.Credentials) (*Client, error) { f := &Client{ LcmInventoryAPIInstance: api.NewInventoryApi(baseClient), LcmConfigAPIInstance: api.NewConfigApi(baseClient), - LcmPreChecksAPIInstance: api.NewPrecheckApi(baseClient), + LcmPreChecksAPIInstance: api.NewPrechecksApi(baseClient), LcmStatusAPIInstance: api.NewStatusApi(baseClient), - LcmEntitiesAPIInstance: api.NewEntityApi(baseClient), + LcmEntitiesAPIInstance: api.NewEntitiesApi(baseClient), + LcmUpgradeAPIInstance: api.NewUpgradesApi(baseClient), } return f, nil diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go index 1f2b9fd0b..1347f8040 100644 --- a/nutanix/services/lcmv2/data_source_lcm_config.go +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/resources" + lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" ) @@ -81,17 +81,50 @@ func DatasourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta i args := make(map[string]interface{}) args["X-Cluster-Id"] = clusterId - resp, err := conn.LcmConfigAPIInstance.GetConfig(args) + resp, err := conn.LcmConfigAPIInstance.GetConfig(&clusterId, args) if err != nil { return diag.Errorf("error while fetching the Lcm config : %v", err) } - lcmConfig := resp.Data.GetValue().(lcmconfigimport1.LcmConfig) - if err := d.Set("is_auto_inventory_enabled", lcmConfig.AutoInventoryEnabled); err != nil { + lcmConfig := resp.Data.GetValue().(lcmconfigimport1.Config) + if err := d.Set("tenant_id", lcmConfig.TenantId); err != nil { return diag.FromErr(err) - }, - - return + } + if err := d.Set("links", flattenLinks(lcmConfig.Links)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_auto_inventory_enabled", lcmConfig.IsAutoInventoryEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("auto_inventory_schedule", lcmConfig.AutoInventorySchedule); err != nil { + return diag.FromErr(err) + } + if err := d.Set("version", lcmConfig.Version); err != nil { + return diag.FromErr(err) + } + if err := d.Set("display_version", lcmConfig.DisplayVersion); err != nil { + return diag.FromErr(err) + } + if err := d.Set("connectivity_type", lcmConfig.ConnectivityType); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_https_enabled", lcmConfig.IsHttpsEnabled); err != nil { + return diag.FromErr(err) + } + // if err := d.Set("supported_software_entities", flattenSoftwareEntities(lcmConfig.SupportedSoftwareEntities)); err != nil { + // return diag.FromErr(err) + // } + // if err := d.Set("deprecated_software_entities", flattenSoftwareEntities(lcmConfig.DeprecatedSoftwareEntities)); err != nil { + // return diag.FromErr(err) + // } + if err := d.Set("is_framework_bundle_uploaded", lcmConfig.IsFrameworkBundleUploaded); err != nil { + return diag.FromErr(err) + } + if err := d.Set("has_module_auto_upgrade_enabled", lcmConfig.HasModuleAutoUpgradeEnabled); err != nil { + return diag.FromErr(err) + } + d.SetId(*lcmConfig.ExtId) + return nil } func schemaForLinks() *schema.Schema { diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go new file mode 100644 index 000000000..95155e52b --- /dev/null +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -0,0 +1,160 @@ +package lcmv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + import2 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/common/v1/response" + lcmstatusimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" +) + +func DatasourceLcmStatus() *schema.Resource { + return &schema.Resource{ + ReadContext: DatasourceLcmStatusRead, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Optional: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "framework_version": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "current_version": { + Type: schema.TypeString, + Computed: true, + }, + "available_version": { + Type: schema.TypeString, + Computed: true, + }, + "is_update_needed": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + "in_progress_operation": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operation_type": { + Type: schema.TypeString, + Computed: true, + }, + "operation_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_cancel_intent_set": { + Type: schema.TypeBool, + Computed: true, + }, + "upload_task_uuid": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func DatasourceLcmStatusRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + + args := make(map[string]interface{}) + args["X-Cluster-Id"] = clusterId + + resp, err := conn.LcmStatusAPIInstance.GetStatus(&clusterId, args) + if err != nil { + return diag.Errorf("error while fetching the Lcm status : %v", err) + } + + lcmStatusResp := resp.Data.GetValue().(lcmstatusimport1.StatusInfo) + if err := d.Set("tenant_id", lcmStatusResp.TenantId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("links", flattenLinks(lcmStatusResp.Links)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_cancel_intent_set", lcmStatusResp.IsCancelIntentSet); err != nil { + return diag.FromErr(err) + } + if err := d.Set("framework_version", flattenFrameworkVersion(lcmStatusResp.FrameworkVersion)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("in_progress_operation", flattenInProgressOperation(lcmStatusResp.InProgressOperation)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("upload_task_uuid", lcmStatusResp.UploadTaskUuid); err != nil { + return diag.FromErr(err) + } + d.SetId(*lcmStatusResp.ExtId) + return nil +} + +func flattenFrameworkVersion(pr *lcmstatusimport1.FrameworkVersionInfo) []map[string]interface{} { + if pr != nil { + frameworVersionRef := make([]map[string]interface{}, 0) + frameworkVersion := make(map[string]interface{}) + + frameworkVersion["current_version"] = pr.CurrentVersion + frameworkVersion["available_version"] = pr.AvailableVersion + frameworkVersion["is_update_needed"] = pr.IsUpdateNeeded + + frameworVersionRef = append(frameworVersionRef, frameworkVersion) + return frameworVersionRef + } + return nil +} + +func flattenInProgressOperation(pr *lcmstatusimport1.InProgressOpInfo) []map[string]interface{} { + if pr != nil { + OperationRef := make([]map[string]interface{}, 0) + Operation := make(map[string]interface{}) + + Operation["operation_type"] = pr.OperationType + Operation["operation_id"] = pr.OperationId + + OperationRef = append(OperationRef, Operation) + return OperationRef + } + return nil +} + +func flattenLinks(pr []import2.ApiLink) []map[string]interface{} { + if len(pr) > 0 { + linkList := make([]map[string]interface{}, len(pr)) + + for k, v := range pr { + links := map[string]interface{}{} + if v.Href != nil { + links["href"] = v.Href + } + if v.Rel != nil { + links["rel"] = v.Rel + } + + linkList[k] = links + } + return linkList + } + return nil +} diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index 25a876ffb..cc1f8cdc4 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" - lcmInventoryResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" + lcmInventoryResp "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/operations" import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" @@ -46,7 +46,7 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, args["X-Cluster-Id"] = clusterId args["NTNX-Request-Id"] = ntnxRequestId - resp, err := conn.LcmInventoryAPIInstance.Inventory(args) + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(&clusterId, args) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) } @@ -61,7 +61,7 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, stateConf := &resource.StateChangeConf{ Pending: []string{"QUEUED", "RUNNING", "PENDING"}, Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroupFunc(ctx, taskconn, utils.StringValue(taskUUID)), + Refresh: taskStateRefreshPrismTaskGroup(ctx, taskconn, utils.StringValue(taskUUID)), Timeout: d.Timeout(schema.TimeoutCreate), } @@ -71,7 +71,7 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, return nil } -func taskStateRefreshPrismTaskGroupFunc(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { +func taskStateRefreshPrismTaskGroup(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { // data := base64.StdEncoding.EncodeToString([]byte("ergon")) // encodeUUID := data + ":" + taskUUID diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go index 6c6ae74a2..b76a431ed 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -2,17 +2,14 @@ package lcmv2 import ( "context" - "fmt" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" - preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/common" - lcmPreCheckResp "github.com/nutanix/ntnx-api-golang-clients/lcm-go-client/v4/models/lcm/v4/operations" - import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" + preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" + lcmPreCheckResp "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/operations" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" - "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) @@ -90,13 +87,13 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in args := make(map[string]interface{}) args["X-Cluster-Id"] = clusterId args["NTNX-Request-Id"] = ntnxRequestId - body := preCheckConfig.PrecheckSpec{} + body := preCheckConfig.PrechecksSpec{} - resp, err := conn.LcmPreChecksAPIInstance.Precheck(&body, args) + resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(&body, &clusterId, args) if err != nil { return diag.Errorf("error while performing the prechecs: %v", err) } - getResp := resp.Data.GetValue().(lcmPreCheckResp.PrecheckApiResponse) + getResp := resp.Data.GetValue().(lcmPreCheckResp.PrechecksApiResponse) TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId @@ -107,7 +104,7 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in stateConf := &resource.StateChangeConf{ Pending: []string{"QUEUED", "RUNNING", "PENDING"}, Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroupFun(ctx, taskconn, utils.StringValue(taskUUID)), + Refresh: taskStateRefreshPrismTaskGroup(ctx, taskconn, utils.StringValue(taskUUID)), Timeout: d.Timeout(schema.TimeoutCreate), } @@ -115,48 +112,4 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in return diag.Errorf("Prechecks task failed: %s", errWaitTask) } return nil - -} - -func taskStateRefreshPrismTaskGroupFun(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - // data := base64.StdEncoding.EncodeToString([]byte("ergon")) - // encodeUUID := data + ":" + taskUUID - vresp, err := client.TaskRefAPI.GetTaskById(utils.StringPtr(taskUUID), nil) - if err != nil { - return "", "", (fmt.Errorf("error while polling prism task: %v", err)) - } - - // get the group results - - v := vresp.Data.GetValue().(import1.Task) - - if getTaskStat(v.Status) == "CANCELED" || getTaskStat(v.Status) == "FAILED" { - return v, getTaskStat(v.Status), - fmt.Errorf("error_detail: %s, progress_message: %d", utils.StringValue(v.ErrorMessages[0].Message), utils.IntValue(v.ProgressPercentage)) - } - return v, getTaskStat(v.Status), nil - } -} - -func getTaskStat(pr *import1.TaskStatus) string { - const two, three, five, six, seven = 2, 3, 5, 6, 7 - if pr != nil { - if *pr == import1.TaskStatus(six) { - return "FAILED" - } - if *pr == import1.TaskStatus(seven) { - return "CANCELED" - } - if *pr == import1.TaskStatus(two) { - return "QUEUED" - } - if *pr == import1.TaskStatus(three) { - return "RUNNING" - } - if *pr == import1.TaskStatus(five) { - return "SUCCEEDED" - } - } - return "UNKNOWN" } From 6a54cb87e87fb775398579da4ddd06fc4dd9d8c3 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 17 Feb 2025 16:02:55 +0530 Subject: [PATCH 04/39] Add LCM config update chanegs --- nutanix/sdks/v4/lcm/lcm.go | 1 - .../lcmv2/resource_lcm_inventory_v2.go | 4 +- .../lcmv2/resource_lcm_prechecks_v2.go | 5 +- ...nfig.go => resource_nutanix_lcm_config.go} | 60 ++++++++++++++++++- 4 files changed, 63 insertions(+), 7 deletions(-) rename nutanix/services/lcmv2/{data_source_lcm_config.go => resource_nutanix_lcm_config.go} (65%) diff --git a/nutanix/sdks/v4/lcm/lcm.go b/nutanix/sdks/v4/lcm/lcm.go index b6ec2c633..3639add71 100644 --- a/nutanix/sdks/v4/lcm/lcm.go +++ b/nutanix/sdks/v4/lcm/lcm.go @@ -39,6 +39,5 @@ func NewLcmClient(credentials client.Credentials) (*Client, error) { LcmEntitiesAPIInstance: api.NewEntitiesApi(baseClient), LcmUpgradeAPIInstance: api.NewUpgradesApi(baseClient), } - return f, nil } diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index cc1f8cdc4..db82ae3db 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -61,7 +61,7 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, stateConf := &resource.StateChangeConf{ Pending: []string{"QUEUED", "RUNNING", "PENDING"}, Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroup(ctx, taskconn, utils.StringValue(taskUUID)), + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), Timeout: d.Timeout(schema.TimeoutCreate), } @@ -71,7 +71,7 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, return nil } -func taskStateRefreshPrismTaskGroup(ctx context.Context, client *prism.Client, taskUUID string) resource.StateRefreshFunc { +func taskStateRefreshPrismTaskGroup(client *prism.Client, taskUUID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { // data := base64.StdEncoding.EncodeToString([]byte("ergon")) // encodeUUID := data + ":" + taskUUID diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go index b76a431ed..8afa2c830 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -100,11 +100,12 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in // calling group API to poll for completion of task taskconn := meta.(*conns.Client).PrismAPI - // Wait for the inventorty to be successful + + // Wait for the PreChecks to be successful stateConf := &resource.StateChangeConf{ Pending: []string{"QUEUED", "RUNNING", "PENDING"}, Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroup(ctx, taskconn, utils.StringValue(taskUUID)), + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), Timeout: d.Timeout(schema.TimeoutCreate), } diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go similarity index 65% rename from nutanix/services/lcmv2/data_source_lcm_config.go rename to nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 1347f8040..fca241b76 100644 --- a/nutanix/services/lcmv2/data_source_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -4,15 +4,27 @@ import ( "context" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" ) func DatasourceLcmConfig() *schema.Resource { return &schema.Resource{ - ReadContext: DatasourceLcmConfigRead, + ReadContext: ResourceLcmConfigRead, + UpdateContext: ResourceLcmConfigUpdate, Schema: map[string]*schema.Schema{ + "ntnx_request_id": { + Type: schema.TypeString, + Required: true, + }, + "if_match": { + Type: schema.TypeString, + Required: true, + }, "x_cluster_id": { Type: schema.TypeString, Optional: true, @@ -74,7 +86,51 @@ func DatasourceLcmConfig() *schema.Resource { } } -func DatasourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceLcmConfigUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + ntnxRequestId, ok := d.Get("ntnx_request_id").(string) + if !ok || ntnxRequestId == "" { + return diag.Errorf("ntnx_request_id is required and cannot be null or empty") + } + if_match, ok := d.Get("if_match").(string) + if !ok || if_match == "" { + return diag.Errorf("if_match is required and cannot be null or empty") + } + + args := make(map[string]interface{}) + args["X-Cluster-Id"] = clusterId + + body := lcmconfigimport1.Config{} + + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, &clusterId, args) + if err != nil { + return diag.Errorf("error while updating the LCM config: %v", err) + } + + getResp := resp.Data.GetValue().(lcmconfigimport1.UpdateConfigApiResponse) + TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + + taskconn := meta.(*conns.Client).PrismAPI + + // Wait for the Config Update to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("Config Update task failed: %s", errWaitTask) + } + return ResourceLcmConfigRead(ctx, d, meta) +} + +func ResourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) From 2e38b7e2e8926b0258a36dce5abb1b10e41915d3 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Tue, 18 Feb 2025 15:29:59 +0530 Subject: [PATCH 05/39] Changes for lcm --- nutanix/provider/provider.go | 3 +++ .../lcmv2/data_source_lcm_status_v2.go | 6 ++--- .../lcmv2/resource_lcm_inventory_v2.go | 24 ++++++++++++++----- .../lcmv2/resource_nutanix_lcm_config.go | 22 ++++++++++++----- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 68b1fbd6f..99e341980 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -17,6 +17,7 @@ import ( foundationCentral "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/foundationCentral" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/iam" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/iamv2" + "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/lcmv2" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/ndb" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/networking" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/services/networkingv2" @@ -289,6 +290,7 @@ func Provider() *schema.Provider { "nutanix_clusters_v2": clustersv2.DatasourceNutanixClusterEntitiesV2(), "nutanix_host_v2": clustersv2.DatasourceNutanixHostEntityV2(), "nutanix_hosts_v2": clustersv2.DatasourceNutanixHostEntitiesV2(), + "nutanix_lcm_status_v2": lcmv2.DatasourceNutanixLcmStatusV2(), }, ResourcesMap: map[string]*schema.Resource{ "nutanix_virtual_machine": vmm.ResourceNutanixVirtualMachine(), @@ -385,6 +387,7 @@ func Provider() *schema.Provider { "nutanix_pc_registration_v2": clustersv2.ResourceNutanixClusterPCRegistrationV2(), "nutanix_clusters_discover_unconfigured_nodes_v2": clustersv2.ResourceNutanixClusterDiscoverUnconfiguredNodesV2(), "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), + "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go index 95155e52b..589570ddc 100644 --- a/nutanix/services/lcmv2/data_source_lcm_status_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -10,9 +10,9 @@ import ( conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" ) -func DatasourceLcmStatus() *schema.Resource { +func DatasourceNutanixLcmStatusV2() *schema.Resource { return &schema.Resource{ - ReadContext: DatasourceLcmStatusRead, + ReadContext: DatasourceNutanixLcmStatusV2Create, Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, @@ -75,7 +75,7 @@ func DatasourceLcmStatus() *schema.Resource { } } -func DatasourceLcmStatusRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func DatasourceNutanixLcmStatusV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index db82ae3db..44352c172 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -15,13 +15,13 @@ import ( "github.com/terraform-providers/terraform-provider-nutanix/utils" ) -func ResourceLcmInventoryV2() *schema.Resource { +func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { return &schema.Resource{ + CreateContext: ResourceNutanixLcmPerformInventoryV2Create, + ReadContext: ResourceNutainxLcmPerformInventoryV2Read, + UpdateContext: ResourceNutanixLcmPerformInventoryV2Update, + DeleteContext: ResourceNutanixLcmPerformInventoryV2Delete, Schema: map[string]*schema.Schema{ - "ntnx_request_id": { - Type: schema.TypeString, - Required: true, - }, "x_cluster_id": { Type: schema.TypeString, Optional: true, @@ -34,7 +34,7 @@ func ResourceLcmInventoryV2() *schema.Resource { } } -func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) ntnxRequestId, ok := d.Get("ntnx_request_id").(string) @@ -71,6 +71,18 @@ func ResourceLcmPerformInventoryV2(ctx context.Context, d *schema.ResourceData, return nil } +func ResourceNutainxLcmPerformInventoryV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return ResourceNutanixLcmPerformInventoryV2Create(ctx, d, meta) +} + +func ResourceNutanixLcmPerformInventoryV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourceNutanixLcmPerformInventoryV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + func taskStateRefreshPrismTaskGroup(client *prism.Client, taskUUID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { // data := base64.StdEncoding.EncodeToString([]byte("ergon")) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index fca241b76..980201216 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -12,10 +12,12 @@ import ( "github.com/terraform-providers/terraform-provider-nutanix/utils" ) -func DatasourceLcmConfig() *schema.Resource { +func ResourceLcmConfigV2() *schema.Resource { return &schema.Resource{ - ReadContext: ResourceLcmConfigRead, - UpdateContext: ResourceLcmConfigUpdate, + CreateContext: ResourceLcmConfigV2Create, + ReadContext: ResourceLcmConfigV2Read, + UpdateContext: ResourceLcmConfigV2Update, + DeleteContext: ResourceLcmConfigV2Delete, Schema: map[string]*schema.Schema{ "ntnx_request_id": { Type: schema.TypeString, @@ -86,7 +88,7 @@ func DatasourceLcmConfig() *schema.Resource { } } -func ResourceLcmConfigUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) ntnxRequestId, ok := d.Get("ntnx_request_id").(string) @@ -127,10 +129,10 @@ func ResourceLcmConfigUpdate(ctx context.Context, d *schema.ResourceData, meta i if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Config Update task failed: %s", errWaitTask) } - return ResourceLcmConfigRead(ctx, d, meta) + return ResourceLcmConfigV2Read(ctx, d, meta) } -func ResourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceLcmConfigV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) @@ -183,6 +185,14 @@ func ResourceLcmConfigRead(ctx context.Context, d *schema.ResourceData, meta int return nil } +func ResourceLcmConfigV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return ResourceLcmConfigV2Create(ctx, d, meta) +} + +func ResourceLcmConfigV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + func schemaForLinks() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, From 18bff9a2687960be13edd1e6152f0ac1d79833c0 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 18:36:06 +0200 Subject: [PATCH 06/39] implement data sources for get LCM entity and list LCM entities --- nutanix/provider/provider.go | 2 + .../lcmv2/data_source_lcm_entities_v2.go | 127 ++++ .../lcmv2/data_source_lcm_entitiy_v2.go | 549 ++++++++++++++++++ 3 files changed, 678 insertions(+) create mode 100644 nutanix/services/lcmv2/data_source_lcm_entities_v2.go create mode 100644 nutanix/services/lcmv2/data_source_lcm_entitiy_v2.go diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 99e341980..6fb311c00 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -291,6 +291,8 @@ func Provider() *schema.Provider { "nutanix_host_v2": clustersv2.DatasourceNutanixHostEntityV2(), "nutanix_hosts_v2": clustersv2.DatasourceNutanixHostEntitiesV2(), "nutanix_lcm_status_v2": lcmv2.DatasourceNutanixLcmStatusV2(), + "nutanix_lcm_entities_v2": lcmv2.DatasourceNutanixLcmEntitiesV2(), + "nutanix_lcm_entity_v2": lcmv2.DatasourceNutanixLcmEntityV2(), }, ResourcesMap: map[string]*schema.Resource{ "nutanix_virtual_machine": vmm.ResourceNutanixVirtualMachine(), diff --git a/nutanix/services/lcmv2/data_source_lcm_entities_v2.go b/nutanix/services/lcmv2/data_source_lcm_entities_v2.go new file mode 100644 index 000000000..7d432a420 --- /dev/null +++ b/nutanix/services/lcmv2/data_source_lcm_entities_v2.go @@ -0,0 +1,127 @@ +package lcmv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + lcmEntityPkg "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func DatasourceNutanixLcmEntitiesV2() *schema.Resource { + return &schema.Resource{ + ReadContext: DatasourceNutanixLcmEntitiesV2Create, + Schema: map[string]*schema.Schema{ + "page": { + Type: schema.TypeInt, + Optional: true, + }, + "limit": { + Type: schema.TypeInt, + Optional: true, + }, + "filter": { + Type: schema.TypeString, + Optional: true, + }, + "order_by": { + Type: schema.TypeString, + Optional: true, + }, + "select": { + Type: schema.TypeString, + Optional: true, + }, + "entities": { + Type: schema.TypeList, + Computed: true, + Elem: DatasourceNutanixLcmEntityV2(), + }, + }, + } +} + +func DatasourceNutanixLcmEntitiesV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + + // initialize query params + var filter, orderBy, selects *string + var page, limit *int + + if pagef, ok := d.GetOk("page"); ok { + page = utils.IntPtr(pagef.(int)) + } else { + page = nil + } + if limitf, ok := d.GetOk("limit"); ok { + limit = utils.IntPtr(limitf.(int)) + } else { + limit = nil + } + if filterf, ok := d.GetOk("filter"); ok { + filter = utils.StringPtr(filterf.(string)) + } else { + filter = nil + } + if order, ok := d.GetOk("order_by"); ok { + orderBy = utils.StringPtr(order.(string)) + } else { + orderBy = nil + } + if selectf, ok := d.GetOk("select"); ok { + selects = utils.StringPtr(selectf.(string)) + } else { + selects = nil + } + + resp, err := conn.LcmEntitiesAPIInstance.ListEntities(page, limit, filter, orderBy, selects) + if err != nil { + return diag.Errorf("error while listing the Lcm entites : %v", err) + } + + entities := resp.Data.GetValue().([]lcmEntityPkg.Entity) + if err := d.Set("entities", flattenLcmEntities(entities)); err != nil { + return diag.FromErr(err) + } + + d.SetId(utils.GenUUID()) + return nil +} + +func flattenLcmEntities(entities []lcmEntityPkg.Entity) []map[string]interface{} { + if len(entities) == 0 { + return nil + } + + flattenedEntities := make([]map[string]interface{}, 0) + + for _, entity := range entities { + flattenedEntity := map[string]interface{}{ + "tenant_id": entity.TenantId, + "ext_id": entity.ExtId, + "links": flattenLinks(entity.Links), + "entity_class": entity.EntityClass, + "entity_model": entity.EntityModel, + "entity_type": flattenEntityTypes(entity.EntityType), + "entity_version": entity.EntityVersion, + "hardware_family": entity.HardwareFamily, + "entity_description": entity.EntityDescription, + "location_info": flattenLocationInfo(entity.LocationInfo), + "target_version": entity.TargetVersion, + "last_updated_time": flattenTime(entity.LastUpdatedTime), + "device_id": entity.DeviceId, + "group_uuid": entity.GroupUuid, + "entity_details": flattenKeyValuePairs(entity.EntityDetails), + "child_entities": entity.ChildEntities, + "available_versions": flattenAvailableVersions(entity.AvailableVersions), + "sub_entities": flattenSubEntities(entity.SubEntities), + "cluster_ext_id": entity.ClusterExtId, + "hardware_vendor": entity.HardwareVendor, + } + flattenedEntities = append(flattenedEntities, flattenedEntity) + } + + return flattenedEntities +} diff --git a/nutanix/services/lcmv2/data_source_lcm_entitiy_v2.go b/nutanix/services/lcmv2/data_source_lcm_entitiy_v2.go new file mode 100644 index 000000000..9b22389d1 --- /dev/null +++ b/nutanix/services/lcmv2/data_source_lcm_entitiy_v2.go @@ -0,0 +1,549 @@ +package lcmv2 + +import ( + "context" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + lcmConfigPkg "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/common/v1/config" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" + lcmEntityPkg "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func DatasourceNutanixLcmEntityV2() *schema.Resource { + return &schema.Resource{ + ReadContext: DatasourceNutanixLcmEntityV2Create, + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Required: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "entity_class": { + Type: schema.TypeString, + Computed: true, + }, + "entity_model": { + Type: schema.TypeString, + Computed: true, + }, + "entity_type": { + Type: schema.TypeString, + Computed: true, + }, + "entity_version": { + Type: schema.TypeString, + Computed: true, + }, + "hardware_family": { + Type: schema.TypeString, + Computed: true, + }, + "entity_description": { + Type: schema.TypeString, + Computed: true, + }, + "location_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + "location_type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "target_version": { + Type: schema.TypeString, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "device_id": { + Type: schema.TypeString, + Computed: true, + }, + "group_uuid": { + Type: schema.TypeString, + Computed: true, + }, + "entity_details": { + Type: schema.TypeList, + Computed: true, + Elem: schemaForKeyValuePairs(), + }, + "child_entities": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, + }, + "available_versions": { + Type: schema.TypeList, + Computed: true, + Elem: schemaForAvailableVersions(), + }, + "sub_entities": { + Type: schema.TypeList, + Computed: true, + Elem: schemaForSubEntities(), + }, + "cluster_ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "hardware_vendor": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func DatasourceNutanixLcmEntityV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + extID := d.Get("ext_id").(string) + + resp, err := conn.LcmEntitiesAPIInstance.GetEntityById(utils.StringPtr(extID)) + if err != nil { + return diag.Errorf("error while fetching the Lcm etity : %v", err) + } + + lcmEntity := resp.Data.GetValue().(lcmEntityPkg.Entity) + if err := d.Set("tenant_id", lcmEntity.TenantId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("links", flattenLinks(lcmEntity.Links)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_class", lcmEntity.EntityClass); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_model", lcmEntity.EntityModel); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_type", flattenEntityTypes(lcmEntity.EntityType)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_version", lcmEntity.EntityVersion); err != nil { + return diag.FromErr(err) + } + if err := d.Set("hardware_family", lcmEntity.HardwareFamily); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_description", lcmEntity.EntityDescription); err != nil { + return diag.FromErr(err) + } + if err := d.Set("location_info", flattenLocationInfo(lcmEntity.LocationInfo)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("target_version", lcmEntity.TargetVersion); err != nil { + return diag.FromErr(err) + } + if err := d.Set("last_updated_time", flattenTime(lcmEntity.LastUpdatedTime)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("device_id", lcmEntity.DeviceId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("group_uuid", lcmEntity.GroupUuid); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_details", flattenKeyValuePairs(lcmEntity.EntityDetails)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("child_entities", lcmEntity.ChildEntities); err != nil { + return diag.FromErr(err) + } + if err := d.Set("available_versions", flattenAvailableVersions(lcmEntity.AvailableVersions)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("sub_entities", flattenSubEntities(lcmEntity.SubEntities)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("cluster_ext_id", lcmEntity.ClusterExtId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("hardware_vendor", lcmEntity.HardwareVendor); err != nil { + return diag.FromErr(err) + } + + d.SetId(utils.StringValue(lcmEntity.ExtId)) + return nil +} + +func schemaForKeyValuePairs() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "value": schemaForValue(), + }, + } +} + +func schemaForValue() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "string": { + Type: schema.TypeString, + Computed: true, + }, + "integer": { + Type: schema.TypeInt, + Computed: true, + }, + "boolean": { + Type: schema.TypeBool, + Computed: true, + }, + "string_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "object": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "map_of_strings": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "map": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "integer_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + } +} + +func schemaForAvailableVersions() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "version": { + Type: schema.TypeString, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "is_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "available_version_uuid": { + Type: schema.TypeString, + Computed: true, + }, + "order": { + Type: schema.TypeInt, + Computed: true, + }, + "disablement_reason": { + Type: schema.TypeString, + Computed: true, + }, + "release_notes": { + Type: schema.TypeString, + Computed: true, + }, + "release_date": { + Type: schema.TypeString, + Computed: true, + }, + "custom_message": { + Type: schema.TypeString, + Computed: true, + }, + "child_entities": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, + }, + "group_uuid": { + Type: schema.TypeString, + Computed: true, + }, + "dependencies": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "entity_class": { + Type: schema.TypeString, + Computed: true, + }, + "entity_model": { + Type: schema.TypeString, + Computed: true, + }, + "entity_type": { + Type: schema.TypeString, + Computed: true, + }, + "entity_version": { + Type: schema.TypeString, + Computed: true, + }, + "hardware_family": { + Type: schema.TypeString, + Computed: true, + }, + "dependent_versions": { + Type: schema.TypeList, + Computed: true, + Elem: schemaForKeyValuePairs(), + }, + }, + }, + }, + }, + } +} + +func schemaForSubEntities() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "entity_class": { + Type: schema.TypeString, + Computed: true, + }, + "entity_model": { + Type: schema.TypeString, + Computed: true, + }, + "entity_type": { + Type: schema.TypeString, + Computed: true, + }, + "entity_version": { + Type: schema.TypeString, + Computed: true, + }, + "hardware_family": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +// flatten Funcs +func flattenLocationInfo(locationInfo *common.LocationInfo) []map[string]interface{} { + if locationInfo == nil { + return nil + } + + locationInfoList := make([]map[string]interface{}, 0) + + locationInfoMap := map[string]interface{}{ + "uuid": locationInfo.Uuid, + "location_type": locationInfo.LocationType.GetName(), + } + locationInfoList = append(locationInfoList, locationInfoMap) + + return locationInfoList +} + +func flattenAvailableVersions(availableVersions []lcmEntityPkg.AvailableVersion) []map[string]interface{} { + if len(availableVersions) == 0 { + return nil + } + + availableVersionsList := make([]map[string]interface{}, 0) + + for _, availableVersion := range availableVersions { + availableVersionMap := map[string]interface{}{ + "version": availableVersion.Version, + "status": availableVersion.Status.GetName(), + "is_enabled": availableVersion.IsEnabled, + "available_version_uuid": availableVersion.AvailableVersionUuid, + "order": availableVersion.Order, + "disablement_reason": availableVersion.DisablementReason, + "release_notes": availableVersion.ReleaseNotes, + "release_date": availableVersion.ReleaseDate, + "custom_message": availableVersion.CustomMessage, + "child_entities": availableVersion.ChildEntities, + "group_uuid": availableVersion.GroupUuid, + "dependencies": flattenDependencies(availableVersion.Dependencies), + } + availableVersionsList = append(availableVersionsList, availableVersionMap) + } + + return availableVersionsList +} + +func flattenDependencies(dependencies []lcmEntityPkg.DependentEntity) []map[string]interface{} { + if len(dependencies) == 0 { + return nil + } + + dependenciesList := make([]map[string]interface{}, 0) + + for _, dependency := range dependencies { + dependencyMap := map[string]interface{}{ + "tenant_id": dependency.TenantId, + "ext_id": dependency.ExtId, + "links": flattenLinks(dependency.Links), + "entity_class": dependency.EntityClass, + "entity_model": dependency.EntityModel, + "entity_type": dependency.EntityType, + "entity_version": dependency.EntityVersion, + "hardware_family": dependency.HardwareFamily, + "dependent_versions": flattenKeyValuePairs(dependency.DependentVersions), + } + dependenciesList = append(dependenciesList, dependencyMap) + } + + return dependenciesList +} + +func flattenKeyValuePairs(dependentVersions []lcmConfigPkg.KVPair) []map[string]interface{} { + if len(dependentVersions) == 0 { + return nil + } + + dependentVersionsList := make([]map[string]interface{}, 0) + + for _, dependentVersion := range dependentVersions { + dependentVersionMap := map[string]interface{}{ + "name": dependentVersion.Name, + "value": flattenKVValue(dependentVersion.Value), + } + dependentVersionsList = append(dependentVersionsList, dependentVersionMap) + } + + return dependentVersionsList +} + +func flattenKVValue(value interface{}) []interface{} { + valueMap := make(map[string]interface{}) + switch v := value.(type) { + case string: + valueMap["string"] = v + case int: + valueMap["integer"] = v + case bool: + valueMap["boolean"] = v + case []string: + valueMap["string_list"] = v + case []int: + valueMap["integer_list"] = v + case map[string]string: + valueMap["object"] = v + + case []lcmConfigPkg.MapOfStringWrapper: + mapOfStrings := make([]interface{}, len(v)) + for i, m := range v { + mapOfStrings[i] = m + } + + valueMap["map_of_strings"] = mapOfStrings + default: + log.Printf("[WARN] Unknown type %T", v) + return nil + } + return []interface{}{valueMap} +} + +func flattenSubEntities(subEntities []common.EntityBaseModel) []map[string]interface{} { + if len(subEntities) == 0 { + return nil + } + + subEntitiesList := make([]map[string]interface{}, 0) + + for _, subEntity := range subEntities { + subEntityMap := map[string]interface{}{ + "tenant_id": subEntity.TenantId, + "ext_id": subEntity.ExtId, + "links": flattenLinks(subEntity.Links), + "entity_class": subEntity.EntityClass, + "entity_model": subEntity.EntityModel, + "entity_type": flattenEntityTypes(subEntity.EntityType), + "entity_version": subEntity.EntityVersion, + "hardware_family": subEntity.HardwareFamily, + } + subEntitiesList = append(subEntitiesList, subEntityMap) + } + + return subEntitiesList +} + +func flattenEntityTypes(entityType *common.EntityType) string { + return entityType.GetName() +} + +func flattenTime(inTime *time.Time) string { + if inTime != nil { + return inTime.UTC().Format(time.RFC3339) + } + return "" +} From 654dcfad78843924b7866144a047125aad36651d Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Tue, 18 Feb 2025 22:49:50 +0530 Subject: [PATCH 07/39] lcm changes to support datasource --- nutanix/provider/provider.go | 3 + .../services/lcmv2/data_source_lcm_config.go | 126 ++++++++++++++++++ .../lcmv2/data_source_lcm_status_v2.go | 9 +- .../lcmv2/resource_lcm_inventory_v2.go | 21 +-- .../lcmv2/resource_lcm_prechecks_v2.go | 39 +++--- .../lcmv2/resource_nutanix_lcm_config.go | 90 +++---------- 6 files changed, 174 insertions(+), 114 deletions(-) create mode 100644 nutanix/services/lcmv2/data_source_lcm_config.go diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 99e341980..ace4b5987 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -291,6 +291,7 @@ func Provider() *schema.Provider { "nutanix_host_v2": clustersv2.DatasourceNutanixHostEntityV2(), "nutanix_hosts_v2": clustersv2.DatasourceNutanixHostEntitiesV2(), "nutanix_lcm_status_v2": lcmv2.DatasourceNutanixLcmStatusV2(), + "nutanix_lcm_get_config_v2": lcmv2.DatasourceNutanixLcmConfigV2(), }, ResourcesMap: map[string]*schema.Resource{ "nutanix_virtual_machine": vmm.ResourceNutanixVirtualMachine(), @@ -388,6 +389,8 @@ func Provider() *schema.Provider { "nutanix_clusters_discover_unconfigured_nodes_v2": clustersv2.ResourceNutanixClusterDiscoverUnconfiguredNodesV2(), "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), + "nutanix_lcm_update_config_v2": lcmv2.ResourceNutanixLcmConfigV2(), + "nutanix_lcm_prechecks_v2": lcmv2.ResourceNutanixPreChecksV2(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go new file mode 100644 index 000000000..01418f967 --- /dev/null +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -0,0 +1,126 @@ +package lcmv2 + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func DatasourceNutanixLcmConfigV2() *schema.Resource { + return &schema.Resource{ + ReadContext: DatasourceNutanixLcmConfigV2Create, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Required: true, + }, + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "links": schemaForLinks(), + "url": { + Type: schema.TypeString, + Computed: true, + }, + "is_auto_inventory_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "auto_inventory_schedule": { + Type: schema.TypeString, + Computed: true, + }, + "version": { + Type: schema.TypeString, + Computed: true, + }, + "display_version": { + Type: schema.TypeString, + Computed: true, + }, + "connectivity_type": { + Type: schema.TypeString, + Computed: true, + }, + "is_https_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "supported_software_entities": { + Type: schema.TypeList, + Computed: true, + }, + "deprecated_software_entities": { + Type: schema.TypeList, + Computed: true, + }, + "is_framework_bundle_uploaded": { + Type: schema.TypeBool, + Computed: true, + }, + "has_module_auto_upgrade_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + }, + } +} + +func DatasourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterId := d.Get("x_cluster_id").(string) + + resp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterId)) + if err != nil { + return diag.Errorf("error while fetching the Lcm config : %v", err) + } + + lcmConfig := resp.Data.GetValue().(lcmconfigimport1.Config) + if err := d.Set("tenant_id", lcmConfig.TenantId); err != nil { + return diag.FromErr(err) + } + if err := d.Set("links", flattenLinks(lcmConfig.Links)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_auto_inventory_enabled", lcmConfig.IsAutoInventoryEnabled); err != nil { + return diag.FromErr(err) + } + if err := d.Set("auto_inventory_schedule", lcmConfig.AutoInventorySchedule); err != nil { + return diag.FromErr(err) + } + if err := d.Set("version", lcmConfig.Version); err != nil { + return diag.FromErr(err) + } + if err := d.Set("display_version", lcmConfig.DisplayVersion); err != nil { + return diag.FromErr(err) + } + if err := d.Set("connectivity_type", lcmConfig.ConnectivityType); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_https_enabled", lcmConfig.IsHttpsEnabled); err != nil { + return diag.FromErr(err) + } + // if err := d.Set("supported_software_entities", flattenSoftwareEntities(lcmConfig.SupportedSoftwareEntities)); err != nil { + // return diag.FromErr(err) + // } + // if err := d.Set("deprecated_software_entities", flattenSoftwareEntities(lcmConfig.DeprecatedSoftwareEntities)); err != nil { + // return diag.FromErr(err) + // } + if err := d.Set("is_framework_bundle_uploaded", lcmConfig.IsFrameworkBundleUploaded); err != nil { + return diag.FromErr(err) + } + if err := d.Set("has_module_auto_upgrade_enabled", lcmConfig.HasModuleAutoUpgradeEnabled); err != nil { + return diag.FromErr(err) + } + d.SetId(*lcmConfig.ExtId) + return nil +} diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go index 589570ddc..6d2ff7d7f 100644 --- a/nutanix/services/lcmv2/data_source_lcm_status_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -8,6 +8,7 @@ import ( import2 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/common/v1/response" lcmstatusimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" ) func DatasourceNutanixLcmStatusV2() *schema.Resource { @@ -16,7 +17,7 @@ func DatasourceNutanixLcmStatusV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Optional: true, + Required: true, }, "tenant_id": { Type: schema.TypeString, @@ -78,11 +79,7 @@ func DatasourceNutanixLcmStatusV2() *schema.Resource { func DatasourceNutanixLcmStatusV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - - args := make(map[string]interface{}) - args["X-Cluster-Id"] = clusterId - - resp, err := conn.LcmStatusAPIInstance.GetStatus(&clusterId, args) + resp, err := conn.LcmStatusAPIInstance.GetStatus(utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while fetching the Lcm status : %v", err) } diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index 44352c172..262806968 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -7,8 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" - lcmInventoryResp "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/operations" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" @@ -24,7 +23,7 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Optional: true, + Required: true, }, "ext_id": { Type: schema.TypeString, @@ -37,21 +36,12 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - ntnxRequestId, ok := d.Get("ntnx_request_id").(string) - if !ok || ntnxRequestId == "" { - return diag.Errorf("ntnx_request_id is required and cannot be null or empty") - } - - args := make(map[string]interface{}) - args["X-Cluster-Id"] = clusterId - args["NTNX-Request-Id"] = ntnxRequestId - - resp, err := conn.LcmInventoryAPIInstance.PerformInventory(&clusterId, args) + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) } - getResp := resp.Data.GetValue().(lcmInventoryResp.InventoryApiResponse) - TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId // calling group API to poll for completion of task @@ -68,6 +58,7 @@ func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.R if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Perform inventory task failed: %s", errWaitTask) } + d.SetId(*taskUUID) return nil } diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go index 8afa2c830..099bfd44b 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -8,18 +8,17 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" - lcmPreCheckResp "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/operations" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) -func ResourcePreChecksV2() *schema.Resource { +func ResourceNutanixPreChecksV2() *schema.Resource { return &schema.Resource{ + CreateContext: ResourceNutanixLcmPreChecksV2Create, + ReadContext: ResourceNutanixLcmPreChecksV2Read, + UpdateContext: ResourceNutanixLcmPreChecksV2Update, + DeleteContext: ResourceNutanixLcmPreChecksV2Delete, Schema: map[string]*schema.Schema{ - "ntnx_request_id": { - Type: schema.TypeString, - Required: true, - }, "x_cluster_id": { Type: schema.TypeString, Optional: true, @@ -76,25 +75,16 @@ func ResourcePreChecksV2() *schema.Resource { } } -func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - ntnxRequestId, ok := d.Get("ntnx_request_id").(string) - if !ok || ntnxRequestId == "" { - return diag.Errorf("ntnx_request_id is required and cannot be null or empty") - } - - args := make(map[string]interface{}) - args["X-Cluster-Id"] = clusterId - args["NTNX-Request-Id"] = ntnxRequestId body := preCheckConfig.PrechecksSpec{} - resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(&body, &clusterId, args) + resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(&body, utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while performing the prechecs: %v", err) } - getResp := resp.Data.GetValue().(lcmPreCheckResp.PrechecksApiResponse) - TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId // calling group API to poll for completion of task @@ -112,5 +102,18 @@ func ResourceLcmPreChecksV2(ctx context.Context, d *schema.ResourceData, meta in if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Prechecks task failed: %s", errWaitTask) } + d.SetId(*taskUUID) + return nil +} + +func ResourceNutanixLcmPreChecksV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourceNutanixLcmPreChecksV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourceNutanixLcmPreChecksV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { return nil } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 980201216..116cde15c 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -12,24 +12,20 @@ import ( "github.com/terraform-providers/terraform-provider-nutanix/utils" ) -func ResourceLcmConfigV2() *schema.Resource { +func ResourceNutanixLcmConfigV2() *schema.Resource { return &schema.Resource{ - CreateContext: ResourceLcmConfigV2Create, - ReadContext: ResourceLcmConfigV2Read, - UpdateContext: ResourceLcmConfigV2Update, - DeleteContext: ResourceLcmConfigV2Delete, + CreateContext: ResourceNutanixLcmConfigV2Create, + ReadContext: ResourceNutanixLcmConfigV2Read, + UpdateContext: ResourceNutanixLcmConfigV2Update, + DeleteContext: ResourceNutanixLcmConfigV2Delete, Schema: map[string]*schema.Schema{ - "ntnx_request_id": { - Type: schema.TypeString, - Required: true, - }, "if_match": { Type: schema.TypeString, Required: true, }, "x_cluster_id": { Type: schema.TypeString, - Optional: true, + Required: true, }, "tenant_id": { Type: schema.TypeString, @@ -88,30 +84,22 @@ func ResourceLcmConfigV2() *schema.Resource { } } -func ResourceLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - ntnxRequestId, ok := d.Get("ntnx_request_id").(string) - if !ok || ntnxRequestId == "" { - return diag.Errorf("ntnx_request_id is required and cannot be null or empty") - } if_match, ok := d.Get("if_match").(string) if !ok || if_match == "" { return diag.Errorf("if_match is required and cannot be null or empty") } - args := make(map[string]interface{}) - args["X-Cluster-Id"] = clusterId - body := lcmconfigimport1.Config{} - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, &clusterId, args) + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while updating the LCM config: %v", err) } - getResp := resp.Data.GetValue().(lcmconfigimport1.UpdateConfigApiResponse) - TaskRef := getResp.Data.GetValue().(taskRef.TaskReference) + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId // calling group API to poll for completion of task @@ -129,67 +117,19 @@ func ResourceLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Config Update task failed: %s", errWaitTask) } - return ResourceLcmConfigV2Read(ctx, d, meta) + d.SetId(*taskUUID) + return nil } -func ResourceLcmConfigV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) - - args := make(map[string]interface{}) - args["X-Cluster-Id"] = clusterId - - resp, err := conn.LcmConfigAPIInstance.GetConfig(&clusterId, args) - if err != nil { - return diag.Errorf("error while fetching the Lcm config : %v", err) - } - - lcmConfig := resp.Data.GetValue().(lcmconfigimport1.Config) - if err := d.Set("tenant_id", lcmConfig.TenantId); err != nil { - return diag.FromErr(err) - } - if err := d.Set("links", flattenLinks(lcmConfig.Links)); err != nil { - return diag.FromErr(err) - } - if err := d.Set("is_auto_inventory_enabled", lcmConfig.IsAutoInventoryEnabled); err != nil { - return diag.FromErr(err) - } - if err := d.Set("auto_inventory_schedule", lcmConfig.AutoInventorySchedule); err != nil { - return diag.FromErr(err) - } - if err := d.Set("version", lcmConfig.Version); err != nil { - return diag.FromErr(err) - } - if err := d.Set("display_version", lcmConfig.DisplayVersion); err != nil { - return diag.FromErr(err) - } - if err := d.Set("connectivity_type", lcmConfig.ConnectivityType); err != nil { - return diag.FromErr(err) - } - if err := d.Set("is_https_enabled", lcmConfig.IsHttpsEnabled); err != nil { - return diag.FromErr(err) - } - // if err := d.Set("supported_software_entities", flattenSoftwareEntities(lcmConfig.SupportedSoftwareEntities)); err != nil { - // return diag.FromErr(err) - // } - // if err := d.Set("deprecated_software_entities", flattenSoftwareEntities(lcmConfig.DeprecatedSoftwareEntities)); err != nil { - // return diag.FromErr(err) - // } - if err := d.Set("is_framework_bundle_uploaded", lcmConfig.IsFrameworkBundleUploaded); err != nil { - return diag.FromErr(err) - } - if err := d.Set("has_module_auto_upgrade_enabled", lcmConfig.HasModuleAutoUpgradeEnabled); err != nil { - return diag.FromErr(err) - } - d.SetId(*lcmConfig.ExtId) +func ResourceNutanixLcmConfigV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { return nil } -func ResourceLcmConfigV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return ResourceLcmConfigV2Create(ctx, d, meta) +func ResourceNutanixLcmConfigV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return ResourceNutanixLcmConfigV2Create(ctx, d, meta) } -func ResourceLcmConfigV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func ResourceNutanixLcmConfigV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { return nil } From a8ecd31b595a8c84f1404e46881563e5db51a2b7 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 18:53:07 +0200 Subject: [PATCH 08/39] implement resource for LCM Preload Artifacts --- nutanix/provider/provider.go | 1 + .../resource_nutanix_preload_artifacts_v2.go | 107 ++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 6fb311c00..cc93e3f10 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -390,6 +390,7 @@ func Provider() *schema.Provider { "nutanix_clusters_discover_unconfigured_nodes_v2": clustersv2.ResourceNutanixClusterDiscoverUnconfiguredNodesV2(), "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), + "nutanix_lcm_preload_artifacts_v2": lcmv2.ResourcePreloadArtifactsV2(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go b/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go new file mode 100644 index 000000000..88df2788a --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go @@ -0,0 +1,107 @@ +package lcmv2 + +import ( + "context" + "encoding/json" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func ResourcePreloadArtifactsV2() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourcePreloadArtifactsV2Create, + ReadContext: ResourcePreloadArtifactsV2Read, + UpdateContext: ResourcePreloadArtifactsV2Update, + DeleteContext: ResourcePreloadArtifactsV2Delete, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Required: true, + }, + "entity_update_specs": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "entity_uuid": { + Type: schema.TypeString, + Required: true, + }, + "entity_type": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + }, + } +} + +func ResourcePreloadArtifactsV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + + clusterId := d.Get("x_cluster_id").(string) + + body := common.NewPreloadSpec() + + entityUpdateSpecs := d.Get("entity_update_specs").([]interface{}) + + body.EntityUpdateSpecs = expandEntityUpdateSpecs(entityUpdateSpecs) + + resp, err := conn.LcmEntitiesAPIInstance.PreloadArtifacts(body, utils.StringPtr(clusterId)) + if err != nil { + return diag.Errorf("error while Perform Preload Artifacts: %v", err) + } + + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + taskconn := meta.(*conns.Client).PrismAPI + + // Wait for the Config Update to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("LCM Upgrade task failed: %s", errWaitTask) + } + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Preload Artifacts task : %v", err) + } + + task := resourceUUID.Data.GetValue().(taskRef.TaskReference) + aJSON, _ := json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] LCM Preload Artifacts Task Response: %s", string(aJSON)) + + // randomly generating the id + d.SetId(utils.GenUUID()) + + return ResourcePreloadArtifactsV2Read(ctx, d, meta) +} + +func ResourcePreloadArtifactsV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourcePreloadArtifactsV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourcePreloadArtifactsV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} From 4e65dbca278bfe34feff0808011a8fe65081e858 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 20:37:14 +0200 Subject: [PATCH 09/39] implement resource for LCM Upgrade --- nutanix/provider/provider.go | 1 + .../lcmv2/resource_nutanix_lcm_upgrade.go | 232 ++++++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index cc93e3f10..e40dbe8ff 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -391,6 +391,7 @@ func Provider() *schema.Provider { "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), "nutanix_lcm_preload_artifacts_v2": lcmv2.ResourcePreloadArtifactsV2(), + "nutanix_lcm_upgrade_v2": lcmv2.ResourceLcmUpgradeV2(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go new file mode 100644 index 000000000..1b5fa2687 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go @@ -0,0 +1,232 @@ +package lcmv2 + +import ( + "context" + "encoding/json" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func ResourceLcmUpgradeV2() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceLcmUpgradeV2Create, + ReadContext: ResourceLcmUpgradeV2Read, + UpdateContext: ResourceLcmUpgradeV2Update, + DeleteContext: ResourceLcmUpgradeV2Delete, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Required: true, + }, + "management_server": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "hypervisor_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"HYPERV", "ESX", "AHV"}, false), + }, + "ip": { + Type: schema.TypeString, + Required: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + }, + "password": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "entity_update_specs": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "entity_uuid": { + Type: schema.TypeString, + Required: true, + }, + "to_version": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "skipped_precheck_flags": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, + }, + "auto_handle_flags": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, + }, + "max_wait_time_in_secs": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(60, 86400), + }, + }, + } +} + +func ResourceLcmUpgradeV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + + clusterId := d.Get("x_cluster_id").(string) + + body := common.NewUpgradeSpec() + + if managementServer, ok := d.GetOk("management_server"); ok && len(managementServer.([]interface{})) > 0 { + body.ManagementServer = expandManagementServer(managementServer) + } + if entityUpdateSpecs, ok := d.GetOk("entity_update_specs"); ok && len(entityUpdateSpecs.([]interface{})) > 0 { + body.EntityUpdateSpecs = expandEntityUpdateSpecs(entityUpdateSpecs.([]interface{})) + } + if skippedPrecheckFlags, ok := d.GetOk("skipped_precheck_flags"); ok && len(skippedPrecheckFlags.([]interface{})) > 0 { + body.SkippedPrecheckFlags = expandSystemAutoMgmtFlag(skippedPrecheckFlags.([]interface{})) + } + if autoHandleFlags, ok := d.GetOk("auto_handle_flags"); ok && len(autoHandleFlags.([]interface{})) > 0 { + body.AutoHandleFlags = expandSystemAutoMgmtFlag(autoHandleFlags.([]interface{})) + } + if maxWaitTimeInSecs, ok := d.GetOk("max_wait_time_in_secs"); ok && maxWaitTimeInSecs.(int) > 0 { + body.MaxWaitTimeInSecs = utils.IntPtr(maxWaitTimeInSecs.(int)) + } + + aJSON, _ := json.MarshalIndent(body, "", " ") + log.Printf("[DEBUG] LCM Upgrade Request: %s", string(aJSON)) + + resp, err := conn.LcmUpgradeAPIInstance.PerformUpgrade(body, utils.StringPtr(clusterId)) + if err != nil { + return diag.Errorf("error while Perform Upgrade the LCM config: %v", err) + } + + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + taskconn := meta.(*conns.Client).PrismAPI + + // Wait for the Config Update to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("LCM Upgrade task failed: %s", errWaitTask) + } + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + } + + task := resourceUUID.Data.GetValue().(taskRef.TaskReference) + aJSON, _ = json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] LCM Upgrade Task Response: %s", string(aJSON)) + + // randomly generating the id + d.SetId(utils.GenUUID()) + return nil +} + +func ResourceLcmUpgradeV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourceLcmUpgradeV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return ResourceLcmUpgradeV2Create(ctx, d, meta) +} + +func ResourceLcmUpgradeV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func expandManagementServer(managementServer interface{}) *common.ManagementServer { + managementServerList := managementServer.([]interface{}) + + if len(managementServerList) == 0 { + return nil + } + managementServerMap := managementServerList[0].(map[string]interface{}) + managementServerObj := common.NewManagementServer() + + managementServerObj.HypervisorType = expandHypervisorType(managementServerMap["hypervisor_type"].(string)) + managementServerObj.Ip = utils.StringPtr(managementServerMap["ip"].(string)) + managementServerObj.Username = utils.StringPtr(managementServerMap["username"].(string)) + managementServerObj.Password = utils.StringPtr(managementServerMap["password"].(string)) + + return managementServerObj +} + +func expandHypervisorType(hypervisorType string) *common.HypervisorType { + if hypervisorType == "HYPERV" { + p := common.HYPERVISORTYPE_HYPERV + return &p + } else if hypervisorType == "ESX" { + p := common.HYPERVISORTYPE_ESX + return &p + } else if hypervisorType == "AHV" { + p := common.HYPERVISORTYPE_AHV + return &p + } + return nil +} + +func expandEntityUpdateSpecs(entityUpdateSpec []interface{}) []common.EntityUpdateSpec { + if len(entityUpdateSpec) == 0 { + return nil + } + + entityUpdateSpecsList := make([]common.EntityUpdateSpec, 0) + + for _, entityUpdateSpecItem := range entityUpdateSpec { + entityUpdateSpecMap := entityUpdateSpecItem.(map[string]interface{}) + entityUpdateSpecObj := common.NewEntityUpdateSpec() + entityUpdateSpecObj.EntityUuid = utils.StringPtr(entityUpdateSpecMap["entity_uuid"].(string)) + entityUpdateSpecObj.ToVersion = utils.StringPtr(entityUpdateSpecMap["to_version"].(string)) + entityUpdateSpecsList = append(entityUpdateSpecsList, *entityUpdateSpecObj) + } + return entityUpdateSpecsList +} + +func expandSystemAutoMgmtFlag(flags []interface{}) []common.SystemAutoMgmtFlag { + if len(flags) == 0 { + return nil + } + + systemAutoMgmtFlags := make([]common.SystemAutoMgmtFlag, 0) + for _, flag := range flags { + if flag == "POWER_OFF_UVMS" { + p := common.SYSTEMAUTOMGMTFLAG_POWER_OFF_UVMS + systemAutoMgmtFlags = append(systemAutoMgmtFlags, p) + } + } + return systemAutoMgmtFlags +} From 5874f64020564acbd727c24cae5c65e6dcad56f4 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 21:01:12 +0200 Subject: [PATCH 10/39] fix lcm status data source id --- nutanix/services/lcmv2/data_source_lcm_status_v2.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go index 6d2ff7d7f..6b6495ec5 100644 --- a/nutanix/services/lcmv2/data_source_lcm_status_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -103,7 +103,9 @@ func DatasourceNutanixLcmStatusV2Create(ctx context.Context, d *schema.ResourceD if err := d.Set("upload_task_uuid", lcmStatusResp.UploadTaskUuid); err != nil { return diag.FromErr(err) } - d.SetId(*lcmStatusResp.ExtId) + + // setting the data source id to the random uuid + d.SetId(utils.GenUUID()) return nil } From 39a05a928798ba972d3f7a0b6ca2d5113fe60d7a Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:43:15 +0200 Subject: [PATCH 11/39] fix lcm entities data source --- nutanix/services/lcmv2/data_source_lcm_entities_v2.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_entities_v2.go b/nutanix/services/lcmv2/data_source_lcm_entities_v2.go index 7d432a420..e3b959edc 100644 --- a/nutanix/services/lcmv2/data_source_lcm_entities_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_entities_v2.go @@ -78,7 +78,11 @@ func DatasourceNutanixLcmEntitiesV2Create(ctx context.Context, d *schema.Resourc resp, err := conn.LcmEntitiesAPIInstance.ListEntities(page, limit, filter, orderBy, selects) if err != nil { - return diag.Errorf("error while listing the Lcm entites : %v", err) + return diag.Errorf("error while listing the Lcm entities : %v", err) + } + + if resp.Data == nil { + return diag.Errorf("error while listing the Lcm entities : response data is empty") } entities := resp.Data.GetValue().([]lcmEntityPkg.Entity) From b95f5b11fb1f12034ab7fe23be47ef5dc9e9a442 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:45:20 +0200 Subject: [PATCH 12/39] fix precheck resource schema and code --- .../lcmv2/resource_lcm_prechecks_v2.go | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go index 099bfd44b..52d848c82 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go @@ -2,12 +2,15 @@ package lcmv2 import ( "context" + "encoding/json" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" preCheckConfig "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) @@ -25,6 +28,7 @@ func ResourceNutanixPreChecksV2() *schema.Resource { }, "management_server": { Type: schema.TypeList, + MaxItems: 1, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -48,7 +52,8 @@ func ResourceNutanixPreChecksV2() *schema.Resource { }, }, "entity_update_specs": { - Type: schema.TypeList, + Type: schema.TypeList, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "entity_uuid": { @@ -61,11 +66,14 @@ func ResourceNutanixPreChecksV2() *schema.Resource { }, }, }, - Required: true, }, "skipped_precheck_flags": { Type: schema.TypeList, Optional: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, }, "ext_id": { Type: schema.TypeString, @@ -78,17 +86,26 @@ func ResourceNutanixPreChecksV2() *schema.Resource { func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - body := preCheckConfig.PrechecksSpec{} + body := preCheckConfig.NewPrechecksSpec() + + if managementServer, ok := d.GetOk("management_server"); ok { + body.ManagementServer = expandManagementServer(managementServer.([]interface{})) + } + if entityUpdateSpecs, ok := d.GetOk("entity_update_specs"); ok { + body.EntityUpdateSpecs = expandEntityUpdateSpecs(entityUpdateSpecs.([]interface{})) + } + if skippedPrecheckFlags, ok := d.GetOk("skipped_precheck_flags"); ok { + body.SkippedPrecheckFlags = expandSystemAutoMgmtFlag(skippedPrecheckFlags.([]interface{})) + } - resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(&body, utils.StringPtr(clusterId)) + resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(body, utils.StringPtr(clusterId)) if err != nil { - return diag.Errorf("error while performing the prechecs: %v", err) + return diag.Errorf("error while performing the prechecks: %v", err) } TaskRef := resp.Data.GetValue().(taskRef.TaskReference) taskUUID := TaskRef.ExtId // calling group API to poll for completion of task - taskconn := meta.(*conns.Client).PrismAPI // Wait for the PreChecks to be successful @@ -102,12 +119,23 @@ func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.Resource if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Prechecks task failed: %s", errWaitTask) } - d.SetId(*taskUUID) + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + } + + task := resourceUUID.Data.GetValue().(prismConfig.Task) + aJSON, _ := json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] PrechecksSpec: %s", string(aJSON)) + + // set the resource id to random uuid + d.SetId(utils.GenUUID()) return nil } func ResourceNutanixLcmPreChecksV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil + return ResourceNutanixLcmPreChecksV2Create(ctx, d, meta) } func ResourceNutanixLcmPreChecksV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { From a38d97dc9a4cb28f54b5a0facef4d846e7e73a7b Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:46:51 +0200 Subject: [PATCH 13/39] add nutanix_lcm_prechecks_v2 to provider resource map --- nutanix/provider/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index e40dbe8ff..d07bff74e 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -391,6 +391,7 @@ func Provider() *schema.Provider { "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), "nutanix_lcm_preload_artifacts_v2": lcmv2.ResourcePreloadArtifactsV2(), + "nutanix_lcm_prechecks_v2": lcmv2.ResourceNutanixPreChecksV2(), "nutanix_lcm_upgrade_v2": lcmv2.ResourceLcmUpgradeV2(), }, ConfigureContextFunc: providerConfigure, From 8d1802bce3ae13be287092c4d6c3a2925a95c1a8 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:48:02 +0200 Subject: [PATCH 14/39] fix lcm inventory code --- .../lcmv2/resource_lcm_inventory_v2.go | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go index 262806968..fbbd46719 100644 --- a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_lcm_inventory_v2.go @@ -2,13 +2,15 @@ package lcmv2 import ( "context" + "encoding/json" "fmt" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" - import1 "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/nutanix/sdks/v4/prism" "github.com/terraform-providers/terraform-provider-nutanix/utils" @@ -17,7 +19,7 @@ import ( func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { return &schema.Resource{ CreateContext: ResourceNutanixLcmPerformInventoryV2Create, - ReadContext: ResourceNutainxLcmPerformInventoryV2Read, + ReadContext: ResourceNutanixLcmPerformInventoryV2Read, UpdateContext: ResourceNutanixLcmPerformInventoryV2Update, DeleteContext: ResourceNutanixLcmPerformInventoryV2Delete, Schema: map[string]*schema.Schema{ @@ -36,6 +38,7 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) @@ -45,7 +48,6 @@ func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.R taskUUID := TaskRef.ExtId // calling group API to poll for completion of task - taskconn := meta.(*conns.Client).PrismAPI // Wait for the inventorty to be successful stateConf := &resource.StateChangeConf{ @@ -58,16 +60,27 @@ func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.R if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Perform inventory task failed: %s", errWaitTask) } - d.SetId(*taskUUID) + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + } + + task := resourceUUID.Data.GetValue().(prismConfig.Task) + aJSON, _ := json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] Perform Inventory Task Response: %s", string(aJSON)) + + // randomly generating the id + d.SetId(utils.GenUUID()) return nil } -func ResourceNutainxLcmPerformInventoryV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return ResourceNutanixLcmPerformInventoryV2Create(ctx, d, meta) +func ResourceNutanixLcmPerformInventoryV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil } func ResourceNutanixLcmPerformInventoryV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil + return ResourceNutanixLcmPerformInventoryV2Create(ctx, d, meta) } func ResourceNutanixLcmPerformInventoryV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { @@ -85,7 +98,7 @@ func taskStateRefreshPrismTaskGroup(client *prism.Client, taskUUID string) resou // get the group results - v := vresp.Data.GetValue().(import1.Task) + v := vresp.Data.GetValue().(prismConfig.Task) if getTaskStatus(v.Status) == "CANCELED" || getTaskStatus(v.Status) == "FAILED" { return v, getTaskStatus(v.Status), @@ -95,22 +108,22 @@ func taskStateRefreshPrismTaskGroup(client *prism.Client, taskUUID string) resou } } -func getTaskStatus(pr *import1.TaskStatus) string { +func getTaskStatus(pr *prismConfig.TaskStatus) string { const two, three, five, six, seven = 2, 3, 5, 6, 7 if pr != nil { - if *pr == import1.TaskStatus(six) { + if *pr == prismConfig.TaskStatus(six) { return "FAILED" } - if *pr == import1.TaskStatus(seven) { + if *pr == prismConfig.TaskStatus(seven) { return "CANCELED" } - if *pr == import1.TaskStatus(two) { + if *pr == prismConfig.TaskStatus(two) { return "QUEUED" } - if *pr == import1.TaskStatus(three) { + if *pr == prismConfig.TaskStatus(three) { return "RUNNING" } - if *pr == import1.TaskStatus(five) { + if *pr == prismConfig.TaskStatus(five) { return "SUCCEEDED" } } From 0c2bb2677b186b2d1e4a1a868757974adf919391 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:49:09 +0200 Subject: [PATCH 15/39] fix preload artifacts, extracting task with correct type --- .../services/lcmv2/resource_nutanix_preload_artifacts_v2.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go b/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go index 88df2788a..b199e7506 100644 --- a/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) @@ -84,7 +85,7 @@ func ResourcePreloadArtifactsV2Create(ctx context.Context, d *schema.ResourceDat return diag.Errorf("error while fetching the Preload Artifacts task : %v", err) } - task := resourceUUID.Data.GetValue().(taskRef.TaskReference) + task := resourceUUID.Data.GetValue().(prismConfig.Task) aJSON, _ := json.MarshalIndent(task, "", " ") log.Printf("[DEBUG] LCM Preload Artifacts Task Response: %s", string(aJSON)) From a70dded23b6dd992f114df92d5089a47078a3fbd Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Tue, 18 Feb 2025 22:49:42 +0200 Subject: [PATCH 16/39] fix lcm upgrade resource, extracting task with correct type --- nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go index 1b5fa2687..4ba2cb139 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) @@ -147,7 +148,7 @@ func ResourceLcmUpgradeV2Create(ctx context.Context, d *schema.ResourceData, met return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) } - task := resourceUUID.Data.GetValue().(taskRef.TaskReference) + task := resourceUUID.Data.GetValue().(prismConfig.Task) aJSON, _ = json.MarshalIndent(task, "", " ") log.Printf("[DEBUG] LCM Upgrade Task Response: %s", string(aJSON)) From 7c6cffca44ea86a1206d8f56226f8b13a299b67b Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Wed, 19 Feb 2025 13:18:22 +0530 Subject: [PATCH 17/39] add get config in provider --- nutanix/provider/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index d07bff74e..639669996 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -293,6 +293,7 @@ func Provider() *schema.Provider { "nutanix_lcm_status_v2": lcmv2.DatasourceNutanixLcmStatusV2(), "nutanix_lcm_entities_v2": lcmv2.DatasourceNutanixLcmEntitiesV2(), "nutanix_lcm_entity_v2": lcmv2.DatasourceNutanixLcmEntityV2(), + "nutanix_lcm_config_v2": lcmv2.DatasourceNutanixLcmConfigV2(), }, ResourcesMap: map[string]*schema.Resource{ "nutanix_virtual_machine": vmm.ResourceNutanixVirtualMachine(), From 4d15a5fec640993a5dd9139dd2a1faa0e1154625 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 11:46:16 +0200 Subject: [PATCH 18/39] fix lcm status --- .../lcmv2/data_source_lcm_status_v2.go | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go index 6b6495ec5..051eff943 100644 --- a/nutanix/services/lcmv2/data_source_lcm_status_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -17,8 +17,9 @@ func DatasourceNutanixLcmStatusV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, + "tenant_id": { Type: schema.TypeString, Computed: true, @@ -78,13 +79,19 @@ func DatasourceNutanixLcmStatusV2() *schema.Resource { func DatasourceNutanixLcmStatusV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) - resp, err := conn.LcmStatusAPIInstance.GetStatus(utils.StringPtr(clusterId)) + + var clusterID *string + if id := d.Get("x_cluster_id").(string); id != "" { + clusterID = &id + } + + resp, err := conn.LcmStatusAPIInstance.GetStatus(clusterID) if err != nil { return diag.Errorf("error while fetching the Lcm status : %v", err) } lcmStatusResp := resp.Data.GetValue().(lcmstatusimport1.StatusInfo) + if err := d.Set("tenant_id", lcmStatusResp.TenantId); err != nil { return diag.FromErr(err) } @@ -111,15 +118,15 @@ func DatasourceNutanixLcmStatusV2Create(ctx context.Context, d *schema.ResourceD func flattenFrameworkVersion(pr *lcmstatusimport1.FrameworkVersionInfo) []map[string]interface{} { if pr != nil { - frameworVersionRef := make([]map[string]interface{}, 0) + frameworkVersionRef := make([]map[string]interface{}, 0) frameworkVersion := make(map[string]interface{}) frameworkVersion["current_version"] = pr.CurrentVersion frameworkVersion["available_version"] = pr.AvailableVersion frameworkVersion["is_update_needed"] = pr.IsUpdateNeeded - frameworVersionRef = append(frameworVersionRef, frameworkVersion) - return frameworVersionRef + frameworkVersionRef = append(frameworkVersionRef, frameworkVersion) + return frameworkVersionRef } return nil } @@ -129,7 +136,7 @@ func flattenInProgressOperation(pr *lcmstatusimport1.InProgressOpInfo) []map[str OperationRef := make([]map[string]interface{}, 0) Operation := make(map[string]interface{}) - Operation["operation_type"] = pr.OperationType + Operation["operation_type"] = pr.OperationType.GetName() Operation["operation_id"] = pr.OperationId OperationRef = append(OperationRef, Operation) From adb85865add9405b8dd52220d797b0419da5a954 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Wed, 19 Feb 2025 15:47:50 +0530 Subject: [PATCH 19/39] Fix data source lcm config --- .../services/lcmv2/data_source_lcm_config.go | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go index 01418f967..294c3bf96 100644 --- a/nutanix/services/lcmv2/data_source_lcm_config.go +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -58,10 +58,18 @@ func DatasourceNutanixLcmConfigV2() *schema.Resource { "supported_software_entities": { Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, }, "deprecated_software_entities": { Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{ + Description: "List of String", + Type: schema.TypeString, + }, }, "is_framework_bundle_uploaded": { Type: schema.TypeBool, @@ -91,6 +99,9 @@ func DatasourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceD if err := d.Set("links", flattenLinks(lcmConfig.Links)); err != nil { return diag.FromErr(err) } + if err := d.Set("url", lcmConfig.Url); err != nil { + return diag.FromErr(err) + } if err := d.Set("is_auto_inventory_enabled", lcmConfig.IsAutoInventoryEnabled); err != nil { return diag.FromErr(err) } @@ -103,24 +114,26 @@ func DatasourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceD if err := d.Set("display_version", lcmConfig.DisplayVersion); err != nil { return diag.FromErr(err) } - if err := d.Set("connectivity_type", lcmConfig.ConnectivityType); err != nil { + if err := d.Set("connectivity_type", lcmConfig.ConnectivityType.GetName()); err != nil { return diag.FromErr(err) } if err := d.Set("is_https_enabled", lcmConfig.IsHttpsEnabled); err != nil { return diag.FromErr(err) } - // if err := d.Set("supported_software_entities", flattenSoftwareEntities(lcmConfig.SupportedSoftwareEntities)); err != nil { - // return diag.FromErr(err) - // } - // if err := d.Set("deprecated_software_entities", flattenSoftwareEntities(lcmConfig.DeprecatedSoftwareEntities)); err != nil { - // return diag.FromErr(err) - // } + if err := d.Set("supported_software_entities", lcmConfig.SupportedSoftwareEntities); err != nil { + return diag.FromErr(err) + } + if err := d.Set("deprecated_software_entities", lcmConfig.DeprecatedSoftwareEntities); err != nil { + return diag.FromErr(err) + } if err := d.Set("is_framework_bundle_uploaded", lcmConfig.IsFrameworkBundleUploaded); err != nil { return diag.FromErr(err) } if err := d.Set("has_module_auto_upgrade_enabled", lcmConfig.HasModuleAutoUpgradeEnabled); err != nil { return diag.FromErr(err) } - d.SetId(*lcmConfig.ExtId) + + // Set Id to random UUID + d.SetId(utils.GenUUID()) return nil } From 0412236b866350bf2618cf09d3290578215c837f Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 12:47:00 +0200 Subject: [PATCH 20/39] lcm status fix operation type --- nutanix/services/lcmv2/data_source_lcm_status_v2.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_status_v2.go b/nutanix/services/lcmv2/data_source_lcm_status_v2.go index 051eff943..cd1c70012 100644 --- a/nutanix/services/lcmv2/data_source_lcm_status_v2.go +++ b/nutanix/services/lcmv2/data_source_lcm_status_v2.go @@ -19,7 +19,6 @@ func DatasourceNutanixLcmStatusV2() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "tenant_id": { Type: schema.TypeString, Computed: true, @@ -136,7 +135,11 @@ func flattenInProgressOperation(pr *lcmstatusimport1.InProgressOpInfo) []map[str OperationRef := make([]map[string]interface{}, 0) Operation := make(map[string]interface{}) - Operation["operation_type"] = pr.OperationType.GetName() + operationType := "" + if pr.OperationType != nil { + operationType = pr.OperationType.GetName() + } + Operation["operation_type"] = operationType Operation["operation_id"] = pr.OperationId OperationRef = append(OperationRef, Operation) From 37772929419df69b2b35755864ae4710a5f70d12 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 12:52:02 +0200 Subject: [PATCH 21/39] rename resource_nutanix_lcm_upgrade_v2.go --- ..._nutanix_lcm_upgrade.go => resource_nutanix_lcm_upgrade_v2.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename nutanix/services/lcmv2/{resource_nutanix_lcm_upgrade.go => resource_nutanix_lcm_upgrade_v2.go} (100%) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go similarity index 100% rename from nutanix/services/lcmv2/resource_nutanix_lcm_upgrade.go rename to nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go From 3727d7f93a5b2f2aecbeb279aa025b87cfb56b2a Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 16:18:26 +0200 Subject: [PATCH 22/39] dev test for lcm inventory, prechecks, and upgrade --- nutanix/services/lcmv2/main_test.go | 43 +++++ ...o => resource_nutanix_lcm_inventory_v2.go} | 0 .../resource_nutanix_lcm_inventry_v2_test.go | 75 ++++++++ ...o => resource_nutanix_lcm_prechecks_v2.go} | 2 +- .../resource_nutanix_lcm_prechecks_v2_test.go | 90 ++++++++++ .../lcmv2/resource_nutanix_lcm_upgrade_v2.go | 14 +- .../resource_nutanix_lcm_upgrade_v2_test.go | 162 ++++++++++++++++++ .../resource_nutanix_preload_artifacts_v2.go | 108 ------------ 8 files changed, 379 insertions(+), 115 deletions(-) create mode 100644 nutanix/services/lcmv2/main_test.go rename nutanix/services/lcmv2/{resource_lcm_inventory_v2.go => resource_nutanix_lcm_inventory_v2.go} (100%) create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go rename nutanix/services/lcmv2/{resource_lcm_prechecks_v2.go => resource_nutanix_lcm_prechecks_v2.go} (98%) create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go delete mode 100644 nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go diff --git a/nutanix/services/lcmv2/main_test.go b/nutanix/services/lcmv2/main_test.go new file mode 100644 index 000000000..5f50ee66f --- /dev/null +++ b/nutanix/services/lcmv2/main_test.go @@ -0,0 +1,43 @@ +package lcmv2_test + +import ( + "encoding/json" + "log" + "os" + "testing" +) + +type TestConfig struct { + Lcm struct { + EntityModel string `json:"entity_model"` + EntityModelVersion string `json:"entity_model_version"` + } `json:"lcm"` +} + +var testVars TestConfig + +var ( + path, _ = os.Getwd() + filepath = path + "/../../../test_config_v2.json" +) + +func loadVars(filepath string, varStuct interface{}) { + // Read config.json from home current path + configData, err := os.ReadFile(filepath) + if err != nil { + log.Printf("Got this error while reading config.json: %s", err.Error()) + os.Exit(1) + } + + err = json.Unmarshal(configData, varStuct) + if err != nil { + log.Printf("Got this error while unmarshalling config.json: %s", err.Error()) + os.Exit(1) + } +} + +func TestMain(m *testing.M) { + log.Println("Do some crazy stuff before tests!") + loadVars("../../../test_config_v2.json", &testVars) + os.Exit(m.Run()) +} diff --git a/nutanix/services/lcmv2/resource_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go similarity index 100% rename from nutanix/services/lcmv2/resource_lcm_inventory_v2.go rename to nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go new file mode 100644 index 000000000..fba096334 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go @@ -0,0 +1,75 @@ +package lcmv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const resourceNameLcmPerformInventory = "nutanix_lcm_perform_inventory_v2.inventory" + +func TestAccV2NutanixLcmPerformInventory_Basic(t *testing.T) { + datasourceNameLcmEntities := "data.nutanix_lcm_entities_v2.lcm-entities" + datasourceNameLcmEntityBeforeUpgrade := "data.nutanix_lcm_entity_v2.entity-before-upgrade" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccFoundationPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testLcmPerformInventoryConfig(), + Check: resource.ComposeTestCheckFunc( + // check if the entity model is present + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.#", "1"), + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.0.entity_model", testVars.Lcm.EntityModel), + // check if the entity is present + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(datasourceNameLcmEntityBeforeUpgrade, "entity_model", testVars.Lcm.EntityModel), + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), + // perform inventory checks + resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), + + ), + }, + }, + }) +} + +func testLcmPerformInventoryConfig() string { + return fmt.Sprintf(` +# list Clusters +data "nutanix_clusters_v2" "clusters" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id + config = jsondecode(file("%[1]s")) + lcm = local.config.lcm +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq '${local.lcm.entity_model}'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + + +`, filepath) +} diff --git a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go similarity index 98% rename from nutanix/services/lcmv2/resource_lcm_prechecks_v2.go rename to nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go index 52d848c82..2a27bb387 100644 --- a/nutanix/services/lcmv2/resource_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go @@ -127,7 +127,7 @@ func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.Resource task := resourceUUID.Data.GetValue().(prismConfig.Task) aJSON, _ := json.MarshalIndent(task, "", " ") - log.Printf("[DEBUG] PrechecksSpec: %s", string(aJSON)) + log.Printf("[DEBUG] PrechecksSpec Task Details: %s", string(aJSON)) // set the resource id to random uuid d.SetId(utils.GenUUID()) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go new file mode 100644 index 000000000..4423f58f1 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go @@ -0,0 +1,90 @@ +package lcmv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const resourceNameLcmPreChecks = "nutanix_lcm_prechecks_v2.pre-checks" + +func TestAccV2NutanixLcmPrechecks_Basic(t *testing.T) { + datasourceNameLcmEntities := "data.nutanix_lcm_entities_v2.lcm-entities" + datasourceNameLcmEntityBeforeUpgrade := "data.nutanix_lcm_entity_v2.entity-before-upgrade" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccFoundationPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testLcmPrechecksConfig(), + Check: resource.ComposeTestCheckFunc( + // check if the entity model is present + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.#", "1"), + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.0.entity_model", testVars.Lcm.EntityModel), + // check if the entity is present + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(datasourceNameLcmEntityBeforeUpgrade, "entity_model", testVars.Lcm.EntityModel), + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), + // perform inventory checks + resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), + // pre-checks checks + resource.TestCheckResourceAttrSet(resourceNameLcmPreChecks, "x_cluster_id"), + resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.#", "1"), + resource.TestCheckResourceAttrPair(resourceNameLcmPreChecks, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), + + ), + }, + }, + }) +} + +func testLcmPrechecksConfig() string { + return fmt.Sprintf(` +# list Clusters +data "nutanix_clusters_v2" "clusters" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id + config = jsondecode(file("%[1]s")) + lcm = local.config.lcm +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq '${local.lcm.entity_model}'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + +resource "nutanix_lcm_prechecks_v2" "pre-checks" { + x_cluster_id = local.pcExtID + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = local.lcm.entity_model_version + } + depends_on = [nutanix_lcm_perform_inventory_v2.inventory] +} + + + +`, filepath) +} diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go index 4ba2cb139..4ea9aa758 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go @@ -25,7 +25,7 @@ func ResourceLcmUpgradeV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "management_server": { Type: schema.TypeList, @@ -96,8 +96,10 @@ func ResourceLcmUpgradeV2() *schema.Resource { func ResourceLcmUpgradeV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - - clusterId := d.Get("x_cluster_id").(string) + var clusterID *string + if id := d.Get("x_cluster_id").(string); id != "" { + clusterID = &id + } body := common.NewUpgradeSpec() @@ -118,9 +120,9 @@ func ResourceLcmUpgradeV2Create(ctx context.Context, d *schema.ResourceData, met } aJSON, _ := json.MarshalIndent(body, "", " ") - log.Printf("[DEBUG] LCM Upgrade Request: %s", string(aJSON)) + log.Printf("[DEBUG] LCM Upgrade Request Spec: %s", string(aJSON)) - resp, err := conn.LcmUpgradeAPIInstance.PerformUpgrade(body, utils.StringPtr(clusterId)) + resp, err := conn.LcmUpgradeAPIInstance.PerformUpgrade(body, clusterID) if err != nil { return diag.Errorf("error while Perform Upgrade the LCM config: %v", err) } @@ -150,7 +152,7 @@ func ResourceLcmUpgradeV2Create(ctx context.Context, d *schema.ResourceData, met task := resourceUUID.Data.GetValue().(prismConfig.Task) aJSON, _ = json.MarshalIndent(task, "", " ") - log.Printf("[DEBUG] LCM Upgrade Task Response: %s", string(aJSON)) + log.Printf("[DEBUG] LCM Upgrade Task Details: %s", string(aJSON)) // randomly generating the id d.SetId(utils.GenUUID()) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go new file mode 100644 index 000000000..21c4d9651 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go @@ -0,0 +1,162 @@ +package lcmv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const resourceNameLcmUpgrade = "nutanix_lcm_upgrade_v2.upgrade" + +func TestAccV2NutanixLcmUpgrade_Basic(t *testing.T) { + datasourceNameLcmEntities := "data.nutanix_lcm_entities_v2.lcm-entities" + datasourceNameLcmEntityBeforeUpgrade := "data.nutanix_lcm_entity_v2.entity-before-upgrade" + datasourceNameLcmStatusBeforeUpgrade := "data.nutanix_lcm_status_v2.status-before-upgrade" + resourceNameLcmPerformInventory := "nutanix_lcm_perform_inventory_v2.inventory" + resourceNameLcmPreChecks := "nutanix_lcm_prechecks_v2.pre-checks" + datasourceNameLcmStatusAfterUpgrade := "data.nutanix_lcm_status_v2.status-after-upgrade" + datasourceNameLcmEntityAfterUpgrade := "data.nutanix_lcm_entity_v2.entity-after-upgrade" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccFoundationPreCheck(t) }, + Providers: acc.TestAccProviders, + // CheckDestroy: testCheckDestroyProtectedResource, + Steps: []resource.TestStep{ + // create protection policy and protected vm + { + Config: testLcmUpgradeConfig(), + Check: resource.ComposeTestCheckFunc( + // check if the entity model is present + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.#", "1"), + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.0.entity_model", testVars.Lcm.EntityModel), + // check if the entity is present + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(datasourceNameLcmEntityBeforeUpgrade, "entity_model", testVars.Lcm.EntityModel), + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), + // check if there is any operation in progress before starting the upgrade + resource.TestCheckResourceAttr(datasourceNameLcmStatusBeforeUpgrade, "in_progress_operation.0.operation_type", ""), + resource.TestCheckResourceAttr(datasourceNameLcmStatusBeforeUpgrade, "in_progress_operation.0.operation_id", ""), + // perform inventory checks + resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), + // pre-checks checks + resource.TestCheckResourceAttrSet(resourceNameLcmPreChecks, "x_cluster_id"), + resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.#", "1"), + resource.TestCheckResourceAttrPair(resourceNameLcmPreChecks, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), + // upgrade checks + resource.TestCheckResourceAttrSet(resourceNameLcmUpgrade, "x_cluster_id"), + resource.TestCheckResourceAttr(resourceNameLcmUpgrade, "entity_update_specs.#", "1"), + resource.TestCheckResourceAttrPair(resourceNameLcmUpgrade, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(resourceNameLcmUpgrade, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), + // lcm status after upgrade + resource.TestCheckResourceAttr(datasourceNameLcmStatusAfterUpgrade, "in_progress_operation.0.operation_type", ""), + resource.TestCheckResourceAttr(datasourceNameLcmStatusAfterUpgrade, "in_progress_operation.0.operation_id", ""), + // entity after upgrade + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityAfterUpgrade, "ext_id"), + resource.TestCheckResourceAttr(datasourceNameLcmEntityAfterUpgrade, "entity_version", testVars.Lcm.EntityModelVersion), + resource.TestCheckResourceAttr(datasourceNameLcmEntityAfterUpgrade, "entity_model", testVars.Lcm.EntityModel), + ), + }, + }, + }) +} + +func testLcmUpgradeConfig() string { + return fmt.Sprintf(` +# list Clusters +data "nutanix_clusters_v2" "clusters" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id + config = jsondecode(file("%[1]s")) + lcm = local.config.lcm +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq '${local.lcm.entity_model}'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + +resource "nutanix_lcm_prechecks_v2" "pre-checks" { + x_cluster_id = local.pcExtID + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = local.lcm.entity_model_version + } + depends_on = [nutanix_lcm_perform_inventory_v2.inventory] +} + +# check if there is any operation in progress before starting the upgrade +data "nutanix_lcm_status_v2" "status-before-upgrade" { + x_cluster_id = local.pcExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_prechecks_v2.pre-checks] +} + +# upgrade the entity +resource "nutanix_lcm_upgrade_v2" "upgrade" { + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = local.lcm.entity_model_version + } + depends_on = [data.nutanix_lcm_status_v2.status-before-upgrade] +} + +# check if there is any operation in progress after upgrade +data "nutanix_lcm_status_v2" "status-after-upgrade" { + x_cluster_id = local.clusterExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade] +} + +# fetch the entity after upgrade +data "nutanix_lcm_entity_v2" "entity-after-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id + lifecycle { + postcondition { + condition = self.ext_id == data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + error_message = "entity ext id changed" + } + postcondition { + condition = self.entity_version == local.lcm.entity_model_version + error_message = "entity version is not upgraded, current version: ${self.entity_version}" + } + postcondition { + condition = self.entity_model == local.lcm.entity_model + error_message = "entity model is changed, current model: ${self.entity_model}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade, data.nutanix_lcm_status_v2.status-after-upgrade] +} + +`, filepath) +} diff --git a/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go b/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go deleted file mode 100644 index b199e7506..000000000 --- a/nutanix/services/lcmv2/resource_nutanix_preload_artifacts_v2.go +++ /dev/null @@ -1,108 +0,0 @@ -package lcmv2 - -import ( - "context" - "encoding/json" - "log" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/common" - taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" - prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" - conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" - "github.com/terraform-providers/terraform-provider-nutanix/utils" -) - -func ResourcePreloadArtifactsV2() *schema.Resource { - return &schema.Resource{ - CreateContext: ResourcePreloadArtifactsV2Create, - ReadContext: ResourcePreloadArtifactsV2Read, - UpdateContext: ResourcePreloadArtifactsV2Update, - DeleteContext: ResourcePreloadArtifactsV2Delete, - Schema: map[string]*schema.Schema{ - "x_cluster_id": { - Type: schema.TypeString, - Required: true, - }, - "entity_update_specs": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "entity_uuid": { - Type: schema.TypeString, - Required: true, - }, - "entity_type": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, - }, - } -} - -func ResourcePreloadArtifactsV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - conn := meta.(*conns.Client).LcmAPI - - clusterId := d.Get("x_cluster_id").(string) - - body := common.NewPreloadSpec() - - entityUpdateSpecs := d.Get("entity_update_specs").([]interface{}) - - body.EntityUpdateSpecs = expandEntityUpdateSpecs(entityUpdateSpecs) - - resp, err := conn.LcmEntitiesAPIInstance.PreloadArtifacts(body, utils.StringPtr(clusterId)) - if err != nil { - return diag.Errorf("error while Perform Preload Artifacts: %v", err) - } - - TaskRef := resp.Data.GetValue().(taskRef.TaskReference) - taskUUID := TaskRef.ExtId - - // calling group API to poll for completion of task - taskconn := meta.(*conns.Client).PrismAPI - - // Wait for the Config Update to be successful - stateConf := &resource.StateChangeConf{ - Pending: []string{"QUEUED", "RUNNING", "PENDING"}, - Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), - Timeout: d.Timeout(schema.TimeoutCreate), - } - - if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { - return diag.Errorf("LCM Upgrade task failed: %s", errWaitTask) - } - - resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) - if err != nil { - return diag.Errorf("error while fetching the Preload Artifacts task : %v", err) - } - - task := resourceUUID.Data.GetValue().(prismConfig.Task) - aJSON, _ := json.MarshalIndent(task, "", " ") - log.Printf("[DEBUG] LCM Preload Artifacts Task Response: %s", string(aJSON)) - - // randomly generating the id - d.SetId(utils.GenUUID()) - - return ResourcePreloadArtifactsV2Read(ctx, d, meta) -} - -func ResourcePreloadArtifactsV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil -} - -func ResourcePreloadArtifactsV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil -} - -func ResourcePreloadArtifactsV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil -} From 010d1f472c511a9f0d328bdededc3145f9686e07 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 16:48:43 +0200 Subject: [PATCH 23/39] update json var file with lcm vars --- test_config_v2.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test_config_v2.json b/test_config_v2.json index 019864caa..a1349c59e 100644 --- a/test_config_v2.json +++ b/test_config_v2.json @@ -215,12 +215,7 @@ "iscsi_ip": "", "iscsi_ip1": "", "dns_servers": ["", ""], - "ntp_servers": [ - "", - "", - "", - "" - ], + "ntp_servers": ["", "", "", ""], "smtp_server": { "ip": "", "port": 25, @@ -237,5 +232,9 @@ "username": "", "password": "" } + }, + "lcm": { + "entity_model": "", + "entity_model_version": "" } } From 27bbb06f10e3dbf55e17cf126bf637fe4661d254 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 16:49:20 +0200 Subject: [PATCH 24/39] docs and examples for lcm upgrade --- examples/lcm_upgrade_v2/main.tf | 104 ++++++++++++++ examples/lcm_upgrade_v2/terraform.tfvars | 5 + examples/lcm_upgrade_v2/variables.tf | 13 ++ .../r/nutanix_lcm_upgrade_v2.html.markdown | 134 ++++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 examples/lcm_upgrade_v2/main.tf create mode 100644 examples/lcm_upgrade_v2/terraform.tfvars create mode 100644 examples/lcm_upgrade_v2/variables.tf create mode 100644 website/docs/r/nutanix_lcm_upgrade_v2.html.markdown diff --git a/examples/lcm_upgrade_v2/main.tf b/examples/lcm_upgrade_v2/main.tf new file mode 100644 index 000000000..359e6e564 --- /dev/null +++ b/examples/lcm_upgrade_v2/main.tf @@ -0,0 +1,104 @@ +terraform { + required_providers { + nutanix = { + source = "nutanix/nutanix" + version = "2.1.0" + } + } +} + +#defining nutanix configuration +provider "nutanix" { + username = var.nutanix_username + password = var.nutanix_password + endpoint = var.nutanix_endpoint + port = 9440 + insecure = true +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq 'Calm Policy Engine'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + +resource "nutanix_lcm_prechecks_v2" "pre-checks" { + x_cluster_id = local.pcExtID + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = "4.0.0" + } + depends_on = [nutanix_lcm_perform_inventory_v2.inventory] +} + +# check if there is any operation in progress before starting the upgrade +data "nutanix_lcm_status_v2" "status-before-upgrade" { + x_cluster_id = local.pcExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_prechecks_v2.pre-checks] +} + +# upgrade the entity +resource "nutanix_lcm_upgrade_v2" "upgrade" { + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = "4.0.0" + } + depends_on = [data.nutanix_lcm_status_v2.status-before-upgrade] +} + +# check if there is any operation in progress after upgrade +data "nutanix_lcm_status_v2" "status-after-upgrade" { + x_cluster_id = local.pcExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade] +} + +# fetch the entity after upgrade +data "nutanix_lcm_entity_v2" "entity-after-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id + lifecycle { + postcondition { + condition = self.ext_id == data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + error_message = "entity ext id changed" + } + postcondition { + condition = self.entity_version == "4.0.0" + error_message = "entity version is not upgraded, current version: ${self.entity_version}" + } + postcondition { + condition = self.entity_model == "Calm Policy Engine" + error_message = "entity model is changed, current model: ${self.entity_model}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade, data.nutanix_lcm_status_v2.status-after-upgrade] +} + + diff --git a/examples/lcm_upgrade_v2/terraform.tfvars b/examples/lcm_upgrade_v2/terraform.tfvars new file mode 100644 index 000000000..867888ffc --- /dev/null +++ b/examples/lcm_upgrade_v2/terraform.tfvars @@ -0,0 +1,5 @@ +#define values to the variables to be used in terraform file +nutanix_username = "admin" +nutanix_password = "password" +nutanix_endpoint = "10.xx.xx.xx" +nutanix_port = 9440 diff --git a/examples/lcm_upgrade_v2/variables.tf b/examples/lcm_upgrade_v2/variables.tf new file mode 100644 index 000000000..dcd130ec8 --- /dev/null +++ b/examples/lcm_upgrade_v2/variables.tf @@ -0,0 +1,13 @@ +#define the type of variables to be used in terraform file +variable "nutanix_username" { + type = string +} +variable "nutanix_password" { + type = string +} +variable "nutanix_endpoint" { + type = string +} +variable "nutanix_port" { + type = string +} diff --git a/website/docs/r/nutanix_lcm_upgrade_v2.html.markdown b/website/docs/r/nutanix_lcm_upgrade_v2.html.markdown new file mode 100644 index 000000000..038fde1f5 --- /dev/null +++ b/website/docs/r/nutanix_lcm_upgrade_v2.html.markdown @@ -0,0 +1,134 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_upgrade_v2" +sidebar_current: "docs-nutanix-lcm-upgrade-v2" +description: |- + Perform upgrade operation to a specific target version for discovered LCM entity/entities. +--- + +# nutanix_lcm_upgrade_v2 + +Perform upgrade operation to a specific target version for discovered LCM entity/entities. + + +## Example + +```hcl + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq 'Calm Policy Engine'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + +resource "nutanix_lcm_prechecks_v2" "pre-checks" { + x_cluster_id = local.pcExtID + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = "4.0.0" + } + depends_on = [nutanix_lcm_perform_inventory_v2.inventory] +} + +# check if there is any operation in progress before starting the upgrade +data "nutanix_lcm_status_v2" "status-before-upgrade" { + x_cluster_id = local.pcExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_prechecks_v2.pre-checks] +} + +# upgrade the entity +resource "nutanix_lcm_upgrade_v2" "upgrade" { + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = "4.0.0" + } + depends_on = [data.nutanix_lcm_status_v2.status-before-upgrade] +} + +# check if there is any operation in progress after upgrade +data "nutanix_lcm_status_v2" "status-after-upgrade" { + x_cluster_id = local.pcExtID + lifecycle { + postcondition { + condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" + error_message = "operation is in progress: ${self.in_progress_operation[0].operation_type}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade] +} + +# fetch the entity after upgrade +data "nutanix_lcm_entity_v2" "entity-after-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id + lifecycle { + postcondition { + condition = self.ext_id == data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + error_message = "entity ext id changed" + } + postcondition { + condition = self.entity_version == "4.0.0" + error_message = "entity version is not upgraded, current version: ${self.entity_version}" + } + postcondition { + condition = self.entity_model == "Calm Policy Engine" + error_message = "entity model is changed, current model: ${self.entity_model}" + } + } + depends_on = [nutanix_lcm_upgrade_v2.upgrade, data.nutanix_lcm_status_v2.status-after-upgrade] +} + +``` + +## Argument Reference +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. +* `management_server`: (Optional) Cluster management server configuration used while updating clusters with ESX or Hyper-V. +* `entity_update_specs`: (Required) List of entity update objects for getting recommendations. +* `skipped_precheck_flags`: (Optional) List of prechecks to skip. The allowed value is 'powerOffUvms' that skips the pinned VM prechecks. Items Enum: `POWER_OFF_UVMS` +* `auto_handle_flags`: (Optional) List of automated system operations to perform, to avoid precheck failure and let the system restore state after an update is complete. The allowed flag is: - 'powerOffUvms': This allows the system to automatically power off user VMs which cannot be migrated to other hosts and power them on when the update is done. This option can avoid pinned VM precheck failure on the host which needs to enter maintenance mode during the update and allow the update to go through. Items Enum: `POWER_OFF_UVMS` +* `max_wait_time_in_secs`: (Optional) Number of seconds LCM waits for the VMs to come up after exiting host maintenance mode. Value in Range [ 60 .. 86400] + +### Management Server +The `management_server` attribute supports the following: + +* `hypervisor_type`: (Required) Type of Hypervisor present in the cluster. Enum Values: + * "HYPERV" : Hyper-V Hypervisor. + * "ESX" : ESX Hypervisor. + * "AHV" : Nutanix AHV Hypervisor. +* `ip`: (Required) IP address of the management server. +* `username`: (Required) Username to login to the management server. +* `password`: (Required) Password to login to the management server. + +### Entity Update Specs +The `entity_update_specs` attribute supports the following: + +* `entity_uuid`: (Required) UUID of the LCM entity. +* `to_version`: (Required) Version to upgrade to. + + +See detailed information in [Nutanix LCM Upgrades v4](https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Upgrades/operation/performUpgrade). + From 90b5f00e1021576771c86a8c74c83926e3c59fea Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:07:34 +0200 Subject: [PATCH 25/39] fix lcm upgrade test --- nutanix/provider/provider.go | 1 - .../lcmv2/resource_nutanix_lcm_upgrade_v2_test.go | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 639669996..3e4d192e9 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -391,7 +391,6 @@ func Provider() *schema.Provider { "nutanix_clusters_discover_unconfigured_nodes_v2": clustersv2.ResourceNutanixClusterDiscoverUnconfiguredNodesV2(), "nutanix_clusters_unconfigured_node_networks_v2": clustersv2.ResourceNutanixClusterUnconfiguredNodeNetworkV2(), "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), - "nutanix_lcm_preload_artifacts_v2": lcmv2.ResourcePreloadArtifactsV2(), "nutanix_lcm_prechecks_v2": lcmv2.ResourceNutanixPreChecksV2(), "nutanix_lcm_upgrade_v2": lcmv2.ResourceLcmUpgradeV2(), }, diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go index 21c4d9651..030004185 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2_test.go @@ -46,7 +46,6 @@ func TestAccV2NutanixLcmUpgrade_Basic(t *testing.T) { resource.TestCheckResourceAttrPair(resourceNameLcmPreChecks, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), // upgrade checks - resource.TestCheckResourceAttrSet(resourceNameLcmUpgrade, "x_cluster_id"), resource.TestCheckResourceAttr(resourceNameLcmUpgrade, "entity_update_specs.#", "1"), resource.TestCheckResourceAttrPair(resourceNameLcmUpgrade, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), resource.TestCheckResourceAttr(resourceNameLcmUpgrade, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), @@ -65,10 +64,6 @@ func TestAccV2NutanixLcmUpgrade_Basic(t *testing.T) { func testLcmUpgradeConfig() string { return fmt.Sprintf(` -# list Clusters -data "nutanix_clusters_v2" "clusters" { - filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" -} # List Prism Central data "nutanix_clusters_v2" "pc" { @@ -76,7 +71,6 @@ data "nutanix_clusters_v2" "pc" { } locals { - clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id config = jsondecode(file("%[1]s")) lcm = local.config.lcm @@ -128,7 +122,7 @@ resource "nutanix_lcm_upgrade_v2" "upgrade" { # check if there is any operation in progress after upgrade data "nutanix_lcm_status_v2" "status-after-upgrade" { - x_cluster_id = local.clusterExtID + x_cluster_id = local.pcExtID lifecycle { postcondition { condition = self.in_progress_operation[0].operation_type == "" && self.in_progress_operation[0].operation_id == "" From a4e1341f84715cae3109683e30fd31ffd782c2f4 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:07:44 +0200 Subject: [PATCH 26/39] lint fix --- nutanix/services/lcmv2/main_test.go | 2 +- nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go | 2 +- nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go | 1 - .../services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/nutanix/services/lcmv2/main_test.go b/nutanix/services/lcmv2/main_test.go index 5f50ee66f..277f1a08d 100644 --- a/nutanix/services/lcmv2/main_test.go +++ b/nutanix/services/lcmv2/main_test.go @@ -9,7 +9,7 @@ import ( type TestConfig struct { Lcm struct { - EntityModel string `json:"entity_model"` + EntityModel string `json:"entity_model"` EntityModelVersion string `json:"entity_model_version"` } `json:"lcm"` } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go index fbbd46719..44c7f3bb9 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go @@ -38,7 +38,7 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterId := d.Get("x_cluster_id").(string) - + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterId)) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go index fba096334..95cdc5f77 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go @@ -30,7 +30,6 @@ func TestAccV2NutanixLcmPerformInventory_Basic(t *testing.T) { resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), // perform inventory checks resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), - ), }, }, diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go index 4423f58f1..b4ba6ab38 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2_test.go @@ -35,7 +35,6 @@ func TestAccV2NutanixLcmPrechecks_Basic(t *testing.T) { resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.#", "1"), resource.TestCheckResourceAttrPair(resourceNameLcmPreChecks, "entity_update_specs.0.entity_uuid", datasourceNameLcmEntityBeforeUpgrade, "ext_id"), resource.TestCheckResourceAttr(resourceNameLcmPreChecks, "entity_update_specs.0.to_version", testVars.Lcm.EntityModelVersion), - ), }, }, From 2203d5084e7d43a3ba33a2ae8b03c7a357f6d033 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:14:54 +0200 Subject: [PATCH 27/39] lint fixes --- nutanix/services/lcmv2/data_source_lcm_config.go | 4 ++-- nutanix/services/lcmv2/resource_nutanix_lcm_config.go | 4 ++-- .../services/lcmv2/resource_nutanix_lcm_inventory_v2.go | 6 +++--- .../services/lcmv2/resource_nutanix_lcm_upgrade_v2.go | 9 +++++---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go index 294c3bf96..4e67148be 100644 --- a/nutanix/services/lcmv2/data_source_lcm_config.go +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -85,9 +85,9 @@ func DatasourceNutanixLcmConfigV2() *schema.Resource { func DatasourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) + clusterExtID := d.Get("x_cluster_id").(string) - resp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterId)) + resp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterExtID)) if err != nil { return diag.Errorf("error while fetching the Lcm config : %v", err) } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 116cde15c..9b95c0cde 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -86,7 +86,7 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) + clusterExtID := d.Get("x_cluster_id").(string) if_match, ok := d.Get("if_match").(string) if !ok || if_match == "" { return diag.Errorf("if_match is required and cannot be null or empty") @@ -94,7 +94,7 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat body := lcmconfigimport1.Config{} - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, utils.StringPtr(clusterId)) + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, utils.StringPtr(clusterExtID)) if err != nil { return diag.Errorf("error while updating the LCM config: %v", err) } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go index 44c7f3bb9..d3dcbb1d1 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go @@ -37,9 +37,9 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) + clusterExtID := d.Get("x_cluster_id").(string) - resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterId)) + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterExtID)) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) } @@ -49,7 +49,7 @@ func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.R // calling group API to poll for completion of task taskconn := meta.(*conns.Client).PrismAPI - // Wait for the inventorty to be successful + // Wait for the inventory to be successful stateConf := &resource.StateChangeConf{ Pending: []string{"QUEUED", "RUNNING", "PENDING"}, Target: []string{"SUCCEEDED"}, diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go index 4ea9aa758..932619247 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_upgrade_v2.go @@ -88,7 +88,7 @@ func ResourceLcmUpgradeV2() *schema.Resource { "max_wait_time_in_secs": { Type: schema.TypeInt, Optional: true, - ValidateFunc: validation.IntBetween(60, 86400), + ValidateFunc: validation.IntBetween(60, 86400), //nolint:gomnd }, }, } @@ -189,13 +189,14 @@ func expandManagementServer(managementServer interface{}) *common.ManagementServ } func expandHypervisorType(hypervisorType string) *common.HypervisorType { - if hypervisorType == "HYPERV" { + switch hypervisorType { + case "HYPERV": p := common.HYPERVISORTYPE_HYPERV return &p - } else if hypervisorType == "ESX" { + case "ESX": p := common.HYPERVISORTYPE_ESX return &p - } else if hypervisorType == "AHV" { + case "AHV": p := common.HYPERVISORTYPE_AHV return &p } From d6e6826d554943ae6ee629af5bd8e74ede127728 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:15:48 +0200 Subject: [PATCH 28/39] lint fixes --- nutanix/services/lcmv2/resource_nutanix_lcm_config.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 9b95c0cde..2cefdcdb5 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -87,10 +87,6 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterExtID := d.Get("x_cluster_id").(string) - if_match, ok := d.Get("if_match").(string) - if !ok || if_match == "" { - return diag.Errorf("if_match is required and cannot be null or empty") - } body := lcmconfigimport1.Config{} From 4d259357f75ee4df4f2e7df9aaabe26fa87b8740 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:18:26 +0200 Subject: [PATCH 29/39] lint fixes --- nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go index 2a27bb387..b8ff86ac4 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go @@ -85,7 +85,7 @@ func ResourceNutanixPreChecksV2() *schema.Resource { func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI - clusterId := d.Get("x_cluster_id").(string) + clusterExtID := d.Get("x_cluster_id").(string) body := preCheckConfig.NewPrechecksSpec() if managementServer, ok := d.GetOk("management_server"); ok { @@ -98,7 +98,7 @@ func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.Resource body.SkippedPrecheckFlags = expandSystemAutoMgmtFlag(skippedPrecheckFlags.([]interface{})) } - resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(body, utils.StringPtr(clusterId)) + resp, err := conn.LcmPreChecksAPIInstance.PerformPrechecks(body, utils.StringPtr(clusterExtID)) if err != nil { return diag.Errorf("error while performing the prechecks: %v", err) } From 1eae4dc9945d0efc28e35a4204c7afb617ba1429 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 17:50:57 +0200 Subject: [PATCH 30/39] fix precheck, call create in Read ctx instead of update ctx --- nutanix/services/lcmv2/resource_nutanix_lcm_config.go | 4 ---- nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go | 6 +----- nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go | 4 ++-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 2cefdcdb5..4a92dcd9c 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -19,10 +19,6 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { UpdateContext: ResourceNutanixLcmConfigV2Update, DeleteContext: ResourceNutanixLcmConfigV2Delete, Schema: map[string]*schema.Schema{ - "if_match": { - Type: schema.TypeString, - Required: true, - }, "x_cluster_id": { Type: schema.TypeString, Required: true, diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go index d3dcbb1d1..f0cfd6b60 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go @@ -27,10 +27,6 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { Type: schema.TypeString, Required: true, }, - "ext_id": { - Type: schema.TypeString, - Computed: true, - }, }, } } @@ -63,7 +59,7 @@ func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.R resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) if err != nil { - return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + return diag.Errorf("error while fetching the Lcm inventory task : %v", err) } task := resourceUUID.Data.GetValue().(prismConfig.Task) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go index b8ff86ac4..cc0889875 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_prechecks_v2.go @@ -135,11 +135,11 @@ func ResourceNutanixLcmPreChecksV2Create(ctx context.Context, d *schema.Resource } func ResourceNutanixLcmPreChecksV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return ResourceNutanixLcmPreChecksV2Create(ctx, d, meta) + return nil } func ResourceNutanixLcmPreChecksV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil + return ResourceNutanixLcmPreChecksV2Create(ctx, d, meta) } func ResourceNutanixLcmPreChecksV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { From 24715efd65fd01e6af0bf959dd2c35e7a75ae5a7 Mon Sep 17 00:00:00 2001 From: Haroon-Dweikat-Ntx Date: Wed, 19 Feb 2025 19:33:24 +0200 Subject: [PATCH 31/39] docs and examples for lcm entities --- examples/lcm_entities_v2/main.tf | 41 +++++ examples/lcm_entities_v2/terraform.tfvars | 5 + examples/lcm_entities_v2/variables.tf | 13 ++ website/docs/d/lcm_entities_v2.html.markdown | 162 +++++++++++++++++++ website/docs/d/lcm_entity_v2.html.markdown | 126 +++++++++++++++ 5 files changed, 347 insertions(+) create mode 100644 examples/lcm_entities_v2/main.tf create mode 100644 examples/lcm_entities_v2/terraform.tfvars create mode 100644 examples/lcm_entities_v2/variables.tf create mode 100644 website/docs/d/lcm_entities_v2.html.markdown create mode 100644 website/docs/d/lcm_entity_v2.html.markdown diff --git a/examples/lcm_entities_v2/main.tf b/examples/lcm_entities_v2/main.tf new file mode 100644 index 000000000..533d8f9d3 --- /dev/null +++ b/examples/lcm_entities_v2/main.tf @@ -0,0 +1,41 @@ +terraform { + required_providers { + nutanix = { + source = "nutanix/nutanix" + version = "2.1.0" + } + } +} + +#defining nutanix configuration +provider "nutanix" { + username = var.nutanix_username + password = var.nutanix_password + endpoint = var.nutanix_endpoint + port = 9440 + insecure = true +} + +# get all entities +data "nutanix_lcm_entities_v2" "lcm-entities" {} + +# get filtered entities +data "nutanix_lcm_entities_v2" "lcm-entities-filtered" { + filter = "entityModel eq 'Calm Policy Engine'" +} + +# get limited entities +data "nutanix_lcm_entities_v2" "lcm-entities-limited" { + limit = 5 +} + +# get filtered and limited entities +data "nutanix_lcm_entities_v2" "lcm-entities-filter-and-limit" { + filter = "startswith(entityModel,'Calm')" + limit = 5 +} + +# get specific entity +data "nutanix_lcm_entity_v2" "entity" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} diff --git a/examples/lcm_entities_v2/terraform.tfvars b/examples/lcm_entities_v2/terraform.tfvars new file mode 100644 index 000000000..867888ffc --- /dev/null +++ b/examples/lcm_entities_v2/terraform.tfvars @@ -0,0 +1,5 @@ +#define values to the variables to be used in terraform file +nutanix_username = "admin" +nutanix_password = "password" +nutanix_endpoint = "10.xx.xx.xx" +nutanix_port = 9440 diff --git a/examples/lcm_entities_v2/variables.tf b/examples/lcm_entities_v2/variables.tf new file mode 100644 index 000000000..dcd130ec8 --- /dev/null +++ b/examples/lcm_entities_v2/variables.tf @@ -0,0 +1,13 @@ +#define the type of variables to be used in terraform file +variable "nutanix_username" { + type = string +} +variable "nutanix_password" { + type = string +} +variable "nutanix_endpoint" { + type = string +} +variable "nutanix_port" { + type = string +} diff --git a/website/docs/d/lcm_entities_v2.html.markdown b/website/docs/d/lcm_entities_v2.html.markdown new file mode 100644 index 000000000..c4c6833fc --- /dev/null +++ b/website/docs/d/lcm_entities_v2.html.markdown @@ -0,0 +1,162 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_entities_v2" +sidebar_current: "docs-nutanix-datasource-lcm-entities-v2" +description: |- + Get details about all LCM entities. + +--- + +# nutanix_lcm_entities_v2 +Get details about all LCM entities. + + +## Example + +```hcl +data "nutanix_lcm_entity_v2" "entities" {} + +data "nutanix_lcm_entities_v2" "lcm-entities-filtered" { + filter = "entityModel eq 'Calm Policy Engine'" +} + +data "nutanix_lcm_entities_v2" "lcm-entities-limit" { + limit = 5 +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `page`: - A URL query parameter that specifies the page number of the result set. It must be a positive integer between 0 and the maximum number of pages that are available for that resource. Any number out of this range might lead to no results. +* `limit` : A URL query parameter that specifies the total number of records returned in the result set. Must be a positive integer between 1 and 100. Any number out of this range will lead to a validation error. If the limit is not provided, a default value of 50 records will be returned in the result set. +* `filter` :A URL query parameter that allows clients to filter a collection of resources. The expression specified with \$filter is evaluated for each resource in the collection, and only items where the expression evaluates to true are included in the response. Expression specified with the \$filter must conform to the OData V4.01 URL conventions. For example, filter '\$filter=name eq 'karbon-ntnx-1.0' would filter the result on cluster name 'karbon-ntnx1.0', filter '\$filter=startswith(name, 'C')' would filter on cluster name starting with 'C'. The filter can be applied to the following fields: clientName, createdBy, extId, createdTime, displayName, extId, isSystemDefined, lastUpdatedTime. + * The filter can be applied to the following fields: + * `clusterExtId` + * `entityClass` + * `entityModel` + * `entityType` + * `entityVersion` + * `hardwareVendor` +* `orderby` : A URL query parameter that allows clients to specify the sort criteria for the returned list of objects. Resources can be sorted in ascending order using asc or descending order using desc. If asc or desc are not specified, the resources will be sorted in ascending order by default. For example, '\$orderby=templateName desc' would get all templates sorted by templateName in descending order. The orderby can be applied to the following fields: createdTime, distinguishedName, displayName, extId, lastUpdatedTime. + * The orderby can be applied to the following fields: + * `entityClass` + * `entityModel` + * `entityType` + * `entityVersion` + * `hardwareVendor` +* `select` : A URL query parameter that allows clients to request a specific set of properties for each entity or complex type. Expression specified with the \$select must conform to the OData V4.01 URL conventions. If a \$select expression consists of a single select item that is an asterisk (i.e., *), then all properties on the matching resource will be returned. following fields: accessibleClients, accessibleEntityTypes, assignedUserGroupsCount, assignedUsersCount, clientName, createdBy, createdTime, description, displayName, extId, isSystemDefined, lastUpdatedTime, links, operations, tenantId. + * The select can be applied to the following fields: + * `entityClass` + * `entityModel` + * `entityType` + * `entityVersion` + * `hardwareVendor` + +## Attributes Reference +The following attributes are exported: + +* `entities`: List of LCM entities. + +### Entities +The `entities` attribute supports the following: + +* `tenant_id`: - A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: - A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. +* `entity_description`: Description of an LCM entity. +* `location_info`: Location info corresponds to a tuple of location type (either node/cluster) and ExtID +* `target_version`: The requested update version of an LCM entity. +* `last_updated_time`: UTC date and time in RFC-3339 format when the task was last updated. +* `device_id`: Unique identifier of an LCM entity e.g. "HDD serial number". +* `group_uuid`: UUID of the group that this LCM entity is part of. +* `entity_details`: Detailed information for the LCM entity. For example, firmware entities contain additional information about NIC and so on. +* `child_entities`: Component information for the payload based entity. +* `available_versions`: List of available versions for an LCM entity to update. +* `sub_entities`: A list of sub-entities applicable to the entity. +* `cluster_ext_id`: Cluster uuid on which the resource is present or operation is being performed. +* `hardware_vendor`: Hardware vendor information. + +### Location Info +The `location` attribute supports the following + +* `uuid`: Location UUID of the resource. +* `location_type`: Scope of entity represented in LCM. This could be either Node or cluster type. Enum Values: + * `PC`: Entity for which the scope is Prism Central wide. + * `NODE`: Entity that belongs to a node in the cluster. + * `CLUSTER`: Entity for which the scope is cluster wide. + +### Entity Details +The `entity_details` attribute supports the following + +* `name`: The key of the key-value pair. +* `value`: The value associated with the key for this key-value pair, string or integer or boolean or Array of strings or object or Array of MapOfString(objects) or Array of integers + +### Available Versions +The `available_versions` attribute supports the following + +* `version`: Version of the LCM entity. +* `status`: Status of the LCM entity. Enum Values: + * `AVAILABLE`: Available version. + * `EMERGENCY`: Emergency version. + * `RECOMMENDED`: Deprecated version. + * `STS`: Short-term supported version. + * `LTS`: Long-term supported version. + * `LATEST`: Latest version. + * `DEPRECATED`: Deprecated version. + * `ESTS`: Extended short-term supported version. + * `CRITICAL`: Critical version. +* `is_enabled`: Indicates if the available update is enabled. +* `available_version_uuid`: Available version UUID. +* `order`: Order of the available version. +* `disablement_reason`: Reason for disablement of the available version. +* `release_notes`: Release notes for the available version. +* `release_date`: Release date of the available version. +* `custom_message`: Custom message associated with the available version. +* `dependencies`: List of dependencies for the available version. + +#### Dependencies +The `dependencies` attribute supports the following + +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. +* `dependent_versions`: Information of the dependent entity versions for this available entity. + +#### Dependent Versions +The `dependent_versions` attribute supports the following + +* `name`: The key of the key-value pair. +* `value`: The value associated with the key for this key-value pair, string or integer or boolean or Array of strings or object or Array of MapOfString(objects) or Array of integers + +### Sub Entities +The `sub_entities` attribute supports the following + +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. + +See detailed information in [Nutanix LCM Entities V4](https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Entities/operation/listEntities). diff --git a/website/docs/d/lcm_entity_v2.html.markdown b/website/docs/d/lcm_entity_v2.html.markdown new file mode 100644 index 000000000..53167193f --- /dev/null +++ b/website/docs/d/lcm_entity_v2.html.markdown @@ -0,0 +1,126 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_entity_v2" +sidebar_current: "docs-nutanix-datasource-lcm-entity-v2" +description: |- + Get details about an LCM entity. +--- + +# nutanix_lcm_entity_v2 +Get details about an LCM entity. + +## Example + +```hcl +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = "613no9d0-7caf-49y7-k582-1db5a5df580c" +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `ext_id`:(Required) ExtId of the LCM entity. + +## Attributes Reference +The fooling attributes are exported: + +* `tenant_id`: - A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: - A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. +* `entity_description`: Description of an LCM entity. +* `location_info`: Location info corresponds to a tuple of location type (either node/cluster) and ExtID +* `target_version`: The requested update version of an LCM entity. +* `last_updated_time`: UTC date and time in RFC-3339 format when the task was last updated. +* `device_id`: Unique identifier of an LCM entity e.g. "HDD serial number". +* `group_uuid`: UUID of the group that this LCM entity is part of. +* `entity_details`: Detailed information for the LCM entity. For example, firmware entities contain additional information about NIC and so on. +* `child_entities`: Component information for the payload based entity. +* `available_versions`: List of available versions for an LCM entity to update. +* `sub_entities`: A list of sub-entities applicable to the entity. +* `cluster_ext_id`: Cluster uuid on which the resource is present or operation is being performed. +* `hardware_vendor`: Hardware vendor information. + +### Location Info +The `location` attribute supports the following + +* `uuid`: Location UUID of the resource. +* `location_type`: Scope of entity represented in LCM. This could be either Node or cluster type. Enum Values: + * `PC`: Entity for which the scope is Prism Central wide. + * `NODE`: Entity that belongs to a node in the cluster. + * `CLUSTER`: Entity for which the scope is cluster wide. + +### Entity Details +The `entity_details` attribute supports the following + +* `name`: The key of the key-value pair. +* `value`: The value associated with the key for this key-value pair, string or integer or boolean or Array of strings or object or Array of MapOfString(objects) or Array of integers + +### Available Versions +The `available_versions` attribute supports the following + +* `version`: Version of the LCM entity. +* `status`: Status of the LCM entity. Enum Values: + * `AVAILABLE`: Available version. + * `EMERGENCY`: Emergency version. + * `RECOMMENDED`: Deprecated version. + * `STS`: Short-term supported version. + * `LTS`: Long-term supported version. + * `LATEST`: Latest version. + * `DEPRECATED`: Deprecated version. + * `ESTS`: Extended short-term supported version. + * `CRITICAL`: Critical version. +* `is_enabled`: Indicates if the available update is enabled. +* `available_version_uuid`: Available version UUID. +* `order`: Order of the available version. +* `disablement_reason`: Reason for disablement of the available version. +* `release_notes`: Release notes for the available version. +* `release_date`: Release date of the available version. +* `custom_message`: Custom message associated with the available version. +* `dependencies`: List of dependencies for the available version. + +#### Dependencies +The `dependencies` attribute supports the following + +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. +* `dependent_versions`: Information of the dependent entity versions for this available entity. + +#### Dependent Versions +The `dependent_versions` attribute supports the following + +* `name`: The key of the key-value pair. +* `value`: The value associated with the key for this key-value pair, string or integer or boolean or Array of strings or object or Array of MapOfString(objects) or Array of integers + +### Sub Entities +The `sub_entities` attribute supports the following + +* `tenant_id`: A globally unique identifier that represents the tenant that owns this entity. The system automatically assigns it, and it and is immutable from an API consumer perspective (some use cases may cause this Id to change - For instance, a use case may require the transfer of ownership of the entity, but these cases are handled automatically on the server). +* `ext_id`: A globally unique identifier of an instance that is suitable for external consumption. +* `links`: A HATEOAS style link for the response. Each link contains a user-friendly name identifying the link and an address for retrieving the particular resource. +* `entity_class`: LCM entity class. +* `entity_model`: LCM entity model. +* `entity_type`: Type of an LCM entity. Enum Values: + * `FIRMWARE`: LCM entity type firmware. + * `SOFTWARE`: LCM entity type software. +* `entity_version`: Current version of an LCM entity. +* `hardware_family`: A hardware family for a LCM entity. + +See detailed information in [Nutanix LCM Entity V4](https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Entities/operation/getEntityById). From 5922ea69c8774da9b8ad3a50992b914bb2bb9d83 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Thu, 20 Feb 2025 17:34:38 +0530 Subject: [PATCH 32/39] Add changes for update config --- nutanix/provider/provider.go | 1 + .../lcmv2/resource_nutanix_lcm_config.go | 104 ++++++++++++------ 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/nutanix/provider/provider.go b/nutanix/provider/provider.go index 3e4d192e9..6b779da2d 100644 --- a/nutanix/provider/provider.go +++ b/nutanix/provider/provider.go @@ -393,6 +393,7 @@ func Provider() *schema.Provider { "nutanix_lcm_perform_inventory_v2": lcmv2.ResourceNutanixLcmPerformInventoryV2(), "nutanix_lcm_prechecks_v2": lcmv2.ResourceNutanixPreChecksV2(), "nutanix_lcm_upgrade_v2": lcmv2.ResourceLcmUpgradeV2(), + "nutanix_lcm_config_v2": lcmv2.ResourceNutanixLcmConfigV2(), }, ConfigureContextFunc: providerConfigure, } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 4a92dcd9c..2615e2d8e 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -2,12 +2,16 @@ package lcmv2 import ( "context" + "encoding/json" + "log" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - taskRef "github.com/nutanix/ntnx-api-golang-clients/clustermgmt-go-client/v4/models/prism/v4/config" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" ) @@ -23,58 +27,33 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { Type: schema.TypeString, Required: true, }, - "tenant_id": { - Type: schema.TypeString, - Computed: true, - }, "ext_id": { Type: schema.TypeString, Computed: true, }, - "links": schemaForLinks(), "url": { Type: schema.TypeString, - Computed: true, + Optional: true, }, "is_auto_inventory_enabled": { Type: schema.TypeBool, - Computed: true, + Optional: true, }, "auto_inventory_schedule": { Type: schema.TypeString, - Computed: true, - }, - "version": { - Type: schema.TypeString, - Computed: true, - }, - "display_version": { - Type: schema.TypeString, - Computed: true, + Optional: true, }, "connectivity_type": { Type: schema.TypeString, - Computed: true, + Optional: true, }, "is_https_enabled": { Type: schema.TypeBool, - Computed: true, - }, - "supported_software_entities": { - Type: schema.TypeList, - Computed: true, - }, - "deprecated_software_entities": { - Type: schema.TypeList, - Computed: true, - }, - "is_framework_bundle_uploaded": { - Type: schema.TypeBool, - Computed: true, + Optional: true, }, "has_module_auto_upgrade_enabled": { Type: schema.TypeBool, - Computed: true, + Optional: true, }, }, } @@ -84,9 +63,52 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat conn := meta.(*conns.Client).LcmAPI clusterExtID := d.Get("x_cluster_id").(string) - body := lcmconfigimport1.Config{} + readResp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterExtID)) + if err != nil { + return diag.Errorf("error while fetching the Lcm config : %v", err) + } + + // Extract E-Tag Header + etagValue := conn.LcmConfigAPIInstance.ApiClient.GetEtag(readResp) + args := make(map[string]interface{}) + args["If-Match"] = utils.StringPtr(etagValue) + + body := &lcmconfigimport1.Config{} + var connectivityTypeMap = map[string]resources.ConnectivityType{ + "$UNKNOWN": resources.CONNECTIVITYTYPE_UNKNOWN, + "$REDACTED": resources.CONNECTIVITYTYPE_REDACTED, + "CONNECTED_SITE": resources.CONNECTIVITYTYPE_CONNECTED_SITE, + "DARKSITE_WEB_SERVER": resources.CONNECTIVITYTYPE_DARKSITE_WEB_SERVER, + "DARKSITE_DIRECT_UPLOAD": resources.CONNECTIVITYTYPE_DARKSITE_DIRECT_UPLOAD, + } + + if url, ok := d.GetOk("url"); ok { + body.Url = utils.StringPtr(url.(string)) + } + + if isAutoInventoryEnabled, ok := d.GetOk("is_auto_inventory_enabled"); ok { + body.IsAutoInventoryEnabled = utils.BoolPtr(isAutoInventoryEnabled.(bool)) + } + if autoInventorySchedule, ok := d.GetOk("auto_inventory_schedule"); ok { + body.AutoInventorySchedule = utils.StringPtr(autoInventorySchedule.(string)) + } + if connectivityType, ok := d.GetOk("connectivity_type"); ok { + if strValue, isString := connectivityType.(string); isString { + if enumValue, exists := connectivityTypeMap[strValue]; exists { + body.ConnectivityType = &enumValue + } + } + } + if isHttpsEnabled, ok := d.GetOk("is_https_enabled"); ok { + body.IsHttpsEnabled = utils.BoolPtr(isHttpsEnabled.(bool)) + } + if hasModuleAutoUpgradeEnabled, ok := d.GetOk("has_module_auto_upgrade_enabled"); ok { + body.HasModuleAutoUpgradeEnabled = utils.BoolPtr(hasModuleAutoUpgradeEnabled.(bool)) + } + aJSON, _ := json.MarshalIndent(body, "", " ") + log.Printf("[DEBUG] LCM Update Config Request Spec: %s", string(aJSON)) - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, utils.StringPtr(clusterExtID)) + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, utils.StringPtr(clusterExtID), args) if err != nil { return diag.Errorf("error while updating the LCM config: %v", err) } @@ -95,7 +117,6 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat taskUUID := TaskRef.ExtId // calling group API to poll for completion of task - taskconn := meta.(*conns.Client).PrismAPI // Wait for the Config Update to be successful @@ -109,7 +130,18 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { return diag.Errorf("Config Update task failed: %s", errWaitTask) } - d.SetId(*taskUUID) + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + } + + task := resourceUUID.Data.GetValue().(prismConfig.Task) + aJSON, _ = json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] LCM Config update Task Details: %s", string(aJSON)) + + // randomly generating the id + d.SetId(utils.GenUUID()) return nil } From bddb32d45858bf072d42a03ea4c22a5a38b3018b Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 24 Feb 2025 10:29:40 +0530 Subject: [PATCH 33/39] Make cluster if field optional as per api reference documentation --- nutanix/services/lcmv2/data_source_lcm_config.go | 11 ++++++++--- .../services/lcmv2/resource_nutanix_lcm_config.go | 13 +++++++++---- .../lcmv2/resource_nutanix_lcm_inventory_v2.go | 11 ++++++++--- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/nutanix/services/lcmv2/data_source_lcm_config.go b/nutanix/services/lcmv2/data_source_lcm_config.go index 4e67148be..1a38e1961 100644 --- a/nutanix/services/lcmv2/data_source_lcm_config.go +++ b/nutanix/services/lcmv2/data_source_lcm_config.go @@ -16,7 +16,7 @@ func DatasourceNutanixLcmConfigV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "tenant_id": { Type: schema.TypeString, @@ -86,8 +86,13 @@ func DatasourceNutanixLcmConfigV2() *schema.Resource { func DatasourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterExtID := d.Get("x_cluster_id").(string) - - resp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterExtID)) + var clusterId *string + if clusterExtID != "" { + clusterId = utils.StringPtr(clusterExtID) + } else { + clusterId = nil + } + resp, err := conn.LcmConfigAPIInstance.GetConfig(clusterId) if err != nil { return diag.Errorf("error while fetching the Lcm config : %v", err) } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go index 2615e2d8e..9fd760413 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go @@ -25,7 +25,7 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "ext_id": { Type: schema.TypeString, @@ -62,8 +62,13 @@ func ResourceNutanixLcmConfigV2() *schema.Resource { func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterExtID := d.Get("x_cluster_id").(string) - - readResp, err := conn.LcmConfigAPIInstance.GetConfig(utils.StringPtr(clusterExtID)) + var clusterId *string + if clusterExtID != "" { + clusterId = utils.StringPtr(clusterExtID) + } else { + clusterId = nil + } + readResp, err := conn.LcmConfigAPIInstance.GetConfig(clusterId) if err != nil { return diag.Errorf("error while fetching the Lcm config : %v", err) } @@ -108,7 +113,7 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat aJSON, _ := json.MarshalIndent(body, "", " ") log.Printf("[DEBUG] LCM Update Config Request Spec: %s", string(aJSON)) - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, utils.StringPtr(clusterExtID), args) + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, clusterId, args) if err != nil { return diag.Errorf("error while updating the LCM config: %v", err) } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go index f0cfd6b60..c6f99cd02 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2.go @@ -25,7 +25,7 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { Schema: map[string]*schema.Schema{ "x_cluster_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, }, } @@ -34,8 +34,13 @@ func ResourceNutanixLcmPerformInventoryV2() *schema.Resource { func ResourceNutanixLcmPerformInventoryV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { conn := meta.(*conns.Client).LcmAPI clusterExtID := d.Get("x_cluster_id").(string) - - resp, err := conn.LcmInventoryAPIInstance.PerformInventory(utils.StringPtr(clusterExtID)) + var clusterId *string + if clusterExtID != "" { + clusterId = utils.StringPtr(clusterExtID) + } else { + clusterId = nil + } + resp, err := conn.LcmInventoryAPIInstance.PerformInventory(clusterId) if err != nil { return diag.Errorf("error while performing the inventory: %v", err) } From 856a68946c99ca26c504308ec5532a9eb22f3c44 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 24 Feb 2025 16:40:27 +0530 Subject: [PATCH 34/39] Rename files to follow a specifc format and add testcase for LCM config --- .../lcmv2/resource_nutanix_lcm_config_v2.go | 182 ++++++++++++++++++ .../resource_nutanix_lcm_config_v2_test.go | 65 +++++++ .../resource_nutanix_lcm_inventory_v2_test.go | 74 +++++++ 3 files changed, 321 insertions(+) create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go create mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2_test.go diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go new file mode 100644 index 000000000..9fd760413 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go @@ -0,0 +1,182 @@ +package lcmv2 + +import ( + "context" + "encoding/json" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" + taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" + prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func ResourceNutanixLcmConfigV2() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceNutanixLcmConfigV2Create, + ReadContext: ResourceNutanixLcmConfigV2Read, + UpdateContext: ResourceNutanixLcmConfigV2Update, + DeleteContext: ResourceNutanixLcmConfigV2Delete, + Schema: map[string]*schema.Schema{ + "x_cluster_id": { + Type: schema.TypeString, + Optional: true, + }, + "ext_id": { + Type: schema.TypeString, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Optional: true, + }, + "is_auto_inventory_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "auto_inventory_schedule": { + Type: schema.TypeString, + Optional: true, + }, + "connectivity_type": { + Type: schema.TypeString, + Optional: true, + }, + "is_https_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "has_module_auto_upgrade_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + }, + } +} + +func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).LcmAPI + clusterExtID := d.Get("x_cluster_id").(string) + var clusterId *string + if clusterExtID != "" { + clusterId = utils.StringPtr(clusterExtID) + } else { + clusterId = nil + } + readResp, err := conn.LcmConfigAPIInstance.GetConfig(clusterId) + if err != nil { + return diag.Errorf("error while fetching the Lcm config : %v", err) + } + + // Extract E-Tag Header + etagValue := conn.LcmConfigAPIInstance.ApiClient.GetEtag(readResp) + args := make(map[string]interface{}) + args["If-Match"] = utils.StringPtr(etagValue) + + body := &lcmconfigimport1.Config{} + var connectivityTypeMap = map[string]resources.ConnectivityType{ + "$UNKNOWN": resources.CONNECTIVITYTYPE_UNKNOWN, + "$REDACTED": resources.CONNECTIVITYTYPE_REDACTED, + "CONNECTED_SITE": resources.CONNECTIVITYTYPE_CONNECTED_SITE, + "DARKSITE_WEB_SERVER": resources.CONNECTIVITYTYPE_DARKSITE_WEB_SERVER, + "DARKSITE_DIRECT_UPLOAD": resources.CONNECTIVITYTYPE_DARKSITE_DIRECT_UPLOAD, + } + + if url, ok := d.GetOk("url"); ok { + body.Url = utils.StringPtr(url.(string)) + } + + if isAutoInventoryEnabled, ok := d.GetOk("is_auto_inventory_enabled"); ok { + body.IsAutoInventoryEnabled = utils.BoolPtr(isAutoInventoryEnabled.(bool)) + } + if autoInventorySchedule, ok := d.GetOk("auto_inventory_schedule"); ok { + body.AutoInventorySchedule = utils.StringPtr(autoInventorySchedule.(string)) + } + if connectivityType, ok := d.GetOk("connectivity_type"); ok { + if strValue, isString := connectivityType.(string); isString { + if enumValue, exists := connectivityTypeMap[strValue]; exists { + body.ConnectivityType = &enumValue + } + } + } + if isHttpsEnabled, ok := d.GetOk("is_https_enabled"); ok { + body.IsHttpsEnabled = utils.BoolPtr(isHttpsEnabled.(bool)) + } + if hasModuleAutoUpgradeEnabled, ok := d.GetOk("has_module_auto_upgrade_enabled"); ok { + body.HasModuleAutoUpgradeEnabled = utils.BoolPtr(hasModuleAutoUpgradeEnabled.(bool)) + } + aJSON, _ := json.MarshalIndent(body, "", " ") + log.Printf("[DEBUG] LCM Update Config Request Spec: %s", string(aJSON)) + + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, clusterId, args) + if err != nil { + return diag.Errorf("error while updating the LCM config: %v", err) + } + + TaskRef := resp.Data.GetValue().(taskRef.TaskReference) + taskUUID := TaskRef.ExtId + + // calling group API to poll for completion of task + taskconn := meta.(*conns.Client).PrismAPI + + // Wait for the Config Update to be successful + stateConf := &resource.StateChangeConf{ + Pending: []string{"QUEUED", "RUNNING", "PENDING"}, + Target: []string{"SUCCEEDED"}, + Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), + Timeout: d.Timeout(schema.TimeoutCreate), + } + + if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { + return diag.Errorf("Config Update task failed: %s", errWaitTask) + } + + resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) + if err != nil { + return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) + } + + task := resourceUUID.Data.GetValue().(prismConfig.Task) + aJSON, _ = json.MarshalIndent(task, "", " ") + log.Printf("[DEBUG] LCM Config update Task Details: %s", string(aJSON)) + + // randomly generating the id + d.SetId(utils.GenUUID()) + return nil +} + +func ResourceNutanixLcmConfigV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func ResourceNutanixLcmConfigV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return ResourceNutanixLcmConfigV2Create(ctx, d, meta) +} + +func ResourceNutanixLcmConfigV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + return nil +} + +func schemaForLinks() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rel": { + Type: schema.TypeString, + Computed: true, + }, + "href": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + } +} diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go new file mode 100644 index 000000000..62c53e812 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go @@ -0,0 +1,65 @@ +package lcmv2_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { + datasourceLcmConfigBeforeUpdate := "data.nutanix_lcm_config_v2.get-lcm-config-before-update" + resourceLcmConfig := "nutanix_lcm_config_v2.update-lcm-config" + datasourceLcmConfigAfterUpdate := "data.nutanix_lcm_config_v2.get-lcm-config-after-update" + + resource.Test(t, resource.TestCase{ + PreCheck: func() {}, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testLcmUpdateConfig(), + Check: resource.ComposeTestCheckFunc( + // Check Auto Inventory is disabled Before Update + resource.TestCheckResourceAttr(datasourceLcmConfigBeforeUpdate, "is_auto_inventory_enabled", "false"), + + // Update LCM Config Check + resource.TestCheckResourceAttr(resourceLcmConfig, "is_auto_inventory_enabled", "true"), + + // Check Auto Inventory is enabled after Update + resource.TestCheckResourceAttr(datasourceLcmConfigAfterUpdate, "is_auto_inventory_enabled", "true"), + ), + }, + }, + }) +} + +func testLcmUpdateConfig() string { + return ` +# Get LCM Config before Update +data "nutanix_lcm_config_v2" "get-lcm-config-before-update" { + lifecycle { + postcondition { + condition = self.is_auto_inventory_enabled == false + error_message = "Auto Inventory is already enabled, current value: ${self.is_auto_inventory_enabled}" + } + } +} + +# Update LCM Config: Enable auto inventory +resource "nutanix_lcm_config_v2" "update-lcm-config" { + is_auto_inventory_enabled = true + depends_on = [data.nutanix_lcm_config_v2.get-lcm-config-before-update] +} + +# Get LCM Config after Update +data "nutanix_lcm_config_v2" "get-lcm-config-after-update" { + lifecycle { + postcondition { + condition = self.is_auto_inventory_enabled == true + error_message = "Auto Inventory is not enabled, current value: ${self.is_auto_inventory_enabled}" + } + } + depends_on = [nutanix_lcm_config_v2.update-lcm-config] +} +` +} diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2_test.go new file mode 100644 index 000000000..95cdc5f77 --- /dev/null +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_inventory_v2_test.go @@ -0,0 +1,74 @@ +package lcmv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" +) + +const resourceNameLcmPerformInventory = "nutanix_lcm_perform_inventory_v2.inventory" + +func TestAccV2NutanixLcmPerformInventory_Basic(t *testing.T) { + datasourceNameLcmEntities := "data.nutanix_lcm_entities_v2.lcm-entities" + datasourceNameLcmEntityBeforeUpgrade := "data.nutanix_lcm_entity_v2.entity-before-upgrade" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccFoundationPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testLcmPerformInventoryConfig(), + Check: resource.ComposeTestCheckFunc( + // check if the entity model is present + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.#", "1"), + resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.0.entity_model", testVars.Lcm.EntityModel), + // check if the entity is present + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "ext_id"), + resource.TestCheckResourceAttr(datasourceNameLcmEntityBeforeUpgrade, "entity_model", testVars.Lcm.EntityModel), + resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), + // perform inventory checks + resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), + ), + }, + }, + }) +} + +func testLcmPerformInventoryConfig() string { + return fmt.Sprintf(` +# list Clusters +data "nutanix_clusters_v2" "clusters" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id + config = jsondecode(file("%[1]s")) + lcm = local.config.lcm +} + +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq '${local.lcm.entity_model}'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID + depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] +} + + +`, filepath) +} From 035b40aa6e846e7be97fab6a0616bb28eebfa99e Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 24 Feb 2025 17:13:29 +0530 Subject: [PATCH 35/39] change var names and commit deleted files change --- .../lcmv2/resource_nutanix_lcm_config.go | 182 ------------------ .../resource_nutanix_lcm_config_v2_test.go | 16 +- .../resource_nutanix_lcm_inventry_v2_test.go | 74 ------- 3 files changed, 8 insertions(+), 264 deletions(-) delete mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_config.go delete mode 100644 nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config.go deleted file mode 100644 index 9fd760413..000000000 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config.go +++ /dev/null @@ -1,182 +0,0 @@ -package lcmv2 - -import ( - "context" - "encoding/json" - "log" - - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" - lcmconfigimport1 "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/lifecycle/v4/resources" - taskRef "github.com/nutanix/ntnx-api-golang-clients/lifecycle-go-client/v4/models/prism/v4/config" - prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" - conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" - "github.com/terraform-providers/terraform-provider-nutanix/utils" -) - -func ResourceNutanixLcmConfigV2() *schema.Resource { - return &schema.Resource{ - CreateContext: ResourceNutanixLcmConfigV2Create, - ReadContext: ResourceNutanixLcmConfigV2Read, - UpdateContext: ResourceNutanixLcmConfigV2Update, - DeleteContext: ResourceNutanixLcmConfigV2Delete, - Schema: map[string]*schema.Schema{ - "x_cluster_id": { - Type: schema.TypeString, - Optional: true, - }, - "ext_id": { - Type: schema.TypeString, - Computed: true, - }, - "url": { - Type: schema.TypeString, - Optional: true, - }, - "is_auto_inventory_enabled": { - Type: schema.TypeBool, - Optional: true, - }, - "auto_inventory_schedule": { - Type: schema.TypeString, - Optional: true, - }, - "connectivity_type": { - Type: schema.TypeString, - Optional: true, - }, - "is_https_enabled": { - Type: schema.TypeBool, - Optional: true, - }, - "has_module_auto_upgrade_enabled": { - Type: schema.TypeBool, - Optional: true, - }, - }, - } -} - -func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - conn := meta.(*conns.Client).LcmAPI - clusterExtID := d.Get("x_cluster_id").(string) - var clusterId *string - if clusterExtID != "" { - clusterId = utils.StringPtr(clusterExtID) - } else { - clusterId = nil - } - readResp, err := conn.LcmConfigAPIInstance.GetConfig(clusterId) - if err != nil { - return diag.Errorf("error while fetching the Lcm config : %v", err) - } - - // Extract E-Tag Header - etagValue := conn.LcmConfigAPIInstance.ApiClient.GetEtag(readResp) - args := make(map[string]interface{}) - args["If-Match"] = utils.StringPtr(etagValue) - - body := &lcmconfigimport1.Config{} - var connectivityTypeMap = map[string]resources.ConnectivityType{ - "$UNKNOWN": resources.CONNECTIVITYTYPE_UNKNOWN, - "$REDACTED": resources.CONNECTIVITYTYPE_REDACTED, - "CONNECTED_SITE": resources.CONNECTIVITYTYPE_CONNECTED_SITE, - "DARKSITE_WEB_SERVER": resources.CONNECTIVITYTYPE_DARKSITE_WEB_SERVER, - "DARKSITE_DIRECT_UPLOAD": resources.CONNECTIVITYTYPE_DARKSITE_DIRECT_UPLOAD, - } - - if url, ok := d.GetOk("url"); ok { - body.Url = utils.StringPtr(url.(string)) - } - - if isAutoInventoryEnabled, ok := d.GetOk("is_auto_inventory_enabled"); ok { - body.IsAutoInventoryEnabled = utils.BoolPtr(isAutoInventoryEnabled.(bool)) - } - if autoInventorySchedule, ok := d.GetOk("auto_inventory_schedule"); ok { - body.AutoInventorySchedule = utils.StringPtr(autoInventorySchedule.(string)) - } - if connectivityType, ok := d.GetOk("connectivity_type"); ok { - if strValue, isString := connectivityType.(string); isString { - if enumValue, exists := connectivityTypeMap[strValue]; exists { - body.ConnectivityType = &enumValue - } - } - } - if isHttpsEnabled, ok := d.GetOk("is_https_enabled"); ok { - body.IsHttpsEnabled = utils.BoolPtr(isHttpsEnabled.(bool)) - } - if hasModuleAutoUpgradeEnabled, ok := d.GetOk("has_module_auto_upgrade_enabled"); ok { - body.HasModuleAutoUpgradeEnabled = utils.BoolPtr(hasModuleAutoUpgradeEnabled.(bool)) - } - aJSON, _ := json.MarshalIndent(body, "", " ") - log.Printf("[DEBUG] LCM Update Config Request Spec: %s", string(aJSON)) - - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, clusterId, args) - if err != nil { - return diag.Errorf("error while updating the LCM config: %v", err) - } - - TaskRef := resp.Data.GetValue().(taskRef.TaskReference) - taskUUID := TaskRef.ExtId - - // calling group API to poll for completion of task - taskconn := meta.(*conns.Client).PrismAPI - - // Wait for the Config Update to be successful - stateConf := &resource.StateChangeConf{ - Pending: []string{"QUEUED", "RUNNING", "PENDING"}, - Target: []string{"SUCCEEDED"}, - Refresh: taskStateRefreshPrismTaskGroup(taskconn, utils.StringValue(taskUUID)), - Timeout: d.Timeout(schema.TimeoutCreate), - } - - if _, errWaitTask := stateConf.WaitForStateContext(ctx); errWaitTask != nil { - return diag.Errorf("Config Update task failed: %s", errWaitTask) - } - - resourceUUID, err := taskconn.TaskRefAPI.GetTaskById(taskUUID, nil) - if err != nil { - return diag.Errorf("error while fetching the Lcm upgrade task : %v", err) - } - - task := resourceUUID.Data.GetValue().(prismConfig.Task) - aJSON, _ = json.MarshalIndent(task, "", " ") - log.Printf("[DEBUG] LCM Config update Task Details: %s", string(aJSON)) - - // randomly generating the id - d.SetId(utils.GenUUID()) - return nil -} - -func ResourceNutanixLcmConfigV2Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil -} - -func ResourceNutanixLcmConfigV2Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return ResourceNutanixLcmConfigV2Create(ctx, d, meta) -} - -func ResourceNutanixLcmConfigV2Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - return nil -} - -func schemaForLinks() *schema.Schema { - return &schema.Schema{ - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "rel": { - Type: schema.TypeString, - Computed: true, - }, - "href": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - } -} diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go index 62c53e812..89081a70c 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go @@ -8,9 +8,9 @@ import ( ) func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { - datasourceLcmConfigBeforeUpdate := "data.nutanix_lcm_config_v2.get-lcm-config-before-update" - resourceLcmConfig := "nutanix_lcm_config_v2.update-lcm-config" - datasourceLcmConfigAfterUpdate := "data.nutanix_lcm_config_v2.get-lcm-config-after-update" + datasourceLcmConfigBeforeUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_before_update" + resourceLcmConfig := "nutanix_lcm_config_v2.update_lcm_config" + datasourceLcmConfigAfterUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_after_update" resource.Test(t, resource.TestCase{ PreCheck: func() {}, @@ -36,7 +36,7 @@ func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { func testLcmUpdateConfig() string { return ` # Get LCM Config before Update -data "nutanix_lcm_config_v2" "get-lcm-config-before-update" { +data "nutanix_lcm_config_v2" "get_lcm_config_before_update" { lifecycle { postcondition { condition = self.is_auto_inventory_enabled == false @@ -46,20 +46,20 @@ data "nutanix_lcm_config_v2" "get-lcm-config-before-update" { } # Update LCM Config: Enable auto inventory -resource "nutanix_lcm_config_v2" "update-lcm-config" { +resource "nutanix_lcm_config_v2" "update_lcm_config" { is_auto_inventory_enabled = true - depends_on = [data.nutanix_lcm_config_v2.get-lcm-config-before-update] + depends_on = [data.nutanix_lcm_config_v2.get_lcm_config_before_update] } # Get LCM Config after Update -data "nutanix_lcm_config_v2" "get-lcm-config-after-update" { +data "nutanix_lcm_config_v2" "get_lcm_config_after_update" { lifecycle { postcondition { condition = self.is_auto_inventory_enabled == true error_message = "Auto Inventory is not enabled, current value: ${self.is_auto_inventory_enabled}" } } - depends_on = [nutanix_lcm_config_v2.update-lcm-config] + depends_on = [nutanix_lcm_config_v2.update_lcm_config] } ` } diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go deleted file mode 100644 index 95cdc5f77..000000000 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_inventry_v2_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package lcmv2_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - acc "github.com/terraform-providers/terraform-provider-nutanix/nutanix/acctest" -) - -const resourceNameLcmPerformInventory = "nutanix_lcm_perform_inventory_v2.inventory" - -func TestAccV2NutanixLcmPerformInventory_Basic(t *testing.T) { - datasourceNameLcmEntities := "data.nutanix_lcm_entities_v2.lcm-entities" - datasourceNameLcmEntityBeforeUpgrade := "data.nutanix_lcm_entity_v2.entity-before-upgrade" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccFoundationPreCheck(t) }, - Providers: acc.TestAccProviders, - Steps: []resource.TestStep{ - { - Config: testLcmPerformInventoryConfig(), - Check: resource.ComposeTestCheckFunc( - // check if the entity model is present - resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.#", "1"), - resource.TestCheckResourceAttr(datasourceNameLcmEntities, "entities.0.entity_model", testVars.Lcm.EntityModel), - // check if the entity is present - resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "ext_id"), - resource.TestCheckResourceAttr(datasourceNameLcmEntityBeforeUpgrade, "entity_model", testVars.Lcm.EntityModel), - resource.TestCheckResourceAttrSet(datasourceNameLcmEntityBeforeUpgrade, "entity_version"), - // perform inventory checks - resource.TestCheckResourceAttrSet(resourceNameLcmPerformInventory, "x_cluster_id"), - ), - }, - }, - }) -} - -func testLcmPerformInventoryConfig() string { - return fmt.Sprintf(` -# list Clusters -data "nutanix_clusters_v2" "clusters" { - filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'AOS')" -} - -# List Prism Central -data "nutanix_clusters_v2" "pc" { - filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" -} - -locals { - clusterExtID = data.nutanix_clusters_v2.clusters.cluster_entities[0].ext_id - pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id - config = jsondecode(file("%[1]s")) - lcm = local.config.lcm -} - -data "nutanix_lcm_entities_v2" "lcm-entities" { - filter = "entityModel eq '${local.lcm.entity_model}'" -} - -data "nutanix_lcm_entity_v2" "entity-before-upgrade" { - ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id -} - -# perform inventory -resource "nutanix_lcm_perform_inventory_v2" "inventory" { - x_cluster_id = local.pcExtID - depends_on = [data.nutanix_lcm_entity_v2.entity-before-upgrade] -} - - -`, filepath) -} From 4b86585ef879584023a2972b0abaa05552568243 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Thu, 27 Feb 2025 10:22:33 +0530 Subject: [PATCH 36/39] change of testcase --- .../lcmv2/resource_nutanix_lcm_config_v2_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go index 89081a70c..1d84c28b8 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go @@ -8,7 +8,6 @@ import ( ) func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { - datasourceLcmConfigBeforeUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_before_update" resourceLcmConfig := "nutanix_lcm_config_v2.update_lcm_config" datasourceLcmConfigAfterUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_after_update" @@ -19,8 +18,6 @@ func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { { Config: testLcmUpdateConfig(), Check: resource.ComposeTestCheckFunc( - // Check Auto Inventory is disabled Before Update - resource.TestCheckResourceAttr(datasourceLcmConfigBeforeUpdate, "is_auto_inventory_enabled", "false"), // Update LCM Config Check resource.TestCheckResourceAttr(resourceLcmConfig, "is_auto_inventory_enabled", "true"), @@ -35,20 +32,9 @@ func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { func testLcmUpdateConfig() string { return ` -# Get LCM Config before Update -data "nutanix_lcm_config_v2" "get_lcm_config_before_update" { - lifecycle { - postcondition { - condition = self.is_auto_inventory_enabled == false - error_message = "Auto Inventory is already enabled, current value: ${self.is_auto_inventory_enabled}" - } - } -} - # Update LCM Config: Enable auto inventory resource "nutanix_lcm_config_v2" "update_lcm_config" { is_auto_inventory_enabled = true - depends_on = [data.nutanix_lcm_config_v2.get_lcm_config_before_update] } # Get LCM Config after Update From 49d826effdab65946da8bbe269794c07c6f2367d Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Fri, 28 Feb 2025 14:58:46 +0530 Subject: [PATCH 37/39] add docs for lcm invnetory, prechecks, status, config modules --- .../lcmv2/resource_nutanix_lcm_config_v2.go | 40 ++++++++--- .../resource_nutanix_lcm_config_v2_test.go | 24 +++++-- website/docs/d/lcm_config_v2.html.markdown | 18 +++++ website/docs/d/lcm_status_v2.html.markdown | 34 ++++++++++ website/docs/r/lcm_config_v2.html.markdown | 50 ++++++++++++++ .../r/lcm_perform_inventory_v2.html.markdown | 35 ++++++++++ website/docs/r/lcm_prechecks_v2.html.markdown | 68 +++++++++++++++++++ 7 files changed, 252 insertions(+), 17 deletions(-) create mode 100644 website/docs/d/lcm_config_v2.html.markdown create mode 100644 website/docs/d/lcm_status_v2.html.markdown create mode 100644 website/docs/r/lcm_config_v2.html.markdown create mode 100644 website/docs/r/lcm_perform_inventory_v2.html.markdown create mode 100644 website/docs/r/lcm_prechecks_v2.html.markdown diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go index 9fd760413..9aabf7627 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2.go @@ -3,8 +3,6 @@ package lcmv2 import ( "context" "encoding/json" - "log" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -14,6 +12,7 @@ import ( prismConfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" "github.com/terraform-providers/terraform-provider-nutanix/utils" + "log" ) func ResourceNutanixLcmConfigV2() *schema.Resource { @@ -78,7 +77,7 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat args := make(map[string]interface{}) args["If-Match"] = utils.StringPtr(etagValue) - body := &lcmconfigimport1.Config{} + body := readResp.Data.GetValue().(lcmconfigimport1.Config) var connectivityTypeMap = map[string]resources.ConnectivityType{ "$UNKNOWN": resources.CONNECTIVITYTYPE_UNKNOWN, "$REDACTED": resources.CONNECTIVITYTYPE_REDACTED, @@ -90,9 +89,9 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat if url, ok := d.GetOk("url"); ok { body.Url = utils.StringPtr(url.(string)) } - - if isAutoInventoryEnabled, ok := d.GetOk("is_auto_inventory_enabled"); ok { - body.IsAutoInventoryEnabled = utils.BoolPtr(isAutoInventoryEnabled.(bool)) + if IsExplicitlySet(d, "is_auto_inventory_enabled") { + v := d.Get("is_auto_inventory_enabled").(bool) + body.IsAutoInventoryEnabled = utils.BoolPtr(v) } if autoInventorySchedule, ok := d.GetOk("auto_inventory_schedule"); ok { body.AutoInventorySchedule = utils.StringPtr(autoInventorySchedule.(string)) @@ -104,16 +103,18 @@ func ResourceNutanixLcmConfigV2Create(ctx context.Context, d *schema.ResourceDat } } } - if isHttpsEnabled, ok := d.GetOk("is_https_enabled"); ok { - body.IsHttpsEnabled = utils.BoolPtr(isHttpsEnabled.(bool)) + if IsExplicitlySet(d, "is_https_enabled") { + v := d.Get("is_https_enabled").(bool) + body.IsHttpsEnabled = utils.BoolPtr(v) } - if hasModuleAutoUpgradeEnabled, ok := d.GetOk("has_module_auto_upgrade_enabled"); ok { - body.HasModuleAutoUpgradeEnabled = utils.BoolPtr(hasModuleAutoUpgradeEnabled.(bool)) + if IsExplicitlySet(d, "has_module_auto_upgrade_enabled") { + v := d.Get("has_module_auto_upgrade_enabled").(bool) + body.HasModuleAutoUpgradeEnabled = utils.BoolPtr(v) } aJSON, _ := json.MarshalIndent(body, "", " ") log.Printf("[DEBUG] LCM Update Config Request Spec: %s", string(aJSON)) - resp, err := conn.LcmConfigAPIInstance.UpdateConfig(body, clusterId, args) + resp, err := conn.LcmConfigAPIInstance.UpdateConfig(&body, clusterId, args) if err != nil { return diag.Errorf("error while updating the LCM config: %v", err) } @@ -180,3 +181,20 @@ func schemaForLinks() *schema.Schema { }, } } + +func IsExplicitlySet(d *schema.ResourceData, key string) bool { + rawConfig := d.GetRawConfig() // Get raw Terraform config as cty.Value + log.Printf("[DEBUG] Raw Config: %s", rawConfig) + if rawConfig.IsNull() || !rawConfig.IsKnown() { + return false // If rawConfig is null/unknown, key wasn't explicitly set + } + + // Convert rawConfig to map and check if key exists + configMap := rawConfig.AsValueMap() + if val, exists := configMap[key]; exists { + log.Printf("[DEBUG1] Key: %s, Value: %s", key, val) + log.Printf("[DEBUG2] values %t", val.IsNull()) + return !val.IsNull() // Ensure key exists and isn't explicitly null + } + return false +} diff --git a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go index 1d84c28b8..37580a046 100644 --- a/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go +++ b/nutanix/services/lcmv2/resource_nutanix_lcm_config_v2_test.go @@ -10,6 +10,7 @@ import ( func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { resourceLcmConfig := "nutanix_lcm_config_v2.update_lcm_config" datasourceLcmConfigAfterUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_after_update" + datasourceLcmConfigBeforeUpdate := "data.nutanix_lcm_config_v2.get_lcm_config_before_update" resource.Test(t, resource.TestCase{ PreCheck: func() {}, @@ -18,12 +19,16 @@ func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { { Config: testLcmUpdateConfig(), Check: resource.ComposeTestCheckFunc( + // Check LCM Config before Update + resource.TestCheckResourceAttr(datasourceLcmConfigBeforeUpdate, "is_auto_inventory_enabled", "false"), // Update LCM Config Check resource.TestCheckResourceAttr(resourceLcmConfig, "is_auto_inventory_enabled", "true"), // Check Auto Inventory is enabled after Update resource.TestCheckResourceAttr(datasourceLcmConfigAfterUpdate, "is_auto_inventory_enabled", "true"), + + resource.TestCheckResourceAttr(datasourceLcmConfigAfterUpdate, "auto_inventory_schedule", "16:30"), ), }, }, @@ -32,20 +37,27 @@ func TestAccV2NutanixLcmConfigUpdate(t *testing.T) { func testLcmUpdateConfig() string { return ` +# Get LCM Config before Update +data "nutanix_lcm_config_v2" "get_lcm_config_before_update" { + +} + # Update LCM Config: Enable auto inventory resource "nutanix_lcm_config_v2" "update_lcm_config" { is_auto_inventory_enabled = true + auto_inventory_schedule = "16:30" + depends_on = [data.nutanix_lcm_config_v2.get_lcm_config_before_update] } # Get LCM Config after Update data "nutanix_lcm_config_v2" "get_lcm_config_after_update" { - lifecycle { - postcondition { - condition = self.is_auto_inventory_enabled == true - error_message = "Auto Inventory is not enabled, current value: ${self.is_auto_inventory_enabled}" - } - } depends_on = [nutanix_lcm_config_v2.update_lcm_config] } + +# Update LCM Config: Enable auto inventory +resource "nutanix_lcm_config_v2" "update_lcm_config_reset_auto_inventory" { + is_auto_inventory_enabled = false + depends_on = [data.nutanix_lcm_config_v2.get_lcm_config_after_update] +} ` } diff --git a/website/docs/d/lcm_config_v2.html.markdown b/website/docs/d/lcm_config_v2.html.markdown new file mode 100644 index 000000000..1f3731411 --- /dev/null +++ b/website/docs/d/lcm_config_v2.html.markdown @@ -0,0 +1,18 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_config_v2" +sidebar_current: "docs-nutanix-datasource-lcm-config-v2" +description: |- + Get LCM configuration. +--- + +# nutanix_lcm_entity_v2 +Get LCM configuration. + +## Example + +```hcl +data "nutanix_lcm_config_v2" "lcm-configuration" {} +``` + +See detailed information in [Nutanix LCM Config V4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Config/operation/getConfig \ No newline at end of file diff --git a/website/docs/d/lcm_status_v2.html.markdown b/website/docs/d/lcm_status_v2.html.markdown new file mode 100644 index 000000000..b8635040c --- /dev/null +++ b/website/docs/d/lcm_status_v2.html.markdown @@ -0,0 +1,34 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_status_v2" +sidebar_current: "docs-nutanix-datasource-lcm-status-v2" +description: |- + Get the LCM framework status. +--- + +# nutanix_lcm_status_v2 + +Get the LCM framework status. Represents the Status of LCM. Status represents details about a pending or ongoing action in LCM. + +## Example + +```hcl +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +data "nutanix_lcm_status_v2" "lcm_framework_status" { + x_cluster_id = local.pcExtID +} +``` + +# Argument Reference +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. + +See detailed information in [Nutanix LCM Status v4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Status diff --git a/website/docs/r/lcm_config_v2.html.markdown b/website/docs/r/lcm_config_v2.html.markdown new file mode 100644 index 000000000..acad4a6f8 --- /dev/null +++ b/website/docs/r/lcm_config_v2.html.markdown @@ -0,0 +1,50 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_config_v2" +sidebar_current: "docs-nutanix-lcm-config-v2" +description: |- + Update LCM configuration. +--- + +# nutanix_lcm_entity_v2 +Update LCM configuration. + +## Example + +```hcl +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +# Enable Auto Inventory, Add Auto Inventory Schedule and enable auto upgrade +resource "nutanix_lcm_config_v2" "lcm-configuration-update" { + x_cluster_id = local.pcExtID + is_auto_inventory_enabled = true + auto_inventory_schedule = "16:30" + has_module_auto_upgrade_enabled = true +} + +# Update the LCM url to darksite server +resource "nutanix_lcm_config_v2" "lcm-configuration-update-connectivity-type" { + x_cluster_id = local.pcExtID + url = "https://x.x.x.x:8000/builds" + connectivity_type = "DARKSITE_WEB_SERVER" +} + +``` +## Argument Reference +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. +* `url`: (Optional) URL of the LCM repository. +* `is_auto_inventory_enabled`: (Optional) Indicates if the auto inventory operation is enabled. The default value is set to False. +* `auto_inventory_schedule`: (Optional) The scheduled time in "%H:%M" 24-hour format of the next inventory execution. Used when auto_inventory_enabled is set to True. The default schedule time is 03:00(AM). +* `connectivity_type`: (Optional)This field indicates whether LCM framework on the cluster is running in connected-site mode or darksite mode. +* `is_https_enabled`: (Optional) Indicates if the LCM URL has HTTPS enabled. The default value is True. +* `has_module_auto_upgrade_enabled`: (Optional) Indicates if LCM is enabled to auto-upgrade products. The default value is False. + +See detailed information in [Nutanix LCM Config V4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Config/operation/updateConfig \ No newline at end of file diff --git a/website/docs/r/lcm_perform_inventory_v2.html.markdown b/website/docs/r/lcm_perform_inventory_v2.html.markdown new file mode 100644 index 000000000..3c4a454a9 --- /dev/null +++ b/website/docs/r/lcm_perform_inventory_v2.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_perform_inventory_v2" +sidebar_current: "docs-nutanix_lcm_perform_inventory_v2" +description: |- + Perform an inventory operation to identify/scan entities on the cluster that can be updated through LCM. +--- + +# nutanix_lcm_perform_inventory_v2 + +Perform an inventory operation to identify/scan entities on the cluster that can be updated through LCM. + +## Example + +```hcl +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +# perform inventory +resource "nutanix_lcm_perform_inventory_v2" "inventory" { + x_cluster_id = local.pcExtID +} +``` + +# Argument Reference +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. + +See detailed information in [Nutanix LCM Perform Inventory v4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Inventory/operation/performInventory \ No newline at end of file diff --git a/website/docs/r/lcm_prechecks_v2.html.markdown b/website/docs/r/lcm_prechecks_v2.html.markdown new file mode 100644 index 000000000..bafef8cbf --- /dev/null +++ b/website/docs/r/lcm_prechecks_v2.html.markdown @@ -0,0 +1,68 @@ +--- +layout: "nutanix" +page_title: "NUTANIX: nutanix_lcm_prechecks_v2" +sidebar_current: "docs-nutanix_lcm_prechecks_v2" +description: |- + Perform LCM prechecks for the intended update operation. +--- + +# nutanix_lcm_prechecks_v2 + +Perform LCM prechecks for the intended update operation. + +## Example + +```hcl +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +# In this example, we are trying to update Calm Policy Engine. +data "nutanix_lcm_entities_v2" "lcm-entities" { + filter = "entityModel eq 'Calm Policy Engine'" +} + +data "nutanix_lcm_entity_v2" "entity-before-upgrade" { + ext_id = data.nutanix_lcm_entities_v2.lcm-entities.entities[0].ext_id +} + +resource "nutanix_lcm_prechecks_v2" "pre-checks" { + x_cluster_id = local.pcExtID + entity_update_specs { + entity_uuid = data.nutanix_lcm_entity_v2.entity-before-upgrade.ext_id + to_version = "4.0.0" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. +* `management_server`: (Optional) Cluster management server configuration used while updating clusters with ESX or Hyper-V. +* `entity_update_specs`: (Required) List of entity update objects for getting recommendations. +* `skipped_precheck_flags`: (Optional) List of prechecks to skip. The allowed value is 'powerOffUvms' that skips the pinned VM prechecks. Items Enum: `POWER_OFF_UVMS` + +### Management Server +The `management_server` attribute supports the following: + +* `hypervisor_type`: (Required) Type of Hypervisor present in the cluster. Enum Values: + * "HYPERV" : Hyper-V Hypervisor. + * "ESX" : ESX Hypervisor. + * "AHV" : Nutanix AHV Hypervisor. +* `ip`: (Required) IP address of the management server. +* `username`: (Required) Username to login to the management server. +* `password`: (Required) Password to login to the management server. + +### Entity Update Specs +The `entity_update_specs` attribute supports the following: + +* `entity_uuid`: (Required) UUID of the LCM entity. +* `to_version`: (Required) Version to upgrade to. + +See detailed information in [Nutanix LCM Prechecks v4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Prechecks/operation/performPrechecks \ No newline at end of file From 2fd0e117f8c4bbb8ad01d3acff60b1611532bcc5 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 3 Mar 2025 11:57:40 +0530 Subject: [PATCH 38/39] Add argument reference for Get config --- website/docs/d/lcm_config_v2.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/docs/d/lcm_config_v2.html.markdown b/website/docs/d/lcm_config_v2.html.markdown index 1f3731411..1985726d0 100644 --- a/website/docs/d/lcm_config_v2.html.markdown +++ b/website/docs/d/lcm_config_v2.html.markdown @@ -15,4 +15,9 @@ Get LCM configuration. data "nutanix_lcm_config_v2" "lcm-configuration" {} ``` +## Argument Reference +The following arguments are supported: + +* `x_cluster_id`: (Optional) Cluster uuid on which the resource is present or operation is being performed. + See detailed information in [Nutanix LCM Config V4] https://developers.nutanix.com/api-reference?namespace=lifecycle&version=v4.0#tag/Config/operation/getConfig \ No newline at end of file From e12859bf743361261a2f6958b1ebb1acb26a5101 Mon Sep 17 00:00:00 2001 From: Gullapalli Akhil Sai Date: Mon, 3 Mar 2025 14:58:40 +0530 Subject: [PATCH 39/39] Add example for lcm config --- examples/lcm_config_v2/main.tf | 41 +++++++++++++++++++++++++ examples/lcm_config_v2/terraform.tfvars | 5 +++ examples/lcm_config_v2/variables.tf | 13 ++++++++ 3 files changed, 59 insertions(+) create mode 100644 examples/lcm_config_v2/main.tf create mode 100644 examples/lcm_config_v2/terraform.tfvars create mode 100644 examples/lcm_config_v2/variables.tf diff --git a/examples/lcm_config_v2/main.tf b/examples/lcm_config_v2/main.tf new file mode 100644 index 000000000..dd22a99ff --- /dev/null +++ b/examples/lcm_config_v2/main.tf @@ -0,0 +1,41 @@ +terraform { + required_providers { + nutanix = { + source = "nutanix/nutanix" + version = "2.1.0" + } + } +} + +#defining nutanix configuration +provider "nutanix" { + username = var.nutanix_username + password = var.nutanix_password + endpoint = var.nutanix_endpoint + port = 9440 + insecure = true +} + +# List Prism Central +data "nutanix_clusters_v2" "pc" { + filter = "config/clusterFunction/any(t:t eq Clustermgmt.Config.ClusterFunctionRef'PRISM_CENTRAL')" +} + +locals { + pcExtID = data.nutanix_clusters_v2.pc.cluster_entities[0].ext_id +} + +# Example here, we are enabling Auto Inventory, adding Auto Inventory Schedule and enabling auto upgrade +resource "nutanix_lcm_config_v2" "lcm-configuration-update" { + x_cluster_id = local.pcExtID + is_auto_inventory_enabled = true + auto_inventory_schedule = "16:30" + has_module_auto_upgrade_enabled = true +} + +# Read LCM config. +data "nutanix_lcm_config_v2" "get-lcm-configuration" { + x_cluster_id = local.pcExtID + depends_on = [nutanix_lcm_config_v2.lcm-configuration-update] +} + diff --git a/examples/lcm_config_v2/terraform.tfvars b/examples/lcm_config_v2/terraform.tfvars new file mode 100644 index 000000000..867888ffc --- /dev/null +++ b/examples/lcm_config_v2/terraform.tfvars @@ -0,0 +1,5 @@ +#define values to the variables to be used in terraform file +nutanix_username = "admin" +nutanix_password = "password" +nutanix_endpoint = "10.xx.xx.xx" +nutanix_port = 9440 diff --git a/examples/lcm_config_v2/variables.tf b/examples/lcm_config_v2/variables.tf new file mode 100644 index 000000000..dcd130ec8 --- /dev/null +++ b/examples/lcm_config_v2/variables.tf @@ -0,0 +1,13 @@ +#define the type of variables to be used in terraform file +variable "nutanix_username" { + type = string +} +variable "nutanix_password" { + type = string +} +variable "nutanix_endpoint" { + type = string +} +variable "nutanix_port" { + type = string +}