From b3419f5e1e12ca06d8b73918d1f36f15f01d280f Mon Sep 17 00:00:00 2001 From: Deepak Selvakumar <77007253+deepaksibm@users.noreply.github.com> Date: Tue, 19 Dec 2023 10:29:08 +0530 Subject: [PATCH] Enhancement: Added operating system attributes to is images data sources (#4998) * Enhancement: Added operating system attributes to is images data sources * set the values * test and doc changes --- ibm/service/vpc/data_source_ibm_is_image.go | 196 +++++++++++++++++- .../vpc/data_source_ibm_is_image_test.go | 37 ++++ ibm/service/vpc/data_source_ibm_is_images.go | 111 ++++++++++ .../vpc/data_source_ibm_is_images_test.go | 34 +++ website/docs/d/is_image.html.markdown | 24 +++ website/docs/d/is_images.html.markdown | 22 ++ 6 files changed, 422 insertions(+), 2 deletions(-) diff --git a/ibm/service/vpc/data_source_ibm_is_image.go b/ibm/service/vpc/data_source_ibm_is_image.go index 760014aff7..61248d9c81 100644 --- a/ibm/service/vpc/data_source_ibm_is_image.go +++ b/ibm/service/vpc/data_source_ibm_is_image.go @@ -48,13 +48,107 @@ func DataSourceIBMISImage() *schema.Resource { ValidateFunc: validate.ValidateAllowedStringValues([]string{"public", "private"}), Description: "Whether the image is publicly visible or private to the account", }, - + "resource_group": { + Type: schema.TypeList, + Computed: true, + Description: "The resource group for this IPsec policy.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL for this resource group.", + }, + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this resource group.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The user-defined name for this resource group.", + }, + }, + }, + }, "status": { Type: schema.TypeString, Computed: true, Description: "The status of this image", }, - + "status_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current status (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A snake case string succinctly identifying the status reason.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the status reason.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about this status reason.", + }, + }, + }, + }, + "operating_system": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "architecture": { + Type: schema.TypeString, + Computed: true, + Description: "The operating system architecture", + }, + "dedicated_host_only": { + Type: schema.TypeBool, + Computed: true, + Description: "Images with this operating system can only be used on dedicated hosts or dedicated host groups", + }, + "display_name": { + Type: schema.TypeString, + Computed: true, + Description: "A unique, display-friendly name for the operating system", + }, + "family": { + Type: schema.TypeString, + Computed: true, + Description: "The software family for this operating system", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL for this operating system", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this operating system", + }, + "vendor": { + Type: schema.TypeString, + Computed: true, + Description: "The vendor of the operating system", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "The major release version of this operating system", + }, + }, + }, + }, "os": { Type: schema.TypeString, Computed: true, @@ -207,6 +301,9 @@ func imageGetByName(d *schema.ResourceData, meta interface{}, name, visibility s if *image.Status == "deprecated" { fmt.Printf("[WARN] Given image %s is deprecated and soon will be obsolete.", name) } + if len(image.StatusReasons) > 0 { + d.Set("status_reasons", dataSourceIBMIsImageFlattenStatusReasons(image.StatusReasons)) + } d.Set("name", *image.Name) accesstags, err := flex.GetGlobalTagsUsingCRN(meta, *image.CRN, "", isImageAccessTagType) if err != nil { @@ -215,6 +312,19 @@ func imageGetByName(d *schema.ResourceData, meta interface{}, name, visibility s } d.Set(isImageAccessTags, accesstags) d.Set("visibility", *image.Visibility) + + if image.OperatingSystem != nil { + operatingSystemList := []map[string]interface{}{} + operatingSystemMap := dataSourceIBMISImageOperatingSystemToMap(*image.OperatingSystem) + operatingSystemList = append(operatingSystemList, operatingSystemMap) + d.Set("operating_system", operatingSystemList) + } + if image.ResourceGroup != nil { + resourceGroupList := []map[string]interface{}{} + resourceGroupMap := dataSourceImageResourceGroupToMap(*image.ResourceGroup) + resourceGroupList = append(resourceGroupList, resourceGroupMap) + d.Set("resource_group", resourceGroupList) + } d.Set("os", *image.OperatingSystem.Name) d.Set("architecture", *image.OperatingSystem.Architecture) d.Set("crn", *image.CRN) @@ -271,8 +381,23 @@ func imageGetById(d *schema.ResourceData, meta interface{}, identifier string) e if *image.Status == "deprecated" { fmt.Printf("[WARN] Given image %s is deprecated and soon will be obsolete.", name) } + if len(image.StatusReasons) > 0 { + d.Set("status_reasons", dataSourceIBMIsImageFlattenStatusReasons(image.StatusReasons)) + } d.Set("name", *image.Name) d.Set("visibility", *image.Visibility) + if image.OperatingSystem != nil { + operatingSystemList := []map[string]interface{}{} + operatingSystemMap := dataSourceIBMISImageOperatingSystemToMap(*image.OperatingSystem) + operatingSystemList = append(operatingSystemList, operatingSystemMap) + d.Set("operating_system", operatingSystemList) + } + if image.ResourceGroup != nil { + resourceGroupList := []map[string]interface{}{} + resourceGroupMap := dataSourceImageResourceGroupToMap(*image.ResourceGroup) + resourceGroupList = append(resourceGroupList, resourceGroupMap) + d.Set("resource_group", resourceGroupList) + } d.Set("os", *image.OperatingSystem.Name) d.Set("architecture", *image.OperatingSystem.Architecture) d.Set("crn", *image.CRN) @@ -297,6 +422,36 @@ func imageGetById(d *schema.ResourceData, meta interface{}, identifier string) e return nil } +func dataSourceIBMISImageOperatingSystemToMap(operatingSystemItem vpcv1.OperatingSystem) (operatingSystemMap map[string]interface{}) { + operatingSystemMap = map[string]interface{}{} + + if operatingSystemItem.Architecture != nil { + operatingSystemMap["architecture"] = operatingSystemItem.Architecture + } + if operatingSystemItem.DedicatedHostOnly != nil { + operatingSystemMap["dedicated_host_only"] = operatingSystemItem.DedicatedHostOnly + } + if operatingSystemItem.DisplayName != nil { + operatingSystemMap["display_name"] = operatingSystemItem.DisplayName + } + if operatingSystemItem.Family != nil { + operatingSystemMap["family"] = operatingSystemItem.Family + } + if operatingSystemItem.Href != nil { + operatingSystemMap["href"] = operatingSystemItem.Href + } + if operatingSystemItem.Name != nil { + operatingSystemMap["name"] = operatingSystemItem.Name + } + if operatingSystemItem.Vendor != nil { + operatingSystemMap["vendor"] = operatingSystemItem.Vendor + } + if operatingSystemItem.Version != nil { + operatingSystemMap["version"] = operatingSystemItem.Version + } + return operatingSystemMap +} + func dataSourceImageCollectionCatalogOfferingToMap(imageCatalogOfferingItem vpcv1.ImageCatalogOffering) (imageCatalogOfferingMap map[string]interface{}) { imageCatalogOfferingMap = map[string]interface{}{} if imageCatalogOfferingItem.Managed != nil { @@ -320,3 +475,40 @@ func dataSourceImageCollectionCatalogOfferingToMap(imageCatalogOfferingItem vpcv return imageCatalogOfferingMap } + +func dataSourceIBMIsImageFlattenStatusReasons(result []vpcv1.ImageStatusReason) (statusReasons []map[string]interface{}) { + for _, statusReasonsItem := range result { + statusReasons = append(statusReasons, dataSourceIBMIsImageStatusReasonToMap(&statusReasonsItem)) + } + + return statusReasons +} + +func dataSourceIBMIsImageStatusReasonToMap(model *vpcv1.ImageStatusReason) map[string]interface{} { + modelMap := make(map[string]interface{}) + if model.Code != nil { + modelMap["code"] = *model.Code + } + if model.Message != nil { + modelMap["message"] = *model.Message + } + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap +} +func dataSourceImageResourceGroupToMap(resourceGroupItem vpcv1.ResourceGroupReference) (resourceGroupMap map[string]interface{}) { + resourceGroupMap = map[string]interface{}{} + + if resourceGroupItem.Href != nil { + resourceGroupMap["href"] = resourceGroupItem.Href + } + if resourceGroupItem.ID != nil { + resourceGroupMap["id"] = resourceGroupItem.ID + } + if resourceGroupItem.Name != nil { + resourceGroupMap["name"] = resourceGroupItem.Name + } + + return resourceGroupMap +} diff --git a/ibm/service/vpc/data_source_ibm_is_image_test.go b/ibm/service/vpc/data_source_ibm_is_image_test.go index 9c7c126b5e..425a160dc5 100644 --- a/ibm/service/vpc/data_source_ibm_is_image_test.go +++ b/ibm/service/vpc/data_source_ibm_is_image_test.go @@ -34,6 +34,33 @@ func TestAccIBMISImageDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISImageDataSource_All(t *testing.T) { + resName := "data.ibm_is_image.test1" + imageName := fmt.Sprintf("tfimage-name-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISImageDataSourceAllConfig(imageName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "operating_system.0.name"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.dedicated_host_only"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.display_name"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.family"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.href"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.vendor"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.version"), + resource.TestCheckResourceAttrSet(resName, "operating_system.0.architecture"), + resource.TestCheckResourceAttrSet(resName, "status"), + resource.TestCheckResourceAttrSet(resName, "resource_group.0.id"), + resource.TestCheckResourceAttrSet(resName, "resource_group.0.name"), + ), + }, + }, + }) +} func TestAccIBMISImageDataSource_ilc(t *testing.T) { resName := "data.ibm_is_image.test1" imageName := fmt.Sprintf("tfimage-name-%d", acctest.RandIntRange(10, 100)) @@ -144,6 +171,16 @@ func testAccCheckIBMISImageDataSourceConfig(imageName string) string { }`, acc.Image_cos_url, imageName, acc.Image_operating_system) } +func testAccCheckIBMISImageDataSourceAllConfig(imageName string) string { + return fmt.Sprintf(` + data "ibm_is_images" "test1" { + status = "available" + } + data "ibm_is_image" "test1" { + name = data.ibm_is_images.test1.images.0.name + }`) +} + func testAccCheckIBMISImageDataSourceConfigIlc(imageName string) string { return fmt.Sprintf(` resource "ibm_is_image" "isExampleImage" { diff --git a/ibm/service/vpc/data_source_ibm_is_images.go b/ibm/service/vpc/data_source_ibm_is_images.go index e1d22caf44..bd9c059110 100644 --- a/ibm/service/vpc/data_source_ibm_is_images.go +++ b/ibm/service/vpc/data_source_ibm_is_images.go @@ -74,11 +74,83 @@ func DataSourceIBMISImages() *schema.Resource { Computed: true, Description: "The status of this image", }, + "status_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current status (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A snake case string succinctly identifying the status reason.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the status reason.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about this status reason.", + }, + }, + }, + }, "visibility": { Type: schema.TypeString, Computed: true, Description: "Whether the image is publicly visible or private to the account", }, + "operating_system": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "architecture": { + Type: schema.TypeString, + Computed: true, + Description: "The operating system architecture", + }, + "dedicated_host_only": { + Type: schema.TypeBool, + Computed: true, + Description: "Images with this operating system can only be used on dedicated hosts or dedicated host groups", + }, + "display_name": { + Type: schema.TypeString, + Computed: true, + Description: "A unique, display-friendly name for the operating system", + }, + "family": { + Type: schema.TypeString, + Computed: true, + Description: "The software family for this operating system", + }, + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL for this operating system", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this operating system", + }, + "vendor": { + Type: schema.TypeString, + Computed: true, + Description: "The vendor of the operating system", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "The major release version of this operating system", + }, + }, + }, + }, "os": { Type: schema.TypeString, Computed: true, @@ -89,6 +161,30 @@ func DataSourceIBMISImages() *schema.Resource { Computed: true, Description: "The operating system architecture", }, + "resource_group": { + Type: schema.TypeList, + Computed: true, + Description: "The resource group for this IPsec policy.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": { + Type: schema.TypeString, + Computed: true, + Description: "The URL for this resource group.", + }, + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this resource group.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The user-defined name for this resource group.", + }, + }, + }, + }, "crn": { Type: schema.TypeString, Computed: true, @@ -283,6 +379,21 @@ func imageList(d *schema.ResourceData, meta interface{}) error { "os": *image.OperatingSystem.Name, "architecture": *image.OperatingSystem.Architecture, } + if len(image.StatusReasons) > 0 { + l["status_reasons"] = dataSourceIBMIsImageFlattenStatusReasons(image.StatusReasons) + } + if image.ResourceGroup != nil { + resourceGroupList := []map[string]interface{}{} + resourceGroupMap := dataSourceImageResourceGroupToMap(*image.ResourceGroup) + resourceGroupList = append(resourceGroupList, resourceGroupMap) + l["resource_group"] = resourceGroupList + } + if image.OperatingSystem != nil { + operatingSystemList := []map[string]interface{}{} + operatingSystemMap := dataSourceIBMISImageOperatingSystemToMap(*image.OperatingSystem) + operatingSystemList = append(operatingSystemList, operatingSystemMap) + l["operating_system"] = operatingSystemList + } if image.File != nil && image.File.Checksums != nil { l[isImageCheckSum] = *image.File.Checksums.Sha256 } diff --git a/ibm/service/vpc/data_source_ibm_is_images_test.go b/ibm/service/vpc/data_source_ibm_is_images_test.go index 2bbbbda009..08c30998de 100644 --- a/ibm/service/vpc/data_source_ibm_is_images_test.go +++ b/ibm/service/vpc/data_source_ibm_is_images_test.go @@ -9,6 +9,7 @@ import ( acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) @@ -30,6 +31,33 @@ func TestAccIBMISImagesDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISImagesDataSource_All(t *testing.T) { + resName := "data.ibm_is_images.test1" + imageName := fmt.Sprintf("tfimage-name-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISImagesDataSourceAllConfig(imageName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.name"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.dedicated_host_only"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.display_name"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.family"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.href"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.vendor"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.version"), + resource.TestCheckResourceAttrSet(resName, "images.0.operating_system.0.architecture"), + resource.TestCheckResourceAttrSet(resName, "images.0.status"), + resource.TestCheckResourceAttrSet(resName, "images.0.resource_group.0.id"), + resource.TestCheckResourceAttrSet(resName, "images.0.resource_group.0.name"), + ), + }, + }, + }) +} func TestAccIBMISImagesDataSource_catalog(t *testing.T) { resName := "data.ibm_is_images.test1" @@ -92,6 +120,12 @@ func testAccCheckIBMISImagesDataSourceConfig() string { data "ibm_is_images" "test1" { }`) } +func testAccCheckIBMISImagesDataSourceAllConfig(imageName string) string { + return fmt.Sprintf(` + data "ibm_is_images" "test1" { + status = "available" + }`) +} func testAccCheckIBMISCatalogImagesDataSourceConfig() string { // status filter defaults to empty return fmt.Sprintf(` diff --git a/website/docs/d/is_image.html.markdown b/website/docs/d/is_image.html.markdown index 4b7f19ebd2..994d2f510e 100644 --- a/website/docs/d/is_image.html.markdown +++ b/website/docs/d/is_image.html.markdown @@ -69,5 +69,29 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The unique identifier of the image. - `obsolescence_at` - (String) The obsolescence date and time (UTC) for this image. If absent, no obsolescence date and time has been set. - `os` - (String) The name of the operating system. +- `operating_system` - (List) The operating system details. + + Nested scheme for `operating_system`: + - `architecture` - (String) The operating system architecture. + - `dedicated_host_only` - (Bool) Images with this operating system can only be used on dedicated hosts or dedicated host groups. + - `display_name` - (String) A unique, display-friendly name for the operating system. + - `family` - (String) The software family for this operating system. + - `href` - (String) The URL for this operating system. + - `name` - (String) The globally unique name for this operating system. + - `vendor` - (String) The vendor of the operating system. + - `version` - (String) The major release version of this operating system. +- `resource_group` - (List) The resource group object, for this image. + + Nested scheme for `resource_group`: + - `href` - (String) The URL for this resource group. + - `id` - (String) The unique identifier for this resource group. + - `name` - (String) The user-defined name for this resource group. - `status` - (String) The status of this image. +- `status_reasons` - (List) The reasons for the current status (if any). + + Nested scheme for `status_reasons`: + - `code` - (String) The status reason code + - `message` - (String) An explanation of the status reason + - `more_info` - (String) Link to documentation about this status reason + - `source_volume` - The source volume id of the image. diff --git a/website/docs/d/is_images.html.markdown b/website/docs/d/is_images.html.markdown index d5a63840af..012e1beb74 100644 --- a/website/docs/d/is_images.html.markdown +++ b/website/docs/d/is_images.html.markdown @@ -65,7 +65,29 @@ You can access the following attribute references after your data source is crea - `id` - (String) The unique identifier for this image. - `name` - (String) The name for this image. - `os` - (String) The name of the Operating System. + - `operating_system` - (List) The operating system details. + + Nested scheme for `operating_system`: + - `architecture` - (String) The operating system architecture. + - `dedicated_host_only` - (Bool) Images with this operating system can only be used on dedicated hosts or dedicated host groups. + - `display_name` - (String) A unique, display-friendly name for the operating system. + - `family` - (String) The software family for this operating system. + - `href` - (String) The URL for this operating system. + - `name` - (String) The globally unique name for this operating system. + - `vendor` - (String) The vendor of the operating system. + - `version` - (String) The major release version of this operating system. + - `resource_group` - (List) The resource group object, for this image. + Nested scheme for `resource_group`: + - `href` - (String) The URL for this resource group. + - `id` - (String) The unique identifier for this resource group. + - `name` - (String) The user-defined name for this resource group. - `status` - (String) The status of this image. + - `status_reasons` - (List) The reasons for the current status (if any). + + Nested scheme for `status_reasons`: + - `code` - (String) The status reason code + - `message` - (String) An explanation of the status reason + - `more_info` - (String) Link to documentation about this status reason - `visibility` - (String) The visibility of the image public or private. - `source_volume` - The source volume id of the image.