From 1b9e90a128b720a2a9dc510c2d72f72e8b22c4b2 Mon Sep 17 00:00:00 2001 From: Axel Ismirlian Date: Fri, 15 Nov 2024 14:45:35 -0600 Subject: [PATCH] [Refactor] Volume Attach --- ibm/service/power/ibm_pi_constants.go | 6 +- .../power/resource_ibm_pi_volume_attach.go | 100 ++++++++--------- .../resource_ibm_pi_volume_attach_test.go | 103 ++++++++++-------- website/docs/r/pi_volume_attach.html.markdown | 38 ++++--- 4 files changed, 129 insertions(+), 118 deletions(-) diff --git a/ibm/service/power/ibm_pi_constants.go b/ibm/service/power/ibm_pi_constants.go index aac2683c62..da53564f88 100644 --- a/ibm/service/power/ibm_pi_constants.go +++ b/ibm/service/power/ibm_pi_constants.go @@ -544,6 +544,7 @@ const ( State_Creating = "creating" State_Deleted = "deleted" State_Deleting = "deleting" + State_Detaching = "detaching" State_Down = "down" State_Error = "error" State_ERROR = "ERROR" @@ -568,11 +569,6 @@ const ( State_Up = "up" State_Updating = "updating" State_VerifyResize = "verify_resize" - Status_Active = "ACTIVE" - Status_Deleting = "deleting" - Status_Error = "ERROR" - Status_Pending = "PENDING" - Status_Shutoff = "SHUTOFF" // Timeout values Timeout_Active = 2 * time.Minute diff --git a/ibm/service/power/resource_ibm_pi_volume_attach.go b/ibm/service/power/resource_ibm_pi_volume_attach.go index cc17613006..66e155d48d 100644 --- a/ibm/service/power/resource_ibm_pi_volume_attach.go +++ b/ibm/service/power/resource_ibm_pi_volume_attach.go @@ -10,14 +10,14 @@ import ( "log" "time" - st "github.com/IBM-Cloud/power-go-client/clients/instance" - "github.com/IBM-Cloud/power-go-client/helpers" + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_volumes" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "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/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func ResourceIBMPIVolumeAttach() *schema.Resource { @@ -33,32 +33,32 @@ func ResourceIBMPIVolumeAttach() *schema.Resource { }, Schema: map[string]*schema.Schema{ - - helpers.PICloudInstanceId: { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: " Cloud Instance ID - This is the service_instance_id.", + // Arguments + Arg_CloudInstanceID: { + Description: "The GUID of the service instance associated with an account.", + ForceNew: true, + Required: true, + Type: schema.TypeString, + ValidateFunc: validation.NoZeroValues, }, - - helpers.PIVolumeId: { - Type: schema.TypeString, - Required: true, + Arg_InstanceID: { + Description: "PI Instance Id", ForceNew: true, - Description: "Id of the volume to attach. Note these volumes should have been created", - }, - - helpers.PIInstanceId: { - Type: schema.TypeString, Required: true, + Type: schema.TypeString, + }, + Arg_VolumeID: { + Description: "Id of the volume to attach. Note these volumes should have been created", ForceNew: true, - Description: "PI Instance Id", + Required: true, + Type: schema.TypeString, }, - // Computed Attribute - helpers.PIVolumeAttachStatus: { - Type: schema.TypeString, - Computed: true, + // Attribute + Attr_Status: { + Computed: true, + Description: "The status of the volume.", + Type: schema.TypeString, }, }, } @@ -70,26 +70,26 @@ func resourceIBMPIVolumeAttachCreate(ctx context.Context, d *schema.ResourceData return diag.FromErr(err) } - volumeID := d.Get(helpers.PIVolumeId).(string) - pvmInstanceID := d.Get(helpers.PIInstanceId).(string) - cloudInstanceID := d.Get(helpers.PICloudInstanceId).(string) + cloudInstanceID := d.Get(Arg_CloudInstanceID).(string) + pvmInstanceID := d.Get(Arg_InstanceID).(string) + volumeID := d.Get(Arg_VolumeID).(string) - volClient := st.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) + volClient := instance.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) volinfo, err := volClient.Get(volumeID) if err != nil { return diag.FromErr(err) } - if volinfo.State == "available" || *volinfo.Shareable { + if volinfo.State == State_Available || *volinfo.Shareable { log.Printf(" In the current state the volume can be attached to the instance ") } - if volinfo.State == "in-use" && *volinfo.Shareable { + if volinfo.State == State_InUse && *volinfo.Shareable { log.Printf("Volume State /Status is permitted and hence attaching the volume to the instance") } - if volinfo.State == helpers.PIVolumeAllowableAttachStatus && !*volinfo.Shareable { + if volinfo.State == State_InUse && !*volinfo.Shareable { return diag.Errorf("the volume cannot be attached in the current state. The volume must be in the *available* state. No other states are permissible") } @@ -121,14 +121,14 @@ func resourceIBMPIVolumeAttachRead(ctx context.Context, d *schema.ResourceData, } cloudInstanceID, pvmInstanceID, volumeID := ids[0], ids[1], ids[2] - client := st.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) vol, err := client.CheckVolumeAttach(pvmInstanceID, volumeID) if err != nil { return diag.FromErr(err) } - d.Set(helpers.PIVolumeAttachStatus, vol.State) + d.Set(Attr_Status, vol.State) return nil } @@ -143,7 +143,7 @@ func resourceIBMPIVolumeAttachDelete(ctx context.Context, d *schema.ResourceData return diag.FromErr(err) } cloudInstanceID, pvmInstanceID, volumeID := ids[0], ids[1], ids[2] - client := st.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) + client := instance.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID) log.Printf("the id of the volume to detach is %s ", volumeID) @@ -170,12 +170,12 @@ func resourceIBMPIVolumeAttachDelete(ctx context.Context, d *schema.ResourceData return nil } -func isWaitForIBMPIVolumeAttachAvailable(ctx context.Context, client *st.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string, timeout time.Duration) (interface{}, error) { +func isWaitForIBMPIVolumeAttachAvailable(ctx context.Context, client *instance.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for Volume (%s) to be available for attachment", id) - stateConf := &resource.StateChangeConf{ - Pending: []string{"retry", helpers.PIVolumeProvisioning}, - Target: []string{helpers.PIVolumeAllowableAttachStatus}, + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Retry, State_Creating}, + Target: []string{State_InUse}, Refresh: isIBMPIVolumeAttachRefreshFunc(client, id, cloudInstanceID, pvmInstanceID), Delay: 10 * time.Second, MinTimeout: 30 * time.Second, @@ -185,27 +185,27 @@ func isWaitForIBMPIVolumeAttachAvailable(ctx context.Context, client *st.IBMPIVo return stateConf.WaitForStateContext(ctx) } -func isIBMPIVolumeAttachRefreshFunc(client *st.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string) resource.StateRefreshFunc { +func isIBMPIVolumeAttachRefreshFunc(client *instance.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string) retry.StateRefreshFunc { return func() (interface{}, string, error) { vol, err := client.Get(id) if err != nil { return nil, "", err } - if vol.State == "in-use" && flex.StringContains(vol.PvmInstanceIDs, pvmInstanceID) { - return vol, helpers.PIVolumeAllowableAttachStatus, nil + if vol.State == State_InUse && flex.StringContains(vol.PvmInstanceIDs, pvmInstanceID) { + return vol, State_InUse, nil } - return vol, helpers.PIVolumeProvisioning, nil + return vol, State_Creating, nil } } -func isWaitForIBMPIVolumeDetach(ctx context.Context, client *st.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string, timeout time.Duration) (interface{}, error) { +func isWaitForIBMPIVolumeDetach(ctx context.Context, client *instance.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string, timeout time.Duration) (interface{}, error) { log.Printf("Waiting for Volume (%s) to be available after detachment", id) - stateConf := &resource.StateChangeConf{ - Pending: []string{"detaching", helpers.PowerVolumeAttachDeleting}, - Target: []string{helpers.PIVolumeProvisioningDone}, + stateConf := &retry.StateChangeConf{ + Pending: []string{State_Detaching, State_Deleting}, + Target: []string{State_Available}, Refresh: isIBMPIVolumeDetachRefreshFunc(client, id, cloudInstanceID, pvmInstanceID), Delay: 10 * time.Second, MinTimeout: 30 * time.Second, @@ -215,7 +215,7 @@ func isWaitForIBMPIVolumeDetach(ctx context.Context, client *st.IBMPIVolumeClien return stateConf.WaitForStateContext(ctx) } -func isIBMPIVolumeDetachRefreshFunc(client *st.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string) resource.StateRefreshFunc { +func isIBMPIVolumeDetachRefreshFunc(client *instance.IBMPIVolumeClient, id, cloudInstanceID, pvmInstanceID string) retry.StateRefreshFunc { return func() (interface{}, string, error) { vol, err := client.Get(id) if err != nil { @@ -223,7 +223,7 @@ func isIBMPIVolumeDetachRefreshFunc(client *st.IBMPIVolumeClient, id, cloudInsta switch uErr.(type) { case *p_cloud_volumes.PcloudCloudinstancesVolumesGetNotFound: log.Printf("[DEBUG] volume does not exist while detaching %v", err) - return vol, helpers.PIVolumeProvisioningDone, nil + return vol, State_Available, nil } return nil, "", err } @@ -232,10 +232,10 @@ func isIBMPIVolumeDetachRefreshFunc(client *st.IBMPIVolumeClient, id, cloudInsta // Also validate the Volume state is 'available' when it is not Sharable // In case of Sharable Volume it can be `in-use` state if !flex.StringContains(vol.PvmInstanceIDs, pvmInstanceID) && - (*vol.Shareable || (!*vol.Shareable && vol.State == "available")) { - return vol, helpers.PIVolumeProvisioningDone, nil + (*vol.Shareable || (!*vol.Shareable && vol.State == State_Available)) { + return vol, State_Available, nil } - return vol, "detaching", nil + return vol, State_Detaching, nil } } diff --git a/ibm/service/power/resource_ibm_pi_volume_attach_test.go b/ibm/service/power/resource_ibm_pi_volume_attach_test.go index 287e5b08c6..2eaa20cfe1 100644 --- a/ibm/service/power/resource_ibm_pi_volume_attach_test.go +++ b/ibm/service/power/resource_ibm_pi_volume_attach_test.go @@ -10,14 +10,14 @@ import ( "log" "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - - st "github.com/IBM-Cloud/power-go-client/clients/instance" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + + "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccIBMPIVolumeAttachbasic(t *testing.T) { @@ -71,7 +71,7 @@ func testAccCheckIBMPIVolumeAttachDestroy(s *terraform.State) error { return err } cloudInstanceID, pvmInstanceID, volumeID := ids[0], ids[1], ids[2] - client := st.NewIBMPIVolumeClient(context.Background(), sess, cloudInstanceID) + client := instance.NewIBMPIVolumeClient(context.Background(), sess, cloudInstanceID) volumeAttach, err := client.CheckVolumeAttach(pvmInstanceID, volumeID) if err == nil { log.Println("volume attach*****", volumeAttach.State) @@ -83,7 +83,6 @@ func testAccCheckIBMPIVolumeAttachDestroy(s *terraform.State) error { } func testAccCheckIBMPIVolumeAttachExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] if !ok { @@ -104,7 +103,7 @@ func testAccCheckIBMPIVolumeAttachExists(n string) resource.TestCheckFunc { return err } cloudInstanceID, pvmInstanceID, volumeID := ids[0], ids[1], ids[2] - client := st.NewIBMPIVolumeClient(context.Background(), sess, cloudInstanceID) + client := instance.NewIBMPIVolumeClient(context.Background(), sess, cloudInstanceID) _, err = client.CheckVolumeAttach(pvmInstanceID, volumeID) if err != nil { @@ -115,24 +114,30 @@ func testAccCheckIBMPIVolumeAttachExists(n string) resource.TestCheckFunc { } func testAccCheckIBMPIVolumeAttachConfig(name string) string { return fmt.Sprintf(` - resource "ibm_pi_volume" "power_volume" { - pi_volume_size = 2 - pi_volume_name = "%[2]s" - pi_volume_shareable = true - pi_volume_pool = "Tier3-Flash-1" - pi_cloud_instance_id = "%[1]s" - } - resource "ibm_pi_instance" "power_instance" { - pi_memory = "2" - pi_processors = "0.25" - pi_instance_name = "%[2]s" - pi_proc_type = "shared" - pi_image_id = "%[3]s" - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" - pi_storage_pool = "Tier3-Flash-1" - pi_network { - network_id = "%[4]s" + resource "ibm_pi_volume" "power_volume" { + pi_volume_size = 2 + pi_volume_name = "%[2]s" + pi_volume_shareable = true + pi_volume_pool = "General-Flash-12" + pi_cloud_instance_id = "%[1]s" + } + resource "ibm_pi_instance" "power_instance" { + pi_memory = "2" + pi_processors = "0.25" + pi_instance_name = "%[2]s" + pi_proc_type = "shared" + pi_image_id = "%[3]s" + pi_sys_type = "s922" + pi_cloud_instance_id = "%[1]s" + pi_storage_pool = "General-Flash-12" + pi_network { + network_id = "%[4]s" + } + } + resource "ibm_pi_volume_attach" "power_attach_volume"{ + pi_cloud_instance_id = "%[1]s" + pi_volume_id = ibm_pi_volume.power_volume.volume_id + pi_instance_id = ibm_pi_instance.power_instance.instance_id } } resource "ibm_pi_volume_attach" "power_attach_volume"{ @@ -145,26 +150,32 @@ func testAccCheckIBMPIVolumeAttachConfig(name string) string { func testAccCheckIBMPIShareableVolumeAttachConfig(name string) string { return fmt.Sprintf(` - resource "ibm_pi_volume" "power_volume" { - pi_volume_size = 2 - pi_volume_name = "%[2]s" - pi_volume_shareable = true - pi_volume_pool = "Tier3-Flash-1" - pi_cloud_instance_id = "%[1]s" - } - resource "ibm_pi_instance" "power_instance" { - count = 2 - pi_memory = "2" - pi_processors = "0.25" - pi_instance_name = "%[2]s-${count.index}" - pi_proc_type = "shared" - pi_image_id = "%[3]s" - pi_sys_type = "s922" - pi_cloud_instance_id = "%[1]s" - pi_storage_pool = "Tier3-Flash-1" - pi_volume_ids = count.index == 0 ? [ibm_pi_volume.power_volume.volume_id] : null - pi_network { - network_id = "%[4]s" + resource "ibm_pi_volume" "power_volume" { + pi_volume_size = 2 + pi_volume_name = "%[2]s" + pi_volume_shareable = true + pi_volume_pool = "General-Flash-12" + pi_cloud_instance_id = "%[1]s" + } + resource "ibm_pi_instance" "power_instance" { + count = 2 + pi_memory = "2" + pi_processors = "0.25" + pi_instance_name = "%[2]s-${count.index}" + pi_proc_type = "shared" + pi_image_id = "%[3]s" + pi_sys_type = "s922" + pi_cloud_instance_id = "%[1]s" + pi_storage_pool = "General-Flash-12" + pi_volume_ids = count.index == 0 ? [ibm_pi_volume.power_volume.volume_id] : null + pi_network { + network_id = "%[4]s" + } + } + resource "ibm_pi_volume_attach" "power_attach_volume"{ + pi_cloud_instance_id = "%[1]s" + pi_volume_id = ibm_pi_volume.power_volume.volume_id + pi_instance_id = ibm_pi_instance.power_instance[1].instance_id } } resource "ibm_pi_volume_attach" "power_attach_volume"{ diff --git a/website/docs/r/pi_volume_attach.html.markdown b/website/docs/r/pi_volume_attach.html.markdown index 12aeddf359..f8f5858c34 100644 --- a/website/docs/r/pi_volume_attach.html.markdown +++ b/website/docs/r/pi_volume_attach.html.markdown @@ -1,5 +1,4 @@ --- - subcategory: "Power Systems" layout: "ibm" page_title: "IBM: pi_volume_attach" @@ -8,26 +7,29 @@ description: |- --- # ibm_pi_volume_attach + Attaches and Detaches a volume to a Power Systems Virtual Server instance. For more information, about managing volume, see [getting started with IBM Power Systems Virtual Servers](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-getting-started). ## Example usage + The following example attaches volume to a power systems virtual server instance. ```terraform resource "ibm_pi_volume_attach" "testacc_volume_attach"{ - pi_cloud_instance_id = "" - pi_volume_id = "" - pi_instance_id = "" + pi_cloud_instance_id = "" + pi_volume_id = "" + pi_instance_id = "" } ``` -**Note** -* Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. -* If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: - * `region` - `lon` - * `zone` - `lon04` +### Notes + +- Please find [supported Regions](https://cloud.ibm.com/apidocs/power-cloud#endpoint) for endpoints. +- If a Power cloud instance is provisioned at `lon04`, The provider level attributes should be as follows: + - `region` - `lon` + - `zone` - `lon04` - Example usage: +Example usage: ```terraform provider "ibm" { @@ -43,25 +45,27 @@ ibm_pi_volume_attach provides the following [timeouts](https://www.terraform.io/ - **create** - (Default 15 minutes) Used for attaching volume. - **delete** - (Default 15 minutes) Used for detaching volume. -## Argument reference -Review the argument references that you can specify for your resource. +## Argument reference + +Review the argument references that you can specify for your resource. - `pi_cloud_instance_id` - (Required, Forces new resource, String) The GUID of the service instance associated with an account. - `pi_instance_id` - (Required, Forces new resource, String) The ID of the pvm instance to attach the volume to. - `pi_volume_id` - (Required, Forces new resource, String) The ID of the volume to attach. ## Attribute reference + In addition to all argument reference list, you can access the following attribute reference after your resource is created. -- `id` - (String) The unique identifier of the volume attach. The ID is composed of `//`. +- `id` - (String) The unique identifier of the volume attach. The ID is composed of `//`. - `status` - (String) The status of the volume. ## Import -The `ibm_pi_volume_attach` resource can be imported by using `power_instance_id`, `instance_id` and `volume_id`. +The `ibm_pi_volume_attach` resource can be imported by using `pi_cloud_instance_id`, `instance_id` and `volume_id`. -**Example** +### Example -``` -$ terraform import ibm_pi_volume_attach.example d7bec597-4726-451f-8a63-e62e6f19c32c/49fba6c9-23f8-40bc-9899-aca322ee7d5b/cea6651a-bc0a-4438-9f8a-a0770bbf3ebb +```bash +terraform import ibm_pi_volume_attach.example d7bec597-4726-451f-8a63-e62e6f19c32c/49fba6c9-23f8-40bc-9899-aca322ee7d5b/cea6651a-bc0a-4438-9f8a-a0770bbf3ebb ```