Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added changes for adjustable iops and volume profile #3068

Merged
merged 1 commit into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 100 additions & 42 deletions ibm/resource_ibm_is_instance_volume_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ func resourceIBMISInstanceVolumeAttachment() *schema.Resource {
Delete: schema.DefaultTimeout(10 * time.Minute),
Update: schema.DefaultTimeout(10 * time.Minute),
},

CustomizeDiff: customdiff.Sequence(
func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error {
return resourceVolumeCapacityValidate(diff)
}),

CustomizeDiff: customdiff.All(
customdiff.Sequence(
func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error {
return resourceVolumeValidate(diff)
}),
),
Schema: map[string]*schema.Schema{
isInstanceId: {
Type: schema.TypeString,
Expand Down Expand Up @@ -96,11 +96,11 @@ func resourceIBMISInstanceVolumeAttachment() *schema.Resource {
},

isInstanceVolIops: {
Type: schema.TypeInt,
Computed: true,
Optional: true,
ForceNew: true,
Description: "The maximum I/O operations per second (IOPS) for the volume.",
Type: schema.TypeInt,
Computed: true,
Optional: true,
ConflictsWith: []string{isInstanceVolAttVol},
Description: "The maximum I/O operations per second (IOPS) for the volume.",
},

isInstanceVolumeAttVolumeReferenceName: {
Expand All @@ -112,11 +112,11 @@ func resourceIBMISInstanceVolumeAttachment() *schema.Resource {
},

isInstanceVolProfile: {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
Description: "The globally unique name for the volume profile to use for this volume.",
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{isInstanceVolAttVol},
Computed: true,
Description: "The globally unique name for the volume profile to use for this volume.",
},
isInstanceVolCapacity: {
Type: schema.TypeInt,
Expand Down Expand Up @@ -420,44 +420,105 @@ func instanceVolAttUpdate(d *schema.ResourceData, meta interface{}) error {
ID: &id,
}
flag := false
volAttPatchModel := &vpcv1.VolumeAttachmentPatch{}

// name && auto delete change
volAttNamePatchModel := &vpcv1.VolumeAttachmentPatch{}
if d.HasChange(isInstanceVolumeDeleteOnInstanceDelete) {
autoDelete := d.Get(isInstanceVolumeDeleteOnInstanceDelete).(bool)
volAttPatchModel.DeleteVolumeOnInstanceDelete = &autoDelete
volAttNamePatchModel.DeleteVolumeOnInstanceDelete = &autoDelete
flag = true
}

if d.HasChange(isInstanceVolAttName) {
name := d.Get(isInstanceVolAttName).(string)
volAttPatchModel.Name = &name
volAttNamePatchModel.Name = &name
flag = true
}
if flag {
volAttPatchModelAsPatch, err := volAttPatchModel.AsPatch()
if err != nil || volAttPatchModelAsPatch == nil {
volAttNamePatchModelAsPatch, err := volAttNamePatchModel.AsPatch()
if err != nil || volAttNamePatchModelAsPatch == nil {
return fmt.Errorf("Error Instance volume attachment (%s) as patch : %s", id, err)
}
updateInstanceVolAttOptions.VolumeAttachmentPatch = volAttPatchModelAsPatch
updateInstanceVolAttOptions.VolumeAttachmentPatch = volAttNamePatchModelAsPatch

instanceVolAttUpdate, response, err := instanceC.UpdateInstanceVolumeAttachment(updateInstanceVolAttOptions)
if err != nil || instanceVolAttUpdate == nil {
log.Printf("[DEBUG] Instance volume attachment creation err %s\n%s", err, response)
log.Printf("[DEBUG] Instance volume attachment updation err %s\n%s", err, response)
return err
}
}

if d.HasChange(isInstanceVolCapacity) {
// profile/iops update

volId := ""
if volIdOk, ok := d.GetOk(isInstanceVolAttVol); ok {
volId = volIdOk.(string)
}

if volId != "" && (d.HasChange(isInstanceVolIops) || d.HasChange(isInstanceVolProfile)) {
insId := d.Get(isInstanceId).(string)
getinsOptions := &vpcv1.GetInstanceOptions{
ID: &insId,
}
instance, response, err := instanceC.GetInstance(getinsOptions)
if err != nil || instance == nil {
return fmt.Errorf("Error retrieving Instance (%s) : %s\n%s", insId, err, response)
}

if instance != nil && *instance.Status != "running" {
actiontype := "start"
createinsactoptions := &vpcv1.CreateInstanceActionOptions{
InstanceID: &insId,
Type: &actiontype,
}
_, response, err = instanceC.CreateInstanceAction(createinsactoptions)
if err != nil {
return fmt.Errorf("Error starting Instance (%s) : %s\n%s", insId, err, response)
}
_, err = isWaitForInstanceAvailable(instanceC, insId, d.Timeout(schema.TimeoutCreate), d)
if err != nil {
return err
}
}
updateVolumeProfileOptions := &vpcv1.UpdateVolumeOptions{
ID: &volId,
}
volumeProfilePatchModel := &vpcv1.VolumePatch{}
if d.HasChange(isInstanceVolProfile) {
profile := d.Get(isInstanceVolProfile).(string)
volumeProfilePatchModel.Profile = &vpcv1.VolumeProfileIdentity{
Name: &profile,
}
} else if d.HasChange(isVolumeIops) {
profile := d.Get(isInstanceVolProfile).(string)
volumeProfilePatchModel.Profile = &vpcv1.VolumeProfileIdentity{
Name: &profile,
}
iops := int64(d.Get(isVolumeIops).(int))
volumeProfilePatchModel.Iops = &iops
}

volumeProfilePatch, err := volumeProfilePatchModel.AsPatch()
if err != nil {
return fmt.Errorf("Error calling asPatch for volumeProfilePatch: %s", err)
}
updateVolumeProfileOptions.VolumePatch = volumeProfilePatch
_, response, err = instanceC.UpdateVolume(updateVolumeProfileOptions)
if err != nil {
return fmt.Errorf("Error updating volume profile/iops: %s\n%s", err, response)
}
isWaitForVolumeAvailable(instanceC, volId, d.Timeout(schema.TimeoutCreate))
}

// capacity update

if volId != "" && d.HasChange(isInstanceVolCapacity) {

id := d.Get(isInstanceVolAttVol).(string)
getvolumeoptions := &vpcv1.GetVolumeOptions{
ID: &id,
ID: &volId,
}
vol, response, err := instanceC.GetVolume(getvolumeoptions)
if err != nil {
if response != nil && response.StatusCode == 404 {
d.SetId("")
return nil
}
return fmt.Errorf("Error Getting Volume (%s): %s\n%s", id, err, response)
}

Expand All @@ -483,27 +544,24 @@ func instanceVolAttUpdate(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error starting Instance (%s) : %s\n%s", instanceId, err, response)
}
_, err = isWaitForInstanceAvailable(instanceC, instanceId, d.Timeout(schema.TimeoutCreate), d)
if err != nil {
return err
}
return fmt.Errorf("Error starting Instance (%s) : %s\n%s", instanceId, err, response)
}

capacity := int64(d.Get(isVolumeCapacity).(int))
updateVolumeOptions := &vpcv1.UpdateVolumeOptions{
ID: &id,
ID: &volId,
}
volumePatchModel := &vpcv1.VolumePatch{}
volumePatchModel.Capacity = &capacity
volumePatch, err := volumePatchModel.AsPatch()
volumeCapacityPatchModel := &vpcv1.VolumePatch{}
volumeCapacityPatchModel.Capacity = &capacity
volumeCapacityPatch, err := volumeCapacityPatchModel.AsPatch()
if err != nil {
return fmt.Errorf("Error calling asPatch for VolumePatch: %s", err)
return fmt.Errorf("Error calling asPatch for volumeCapacityPatchModel: %s", err)
}
updateVolumeOptions.VolumePatch = volumePatch
updateVolumeOptions.VolumePatch = volumeCapacityPatch
_, response, err = instanceC.UpdateVolume(updateVolumeOptions)
if err != nil {
return fmt.Errorf("Error updating volume: %s\n%s", err, response)
return fmt.Errorf("Error updating volume capacity: %s\n%s", err, response)
}
_, err = isWaitForVolumeAvailable(instanceC, id, d.Timeout(schema.TimeoutCreate))
_, err = isWaitForVolumeAvailable(instanceC, volId, d.Timeout(schema.TimeoutCreate))
if err != nil {
return err
}
Expand Down
32 changes: 27 additions & 5 deletions ibm/resource_ibm_is_instance_volume_attachment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,33 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE
attName := fmt.Sprintf("tf-volatt-%d", acctest.RandIntRange(10, 100))
autoDelete := true
volName := fmt.Sprintf("tf-vol-%d", acctest.RandIntRange(10, 100))
iops1 := int64(600)
iops2 := int64(900)

capacity1 := int64(20)
capacity2 := int64(22)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIBMISInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName, autoDelete, capacity1),
Config: testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName, autoDelete, capacity1, iops1),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMISInstanceVolumeAttachmentExists("ibm_is_instance_volume_attachment.testacc_att", instanceVolAtt),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "name", attName),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "delete_volume_on_instance_delete", fmt.Sprintf("%t", autoDelete)),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "capacity", fmt.Sprintf("%d", capacity1)),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "iops", "600"),
),
},
{
Config: testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName, autoDelete, capacity1, iops2),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMISInstanceVolumeAttachmentExists("ibm_is_instance_volume_attachment.testacc_att", instanceVolAtt),
resource.TestCheckResourceAttr(
Expand All @@ -44,10 +62,13 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE
"ibm_is_instance_volume_attachment.testacc_att", "delete_volume_on_instance_delete", fmt.Sprintf("%t", autoDelete)),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "capacity", fmt.Sprintf("%d", capacity1)),
resource.TestCheckResourceAttr(
"ibm_is_instance_volume_attachment.testacc_att", "iops", "900"),
),
},

{
Config: testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName, autoDelete, capacity2),
Config: testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName, autoDelete, capacity2, iops2),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMISInstanceVolumeAttachmentExists("ibm_is_instance_volume_attachment.testacc_att", instanceVolAtt),
resource.TestCheckResourceAttr(
Expand Down Expand Up @@ -108,7 +129,7 @@ func testAccCheckIBMISInstanceVolumeAttachmentExists(n string, instanceVolAtt st
}
}

func testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName string, autoDelete bool, capacity int64) string {
func testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshname, publicKey, name, attName, volName string, autoDelete bool, capacity, iops int64) string {
return fmt.Sprintf(`
resource "ibm_is_vpc" "testacc_vpc" {
name = "%s"
Expand Down Expand Up @@ -145,12 +166,13 @@ func testAccCheckIBMISInstanceVolumeAttachmentConfig(vpcname, subnetname, sshnam
instance = ibm_is_instance.testacc_instance.id

name = "%s"
profile = "general-purpose"
profile = "custom"
capacity = %d
iops = %d

delete_volume_on_instance_delete = %t
volume_name = "%s"
}

`, vpcname, subnetname, ISZoneName, sshname, publicKey, name, isImage, instanceProfileName, ISZoneName, attName, capacity, autoDelete, volName)
`, vpcname, subnetname, ISZoneName, sshname, publicKey, name, isImage, instanceProfileName, ISZoneName, attName, capacity, iops, autoDelete, volName)
}
Loading