From add6e8c723fd81a594d2dd7449e4c97cff5d8f04 Mon Sep 17 00:00:00 2001 From: ismirlia <90468712+ismirlia@users.noreply.github.com> Date: Sun, 10 Dec 2023 20:51:14 -0600 Subject: [PATCH] Update pi_user_data to accept string input (#4974) * Add string support for pi_user_data field in instance creation * Add new user data test * Updated pi_user_data documentation * Remove duplicate import --- ibm/service/power/resource_ibm_pi_instance.go | 23 +++---- .../power/resource_ibm_pi_instance_test.go | 60 +++++++++++++++++++ website/docs/r/pi_instance.html.markdown | 2 +- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/ibm/service/power/resource_ibm_pi_instance.go b/ibm/service/power/resource_ibm_pi_instance.go index 0a5a760803..610bf44813 100644 --- a/ibm/service/power/resource_ibm_pi_instance.go +++ b/ibm/service/power/resource_ibm_pi_instance.go @@ -856,12 +856,13 @@ func isPIInstanceRefreshFunc(client *st.IBMPIInstanceClient, id, instanceReadySt } } -func checkBase64(input string) error { - _, err := base64.StdEncoding.DecodeString(input) +// This function takes the input string and encodes into base64 if isn't already encoded +func encodeBase64(userData string) string { + _, err := base64.StdEncoding.DecodeString(userData) if err != nil { - return fmt.Errorf("failed to check if input is base64 %s", err) + return base64.StdEncoding.EncodeToString([]byte(userData)) } - return err + return userData } func isWaitForPIInstanceStopped(ctx context.Context, client *st.IBMPIInstanceClient, id string) (interface{}, error) { @@ -1081,12 +1082,7 @@ func createSAPInstance(d *schema.ResourceData, sapClient *st.IBMPISAPInstanceCli } if u, ok := d.GetOk(helpers.PIInstanceUserData); ok { userData := u.(string) - err := checkBase64(userData) - if err != nil { - log.Printf("Data is not base64 encoded") - return nil, err - } - body.UserData = userData + body.UserData = encodeBase64(userData) } if sys, ok := d.GetOk(helpers.PIInstanceSystemType); ok { body.SysType = sys.(string) @@ -1205,11 +1201,6 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i if u, ok := d.GetOk(helpers.PIInstanceUserData); ok { userData = u.(string) } - err := checkBase64(userData) - if err != nil { - log.Printf("Data is not base64 encoded") - return nil, err - } //publicinterface := d.Get(helpers.PIInstancePublicNetwork).(bool) body := &models.PVMInstanceCreate{ @@ -1221,7 +1212,7 @@ func createPVMInstance(d *schema.ResourceData, client *st.IBMPIInstanceClient, i ImageID: flex.PtrToString(imageid), ProcType: flex.PtrToString(processortype), Replicants: replicants, - UserData: userData, + UserData: encodeBase64(userData), ReplicantNamingScheme: flex.PtrToString(replicationNamingScheme), ReplicantAffinityPolicy: flex.PtrToString(replicationpolicy), Networks: pvmNetworks, diff --git a/ibm/service/power/resource_ibm_pi_instance_test.go b/ibm/service/power/resource_ibm_pi_instance_test.go index f6dbf5fba2..9e5555fadd 100644 --- a/ibm/service/power/resource_ibm_pi_instance_test.go +++ b/ibm/service/power/resource_ibm_pi_instance_test.go @@ -62,6 +62,47 @@ func testAccCheckIBMPIInstanceConfig(name, instanceHealthStatus string) string { `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus) } +func testAccCheckIBMPIInstanceUserDataConfig(name, instanceHealthStatus string) string { + return fmt.Sprintf(` + resource "ibm_pi_key" "key" { + pi_cloud_instance_id = "%[1]s" + pi_key_name = "%[2]s" + pi_ssh_key = "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEArb2aK0mekAdbYdY9rwcmeNSxqVCwez3WZTYEq+1Nwju0x5/vQFPSD2Kp9LpKBbxx3OVLN4VffgGUJznz9DAr7veLkWaf3iwEil6U4rdrhBo32TuDtoBwiczkZ9gn1uJzfIaCJAJdnO80Kv9k0smbQFq5CSb9H+F5VGyFue/iVd5/b30MLYFAz6Jg1GGWgw8yzA4Gq+nO7HtyuA2FnvXdNA3yK/NmrTiPCdJAtEPZkGu9LcelkQ8y90ArlKfjtfzGzYDE4WhOufFxyWxciUePh425J2eZvElnXSdGha+FCfYjQcvqpCVoBAG70U4fJBGjB+HL/GpCXLyiYXPrSnzC9w==" + } + data "ibm_pi_image" "power_image" { + pi_image_name = "%[3]s" + pi_cloud_instance_id = "%[1]s" + } + data "ibm_pi_network" "power_networks" { + pi_cloud_instance_id = "%[1]s" + pi_network_name = "%[4]s" + } + resource "ibm_pi_volume" "power_volume" { + pi_volume_size = 20 + pi_volume_name = "%[2]s" + pi_volume_shareable = true + pi_volume_pool = data.ibm_pi_image.power_image.storage_pool + 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 = data.ibm_pi_image.power_image.id + pi_sys_type = "s922" + pi_cloud_instance_id = "%[1]s" + pi_storage_pool = data.ibm_pi_image.power_image.storage_pool + pi_health_status = "%[5]s" + pi_volume_ids = [ibm_pi_volume.power_volume.volume_id] + pi_network { + network_id = data.ibm_pi_network.power_networks.id + } + pi_user_data = "this is test user data" + } + `, acc.Pi_cloud_instance_id, name, acc.Pi_image, acc.Pi_network_name, instanceHealthStatus) +} + func testAccCheckIBMPIInstanceDeploymentTypeConfig(name, instanceHealthStatus string) string { return fmt.Sprintf(` resource "ibm_pi_key" "key" { @@ -238,6 +279,25 @@ func TestAccIBMPIInstanceBasic(t *testing.T) { }) } +func TestAccIBMPIInstanceUserData(t *testing.T) { + instanceRes := "ibm_pi_instance.power_instance" + name := fmt.Sprintf("tf-pi-instance-%d", acctest.RandIntRange(10, 100)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMPIInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMPIInstanceUserDataConfig(name, helpers.PIInstanceHealthWarning), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMPIInstanceExists(instanceRes), + resource.TestCheckResourceAttr(instanceRes, "pi_instance_name", name), + ), + }, + }, + }) +} + func TestAccIBMPIInstanceDeploymentType(t *testing.T) { instanceRes := "ibm_pi_instance.power_instance" name := fmt.Sprintf("tf-pi-instance-%d", acctest.RandIntRange(10, 100)) diff --git a/website/docs/r/pi_instance.html.markdown b/website/docs/r/pi_instance.html.markdown index 6a5e2234a9..1001d49f34 100644 --- a/website/docs/r/pi_instance.html.markdown +++ b/website/docs/r/pi_instance.html.markdown @@ -99,7 +99,7 @@ Review the argument references that you can specify for your resource. - `pi_storage_connection` - (Optional, String) - Storage Connectivity Group (SCG) for server deployment. Only supported value is `vSCSI`. - `pi_sys_type` - (Optional, String) The type of system on which to create the VM (s922/e880/e980/s1022). - Supported SAP system types are (e880/e980). -- `pi_user_data` - (Optional, String) The base64 encoded form of the user data `cloud-init` to pass to the instance during creation. +- `pi_user_data` - (Optional, String) The user data `cloud-init` to pass to the instance during creation. It can be a base64 encoded or an unencoded string. If it is an unencoded string, the provider will encode it before it passing it down. - `pi_virtual_cores_assigned` - (Optional, Integer) Specify the number of virtual cores to be assigned. - `pi_volume_ids` - (Optional, List of String) The list of volume IDs that you want to attach to the instance during creation. ## Attribute reference