Skip to content

Commit

Permalink
granular CRN for volumes
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander-Kita authored and kavya498 committed Oct 11, 2024
1 parent 405900d commit 91ccc79
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 11 deletions.
26 changes: 24 additions & 2 deletions ibm/service/power/data_source_ibm_pi_instance_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ package power

import (
"context"
"log"

"github.com/IBM-Cloud/power-go-client/clients/instance"
"github.com/IBM-Cloud/power-go-client/power/models"
"github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns"
"github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -49,6 +51,11 @@ func DataSourceIBMPIInstanceVolumes() *schema.Resource {
Description: "Indicates if the volume is boot capable.",
Type: schema.TypeBool,
},
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
Attr_Href: {
Computed: true,
Description: "The hyper link of the volume.",
Expand Down Expand Up @@ -89,6 +96,13 @@ func DataSourceIBMPIInstanceVolumes() *schema.Resource {
Description: "The disk type that is used for this volume.",
Type: schema.TypeString,
},
Attr_UserTags: {
Computed: true,
Description: "List of user tags attached to the resource.",
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Type: schema.TypeSet,
},
},
},
Type: schema.TypeList,
Expand All @@ -114,12 +128,12 @@ func dataSourceIBMPIInstanceVolumesRead(ctx context.Context, d *schema.ResourceD
var clientgenU, _ = uuid.GenerateUUID()
d.SetId(clientgenU)
d.Set(Attr_BootVolumeID, *volumedata.Volumes[0].VolumeID)
d.Set(Attr_InstanceVolumes, flattenVolumesInstances(volumedata.Volumes))
d.Set(Attr_InstanceVolumes, flattenVolumesInstances(volumedata.Volumes, meta))

return nil
}

func flattenVolumesInstances(list []*models.VolumeReference) []map[string]interface{} {
func flattenVolumesInstances(list []*models.VolumeReference, meta interface{}) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
l := map[string]interface{}{
Expand All @@ -133,6 +147,14 @@ func flattenVolumesInstances(list []*models.VolumeReference) []map[string]interf
Attr_State: *i.State,
Attr_Type: *i.DiskType,
}
if i.Crn != "" {
l[Attr_CRN] = i.Crn
tags, err := flex.GetGlobalTagsUsingCRN(meta, string(i.Crn), "", UserTagType)
if err != nil {
log.Printf("Error on get of volume (%s) user_tags: %s", *i.VolumeID, err)
}
l[Attr_UserTags] = tags
}
result = append(result, l)
}
return result
Expand Down
22 changes: 22 additions & 0 deletions ibm/service/power/data_source_ibm_pi_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package power

import (
"context"
"log"

"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/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
Expand Down Expand Up @@ -47,6 +49,11 @@ func DataSourceIBMPIVolume() *schema.Resource {
Description: "Indicates if the volume is boot capable.",
Type: schema.TypeBool,
},
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
Attr_ConsistencyGroupName: {
Computed: true,
Description: "Consistency group name if volume is a part of volume group.",
Expand Down Expand Up @@ -112,6 +119,13 @@ func DataSourceIBMPIVolume() *schema.Resource {
Description: "The state of the volume.",
Type: schema.TypeString,
},
Attr_UserTags: {
Computed: true,
Description: "List of user tags attached to the resource.",
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
Type: schema.TypeSet,
},
Attr_VolumePool: {
Computed: true,
Description: "Volume pool, name of storage pool where the volume is located.",
Expand Down Expand Up @@ -144,6 +158,14 @@ func dataSourceIBMPIVolumeRead(ctx context.Context, d *schema.ResourceData, meta
d.Set(Attr_AuxiliaryVolumeName, volumedata.AuxVolumeName)
d.Set(Attr_Bootable, volumedata.Bootable)
d.Set(Attr_ConsistencyGroupName, volumedata.ConsistencyGroupName)
if volumedata.Crn != "" {
d.Set(Attr_CRN, volumedata.Crn)
tags, err := flex.GetTagsUsingCRN(meta, string(volumedata.Crn))
if err != nil {
log.Printf("Error on get of pi volume (%s) user_tags: %s", *volumedata.VolumeID, err)
}
d.Set(Attr_UserTags, tags)
}
d.Set(Attr_DiskType, volumedata.DiskType)
d.Set(Attr_GroupID, volumedata.GroupID)
d.Set(Attr_IOThrottleRate, volumedata.IoThrottleRate)
Expand Down
3 changes: 2 additions & 1 deletion ibm/service/power/data_source_ibm_pi_volume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import (
)

func TestAccIBMPIVolumeDataSource_basic(t *testing.T) {
volumeRes := "data.ibm_pi_volume.testacc_ds_volume"
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMPIVolumeDataSourceConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.ibm_pi_volume.testacc_ds_volume", "id"),
resource.TestCheckResourceAttrSet(volumeRes, "id"),
),
},
},
Expand Down
41 changes: 41 additions & 0 deletions ibm/service/power/resource_ibm_pi_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ func ResourceIBMPIVolume() *schema.Resource {
Optional: true,
Type: schema.TypeBool,
},
Arg_UserTags: {
Description: "The user tags attached to this resource.",
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Set: schema.HashString,
Type: schema.TypeSet,
},
Arg_VolumeName: {
Description: "The name of the volume.",
Required: true,
Expand Down Expand Up @@ -136,6 +143,11 @@ func ResourceIBMPIVolume() *schema.Resource {
Description: "The consistency group name if volume is a part of volume group.",
Type: schema.TypeString,
},
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
Attr_DeleteOnTermination: {
Computed: true,
Description: "Indicates if the volume should be deleted when the server terminates.",
Expand Down Expand Up @@ -265,6 +277,9 @@ func resourceIBMPIVolumeCreate(ctx context.Context, d *schema.ResourceData, meta
}

}
if v, ok := d.GetOk(Arg_UserTags); ok {
body.UserTags = flex.FlattenSet(v.(*schema.Set))
}

client := instance.NewIBMPIVolumeClient(ctx, sess, cloudInstanceID)
vol, err := client.CreateVolume(body)
Expand All @@ -280,6 +295,14 @@ func resourceIBMPIVolumeCreate(ctx context.Context, d *schema.ResourceData, meta
return diag.FromErr(err)
}

if _, ok := d.GetOk(Arg_UserTags); ok {
oldList, newList := d.GetChange(Arg_UserTags)
err := flex.UpdateGlobalTagsUsingCRN(oldList, newList, meta, string(vol.Crn), "", UserTagType)
if err != nil {
log.Printf("Error on update of volume (%s) pi_user_tags during creation: %s", volumeid, err)
}
}

return resourceIBMPIVolumeRead(ctx, d, meta)
}

Expand All @@ -304,6 +327,14 @@ func resourceIBMPIVolumeRead(ctx context.Context, d *schema.ResourceData, meta i
if vol.VolumeID != nil {
d.Set(Attr_VolumeID, vol.VolumeID)
}
if vol.Crn != "" {
d.Set(Attr_CRN, vol.Crn)
tags, err := flex.GetGlobalTagsUsingCRN(meta, string(vol.Crn), "", UserTagType)
if err != nil {
log.Printf("Error on get of volume (%s) pi_user_tags: %s", *vol.VolumeID, err)
}
d.Set(Arg_UserTags, tags)
}
d.Set(Arg_VolumeName, vol.Name)
d.Set(Arg_VolumePool, vol.VolumePool)
if vol.Shareable != nil {
Expand Down Expand Up @@ -383,6 +414,16 @@ func resourceIBMPIVolumeUpdate(ctx context.Context, d *schema.ResourceData, meta
}
}

if d.HasChange(Arg_UserTags) {
crn := d.Get(Attr_CRN)
if crn != nil && crn != "" {
oldList, newList := d.GetChange(Arg_UserTags)
err := flex.UpdateGlobalTagsUsingCRN(oldList, newList, meta, crn.(string), "", UserTagType)
if err != nil {
log.Printf("Error on update of pi volume (%s) pi_user_tags: %s", volumeID, err)
}
}
}
return resourceIBMPIVolumeRead(ctx, d, meta)
}

Expand Down
12 changes: 12 additions & 0 deletions ibm/service/power/resource_ibm_pi_volume_clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ func ResourceIBMPIVolumeClone() *schema.Resource {
Optional: true,
Type: schema.TypeBool,
},
Arg_UserTags: {
Description: "The user tags attached to this resource.",
Elem: &schema.Schema{Type: schema.TypeString},
ForceNew: true,
Optional: true,
Set: schema.HashString,
Type: schema.TypeSet,
},
Arg_VolumeCloneName: {
Description: "The base name of the newly cloned volume(s).",
ForceNew: true,
Expand Down Expand Up @@ -135,6 +143,10 @@ func resourceIBMPIVolumeCloneCreate(ctx context.Context, d *schema.ResourceData,
body.TargetReplicationEnabled = flex.PtrToBool(d.Get(Arg_ReplicationEnabled).(bool))
}

if v, ok := d.GetOk(Arg_UserTags); ok {
body.UserTags = flex.FlattenSet(v.(*schema.Set))
}

client := instance.NewIBMPICloneVolumeClient(ctx, sess, cloudInstanceID)
volClone, err := client.Create(body)
if err != nil {
Expand Down
61 changes: 53 additions & 8 deletions ibm/service/power/resource_ibm_pi_volume_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

func TestAccIBMPIVolumebasic(t *testing.T) {
name := fmt.Sprintf("tf-pi-volume-%d", acctest.RandIntRange(10, 100))
volumeRes := "ibm_pi_volume.power_volume"
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
Expand All @@ -29,19 +30,16 @@ func TestAccIBMPIVolumebasic(t *testing.T) {
{
Config: testAccCheckIBMPIVolumeConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIVolumeExists("ibm_pi_volume.power_volume"),
resource.TestCheckResourceAttr(
"ibm_pi_volume.power_volume", "pi_volume_name", name),
testAccCheckIBMPIVolumeExists(volumeRes),
resource.TestCheckResourceAttr(volumeRes, "pi_volume_name", name),
),
},
{
Config: testAccCheckIBMPIVolumeSizeConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIVolumeExists("ibm_pi_volume.power_volume"),
resource.TestCheckResourceAttr(
"ibm_pi_volume.power_volume", "pi_volume_name", name),
resource.TestCheckResourceAttr(
"ibm_pi_volume.power_volume", "pi_volume_size", "30"),
testAccCheckIBMPIVolumeExists(volumeRes),
resource.TestCheckResourceAttr(volumeRes, "pi_volume_name", name),
resource.TestCheckResourceAttr(volumeRes, "pi_volume_size", "30"),
),
},
},
Expand Down Expand Up @@ -260,3 +258,50 @@ func testAccCheckIBMPIVolumeUpdateBasicConfig(name, piCloudInstanceId, piStorage
pi_volume_type = "%[4]v"
}`, name, piCloudInstanceId, piStoragePool, piStorageType)
}

func TestAccIBMPIVolumeUserTags(t *testing.T) {
name := fmt.Sprintf("tf-pi-volume-%d", acctest.RandIntRange(10, 100))
volumeRes := "ibm_pi_volume.power_volume"
userTagsString := `["env:dev","test_tag"]`
userTagsStringUpdated := `["env:dev","test_tag","test_tag2"]`
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
CheckDestroy: testAccCheckIBMPIVolumeDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMPIVolumeUserTagsConfig(name, userTagsString),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIVolumeExists(volumeRes),
resource.TestCheckResourceAttr(volumeRes, "pi_volume_name", name),
resource.TestCheckResourceAttr(volumeRes, "pi_user_tags.#", "2"),
resource.TestCheckTypeSetElemAttr(volumeRes, "pi_user_tags.*", "env:dev"),
resource.TestCheckTypeSetElemAttr(volumeRes, "pi_user_tags.*", "test_tag"),
),
},
{
Config: testAccCheckIBMPIVolumeUserTagsConfig(name, userTagsStringUpdated),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIVolumeExists(volumeRes),
resource.TestCheckResourceAttr(volumeRes, "pi_volume_name", name),
resource.TestCheckResourceAttr(volumeRes, "pi_user_tags.#", "3"),
resource.TestCheckTypeSetElemAttr(volumeRes, "pi_user_tags.*", "env:dev"),
resource.TestCheckTypeSetElemAttr(volumeRes, "pi_user_tags.*", "test_tag"),
resource.TestCheckTypeSetElemAttr(volumeRes, "pi_user_tags.*", "test_tag2"),
),
},
},
})
}

func testAccCheckIBMPIVolumeUserTagsConfig(name string, userTagsString string) string {
return fmt.Sprintf(`
resource "ibm_pi_volume" "power_volume" {
pi_cloud_instance_id = "%[2]s"
pi_volume_name = "%[1]s"
pi_volume_shareable = true
pi_volume_size = 20
pi_volume_type = "tier1"
pi_user_tags = %[3]s
}`, name, acc.Pi_cloud_instance_id, userTagsString)
}
2 changes: 2 additions & 0 deletions website/docs/d/pi_instance_volumes.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ In addition to all argument reference list, you can access the following attribu

Nested scheme for `instance_volumes`:
- `bootable`- (Boolean) Indicates if the volume is boot capable.
- `crn` - (String) The CRN of this resource.
- `href` - (String) The hyper link of the volume.
- `id` - (String) The unique identifier of the volume.
- `name` - (String) The name of the volume.
Expand All @@ -61,3 +62,4 @@ In addition to all argument reference list, you can access the following attribu
- `size` - (Integer) The size of this volume in GB.
- `state` - (String) The state of the volume.
- `type` - (String) The disk type that is used for this volume.
- `user_tags` - (List) List of user tags attached to the resource.
3 changes: 3 additions & 0 deletions website/docs/d/pi_volume.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ In addition to all argument reference list, you can access the following attribu
- `auxiliary_volume_name` - (String) The auxiliary volume name.
- `bootable` - (Boolean) Indicates if the volume is boot capable.
- `consistency_group_name` - (String) Consistency group name if volume is a part of volume group.
- `crn` - (String) The CRN of this resource.
- `disk_type` - (String) The disk type that is used for the volume.
- `group_id` - (String) The volume group id in which the volume belongs.
- `id` - (String) The unique identifier of the volume.
Expand All @@ -65,5 +66,7 @@ In addition to all argument reference list, you can access the following attribu
- `shareable` - (String) Indicates if the volume is shareable between VMs.
- `size` - (Integer) The size of the volume in GB.
- `state` - (String) The state of the volume.
- `user_tags` - (List) List of user tags attached to the resource.
- `volume_pool` - (String) Volume pool, name of storage pool where the volume is located.
- `wwn` - (String) The world wide name of the volume.

2 changes: 2 additions & 0 deletions website/docs/r/pi_volume.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Review the argument references that you can specify for your resource.
- `pi_anti_affinity_volumes`- (Optional, String) List of volumes to base volume anti-affinity policy against; required if requesting `anti-affinity` and `pi_anti_affinity_instances` is not provided.
- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account.
- `pi_replication_enabled` - (Optional, Boolean) Indicates if the volume should be replication enabled or not.
- `pi_user_tags` - (Optional, List) The user tags attached to this resource.
- `pi_volume_name` - (Required, String) The name of the volume.
- `pi_volume_pool` - (Optional, String) Volume pool where the volume will be created; if provided then `pi_affinity_policy` values will be ignored.
- `pi_volume_shareable` - (Required, Boolean) If set to **true**, the volume can be shared across Power Systems Virtual Server instances. If set to **false**, you can attach it only to one instance.
Expand All @@ -72,6 +73,7 @@ In addition to all argument reference list, you can access the following attribu
- `auxiliary` - (Boolean) Indicates if the volume is auxiliary or not.
- `auxiliary_volume_name` - (String) The auxiliary volume name.
- `consistency_group_name` - (String) The consistency group name if volume is a part of volume group.
- `crn` - (String) The CRN of this resource.
- `delete_on_termination` - (Boolean) Indicates if the volume should be deleted when the server terminates.
- `group_id` - (String) The volume group id to which volume belongs.
- `id` - (String) The unique identifier of the volume. The ID is composed of `<cloud_instance_id>/<volume_id>`.
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/pi_volume_clone.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Review the argument references that you can specify for your resource.
- `pi_cloud_instance_id` - (Required, String) The GUID of the service instance associated with an account.
- `pi_replication_enabled` - (Optional, Boolean) Indicates whether the cloned volume should have replication enabled. If no value is provided, it will default to the replication status of the source volume(s).
- `pi_target_storage_tier` - (Optional, String) The storage tier for the cloned volume(s). To get a list of available storage tiers, please use the [ibm_pi_storage_types_capacity](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/data-sources/pi_storage_types_capacity) data source.
- `pi_user_tags` - (Optional, List) The user tags attached to this resource.
- `pi_volume_clone_name` - (Required, String) The base name of the newly cloned volume(s).
- `pi_volume_ids` - (Required, Set of String) List of volumes to be cloned.

Expand Down

0 comments on commit 91ccc79

Please sign in to comment.