Skip to content

Commit

Permalink
Granular CRN for images
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 68d99ba commit fef11ba
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 9 deletions.
9 changes: 8 additions & 1 deletion ibm/acctest/acctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ var (
Pi_image_bucket_name string
Pi_image_bucket_region string
Pi_image_bucket_secret_key string
Pi_image_id string
Pi_instance_name string
Pi_key_name string
Pi_network_name string
Expand Down Expand Up @@ -1047,7 +1048,13 @@ func init() {
Pi_image_bucket_region = os.Getenv("PI_IMAGE_BUCKET_REGION")
if Pi_image_bucket_region == "" {
Pi_image_bucket_region = "us-east"
fmt.Println("[INFO] Set the environment variable PI_IMAGE_BUCKET_REGION for testing ibm_pi_image_export resource else it is set to default value 'us-east'")
fmt.Println("[INFO] Set the environment variable PI_IMAGE_BUCKET_REGION for testing ibm_pi_image resource else it is set to default value 'us-east'")
}

Pi_image_id = os.Getenv("PI_IMAGE_ID")
if Pi_image_id == "" {
Pi_image_id = "IBMi-72-09-2924-11"
fmt.Println("[INFO] Set the environment variable PI_IMAGE_ID for testing ibm_pi_image resource else it is set to default value 'IBMi-72-09-2924-11'")
}

Pi_key_name = os.Getenv("PI_KEY_NAME")
Expand Down
8 changes: 8 additions & 0 deletions ibm/service/power/data_source_ibm_pi_catalog_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func DataSourceIBMPICatalogImages() *schema.Resource {
Description: "Date of image creation",
Type: schema.TypeString,
},
Attr_CRN: {
Computed: true,
Description: "CRN of this resource.",
Type: schema.TypeString,
},
Attr_Description: {
Computed: true,
Description: "The description of an image.",
Expand Down Expand Up @@ -159,6 +164,9 @@ func dataSourceIBMPICatalogImagesRead(ctx context.Context, d *schema.ResourceDat
if i.CreationDate != nil {
image[Attr_CreationDate] = i.CreationDate.String()
}
if i.Crn != "" {
image[Attr_CRN] = i.Crn
}
if i.Href != nil {
image[Attr_Href] = *i.Href
}
Expand Down
22 changes: 22 additions & 0 deletions ibm/service/power/data_source_ibm_pi_image.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 @@ -37,6 +39,11 @@ func DataSourceIBMPIImage() *schema.Resource {
Description: "The CPU architecture that the image is designed for. ",
Type: schema.TypeString,
},
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
Attr_Hypervisor: {
Computed: true,
Description: "Hypervision Type.",
Expand Down Expand Up @@ -73,6 +80,13 @@ func DataSourceIBMPIImage() *schema.Resource {
Description: "The storage type for this image.",
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,
},
},
}
}
Expand All @@ -93,6 +107,14 @@ func dataSourceIBMPIImagesRead(ctx context.Context, d *schema.ResourceData, meta

d.SetId(*imagedata.ImageID)
d.Set(Attr_Architecture, imagedata.Specifications.Architecture)
if imagedata.Crn != "" {
d.Set(Attr_CRN, imagedata.Crn)
tags, err := flex.GetTagsUsingCRN(meta, string(imagedata.Crn))
if err != nil {
log.Printf("Error on get of pi image (%s) user_tags: %s", *imagedata.ImageID, err)
}
d.Set(Attr_UserTags, tags)
}
d.Set(Attr_Hypervisor, imagedata.Specifications.HypervisorType)
d.Set(Attr_ImageType, imagedata.Specifications.ImageType)
d.Set(Attr_OperatingSystem, imagedata.Specifications.OperatingSystem)
Expand Down
27 changes: 25 additions & 2 deletions ibm/service/power/data_source_ibm_pi_images.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 All @@ -34,6 +36,11 @@ func DataSourceIBMPIImages() *schema.Resource {
Description: "List of all supported images.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
Attr_Href: {
Computed: true,
Description: "The hyper link of an image.",
Expand Down Expand Up @@ -69,6 +76,13 @@ func DataSourceIBMPIImages() *schema.Resource {
Description: "The storage type of an image.",
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 @@ -93,12 +107,12 @@ func dataSourceIBMPIImagesAllRead(ctx context.Context, d *schema.ResourceData, m

var clientgenU, _ = uuid.GenerateUUID()
d.SetId(clientgenU)
d.Set(Attr_ImageInfo, flattenStockImages(imagedata.Images))
d.Set(Attr_ImageInfo, flattenStockImages(imagedata.Images, meta))

return nil
}

func flattenStockImages(list []*models.ImageReference) []map[string]interface{} {
func flattenStockImages(list []*models.ImageReference, meta interface{}) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
l := map[string]interface{}{
Expand All @@ -110,6 +124,15 @@ func flattenStockImages(list []*models.ImageReference) []map[string]interface{}
Attr_StoragePool: *i.StoragePool,
Attr_StorageType: *i.StorageType,
}
if i.Crn != "" {
l[Attr_CRN] = i.Crn
tags, err := flex.GetTagsUsingCRN(meta, string(i.Crn))
if err != nil {
log.Printf(
"Error on get of image (%s) user_tags: %s", *i.ImageID, err)
}
l[Attr_UserTags] = tags
}
result = append(result, l)
}
return result
Expand Down
68 changes: 68 additions & 0 deletions ibm/service/power/resource_ibm_pi_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ func ResourceIBMPIImage() *schema.Resource {
CreateContext: resourceIBMPIImageCreate,
ReadContext: resourceIBMPIImageRead,
DeleteContext: resourceIBMPIImageDelete,
UpdateContext: resourceIBMPIImageUpdate,
Importer: &schema.ResourceImporter{},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(60 * time.Minute),
Delete: schema.DefaultTimeout(60 * time.Minute),
Update: schema.DefaultTimeout(60 * time.Minute),
},

Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -188,8 +190,20 @@ func ResourceIBMPIImage() *schema.Resource {
},
},
},
Arg_UserTags: {
Description: "The user tags attached to this resource.",
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Set: schema.HashString,
Type: schema.TypeSet,
},

// Computed Attribute
Attr_CRN: {
Computed: true,
Description: "The CRN of this resource.",
Type: schema.TypeString,
},
"image_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -219,6 +233,9 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta
ImageID: imageid,
Source: &source,
}
if tags, ok := d.GetOk(Arg_UserTags); ok {
body.UserTags = flex.FlattenSet(tags.(*schema.Set))
}
imageResponse, err := client.Create(body)
if err != nil {
return diag.FromErr(err)
Expand All @@ -232,6 +249,16 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta
log.Printf("[DEBUG] err %s", err)
return diag.FromErr(err)
}

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

// COS image import
Expand All @@ -240,6 +267,7 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta
bucketImageFileName := d.Get(helpers.PIImageBucketFileName).(string)
bucketRegion := d.Get(helpers.PIImageBucketRegion).(string)
bucketAccess := d.Get(helpers.PIImageBucketAccess).(string)

body := &models.CreateCosImageImportJob{
ImageName: &imageName,
BucketName: &bucketName,
Expand Down Expand Up @@ -297,6 +325,9 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta
}
body.ImportDetails = &importDetailsModel
}
if tags, ok := d.GetOk(Arg_UserTags); ok {
body.UserTags = flex.FlattenSet(tags.(*schema.Set))
}
imageResponse, err := client.CreateCosImage(body)
if err != nil {
return diag.FromErr(err)
Expand All @@ -313,6 +344,16 @@ func resourceIBMPIImageCreate(ctx context.Context, d *schema.ResourceData, meta
if err != nil {
return diag.FromErr(err)
}

if _, ok := d.GetOk(Arg_UserTags); ok {
if image.Crn != "" {
oldList, newList := d.GetChange(Arg_UserTags)
err := flex.UpdateGlobalTagsUsingCRN(oldList, newList, meta, string(image.Crn), "", UserTagType)
if err != nil {
log.Printf("Error on update of pi image (%s) pi_user_tags during creation: %s", *image.ImageID, err)
}
}
}
d.SetId(fmt.Sprintf("%s/%s", cloudInstanceID, *image.ImageID))
}

Expand Down Expand Up @@ -345,12 +386,39 @@ func resourceIBMPIImageRead(ctx context.Context, d *schema.ResourceData, meta in
}

imageid := *imagedata.ImageID
if imagedata.Crn != "" {
d.Set(Attr_CRN, imagedata.Crn)
tags, err := flex.GetGlobalTagsUsingCRN(meta, string(imagedata.Crn), "", UserTagType)
if err != nil {
log.Printf("Error on get of image (%s) pi_user_tags: %s", *imagedata.ImageID, err)
}
d.Set(Arg_UserTags, tags)
}
d.Set("image_id", imageid)
d.Set(helpers.PICloudInstanceId, cloudInstanceID)

return nil
}

func resourceIBMPIImageUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
_, imageID, err := splitID(d.Id())
if err != nil {
return diag.FromErr(err)
}

if d.HasChange(Arg_UserTags) {
if crn, ok := d.GetOk(Attr_CRN); ok {
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 image (%s) pi_user_tags: %s", imageID, err)
}
}
}

return resourceIBMPIImageRead(ctx, d, meta)
}

func resourceIBMPIImageDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
sess, err := meta.(conns.ClientSession).IBMPISession()
if err != nil {
Expand Down
59 changes: 53 additions & 6 deletions ibm/service/power/resource_ibm_pi_image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
)

func TestAccIBMPIImagebasic(t *testing.T) {

imageRes := "ibm_pi_image.power_image"
name := fmt.Sprintf("tf-pi-image-%d", acctest.RandIntRange(10, 100))
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Expand All @@ -30,9 +30,8 @@ func TestAccIBMPIImagebasic(t *testing.T) {
{
Config: testAccCheckIBMPIImageConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIImageExists("ibm_pi_image.power_image"),
resource.TestCheckResourceAttr(
"ibm_pi_image.power_image", "pi_image_name", name),
testAccCheckIBMPIImageExists(imageRes),
resource.TestCheckResourceAttr(imageRes, "pi_image_name", name),
),
},
},
Expand Down Expand Up @@ -137,6 +136,54 @@ func testAccCheckIBMPIImageCOSPublicConfig(name string) string {
`, name, acc.Pi_cloud_instance_id, acc.Pi_image_bucket_name, acc.Pi_image_bucket_file_name)
}

func TestAccIBMPIImageUserTags(t *testing.T) {
imageRes := "ibm_pi_image.power_image"
name := fmt.Sprintf("tf-pi-image-%d", acctest.RandIntRange(10, 100))
userTagsString := `["env:dev","test_tag"]`
userTagsStringUpdated := `["env:dev","test_tag","ibm"]`
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
CheckDestroy: testAccCheckIBMPIImageDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMPIImageUserTagsConfig(name, userTagsString),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIImageExists(imageRes),
resource.TestCheckResourceAttr(imageRes, "pi_image_name", name),
resource.TestCheckResourceAttrSet(imageRes, "image_id"),
resource.TestCheckResourceAttr(imageRes, "pi_user_tags.#", "2"),
resource.TestCheckTypeSetElemAttr(imageRes, "pi_user_tags.*", "env:dev"),
resource.TestCheckTypeSetElemAttr(imageRes, "pi_user_tags.*", "test_tag"),
),
},
{
Config: testAccCheckIBMPIImageUserTagsConfig(name, userTagsStringUpdated),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMPIImageExists(imageRes),
resource.TestCheckResourceAttr(imageRes, "pi_image_name", name),
resource.TestCheckResourceAttrSet(imageRes, "image_id"),
resource.TestCheckResourceAttr(imageRes, "pi_user_tags.#", "3"),
resource.TestCheckTypeSetElemAttr(imageRes, "pi_user_tags.*", "env:dev"),
resource.TestCheckTypeSetElemAttr(imageRes, "pi_user_tags.*", "test_tag"),
resource.TestCheckTypeSetElemAttr(imageRes, "pi_user_tags.*", "ibm"),
),
},
},
})
}

func testAccCheckIBMPIImageUserTagsConfig(name string, userTagsString string) string {
return fmt.Sprintf(`
resource "ibm_pi_image" "power_image" {
pi_cloud_instance_id = "%[2]s"
pi_image_id = "%[3]s"
pi_image_name = "%[1]s"
pi_user_tags = %[4]s
}
`, name, acc.Pi_cloud_instance_id, acc.Pi_image, userTagsString)
}

func TestAccIBMPIImageBYOLImport(t *testing.T) {
imageRes := "ibm_pi_image.cos_image"
name := fmt.Sprintf("tf-pi-image-byoi-%d", acctest.RandIntRange(10, 100))
Expand Down Expand Up @@ -164,7 +211,7 @@ func testAccCheckIBMPIImageBYOLConfig(name string) string {
pi_image_bucket_access = "private"
pi_image_bucket_file_name = "%[4]s"
pi_image_bucket_name = "%[3]s"
pi_image_bucket_region = "us-east"
pi_image_bucket_region = "%[7]s"
pi_image_name = "%[1]s"
pi_image_secret_key = "%[6]s"
pi_image_storage_type = "tier3"
Expand All @@ -174,5 +221,5 @@ func testAccCheckIBMPIImageBYOLConfig(name string) string {
vendor = "SAP"
}
}
`, name, acc.Pi_cloud_instance_id, acc.Pi_image_bucket_name, acc.Pi_image_bucket_file_name, acc.Pi_image_bucket_access_key, acc.Pi_image_bucket_secret_key)
`, name, acc.Pi_cloud_instance_id, acc.Pi_image_bucket_name, acc.Pi_image_bucket_file_name, acc.Pi_image_bucket_access_key, acc.Pi_image_bucket_secret_key, acc.Pi_image_bucket_region)
}
Loading

0 comments on commit fef11ba

Please sign in to comment.