From 0a81c97ab9f6a6e13e46c0ab1f111d0cded149cd Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Thu, 5 Dec 2024 03:53:15 +0530 Subject: [PATCH 1/3] added primary_ip refernce to nac for consistency --- ibm/service/vpc/resource_ibm_is_instance.go | 121 +++++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index bf50974825..95ec9eb880 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -832,6 +832,55 @@ func ResourceIBMISInstance() *schema.Resource { Computed: true, Description: "The resource type.", }, + // primary_ip for consistency + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP address of the virtual network interface for the network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address has not yet been selected, the value will be `0.0.0.0`.This property may add support for IPv6 addresses in the future. When processing a value in this property, verify that the address is in an expected format. If it is not, log an error. Optionally halt processing and surface the error, or bypass the resource on which the unexpected IP address format was encountered.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this reserved IP. The name is unique across all reserved IPs in a subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "id": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -1196,7 +1245,55 @@ func ResourceIBMISInstance() *schema.Resource { }, }, }, - + // primary_ip for consistency + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP address of the virtual network interface for the network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address has not yet been selected, the value will be `0.0.0.0`.This property may add support for IPv6 addresses in the future. When processing a value in this property, verify that the address is in an expected format. If it is not, log an error. Optionally halt processing and surface the error, or bypass the resource on which the unexpected IP address format was encountered.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about deleted resources.", + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this reserved IP. The name is unique across all reserved IPs in a subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "virtual_network_interface": &schema.Schema{ Type: schema.TypeList, MaxItems: 1, @@ -7249,6 +7346,10 @@ func resourceIBMIsInstanceInstanceNetworkAttachmentReferenceToMap(model *vpcv1.I vniMap["name"] = pna.VirtualNetworkInterface.Name vniMap["resource_type"] = pna.VirtualNetworkInterface.ResourceType } + if model.PrimaryIP != nil { + primaryipmap, _ := resourceIBMIsInstancePrimaryIPReferenceToMap(model.PrimaryIP) + modelMap["primary_ip"] = []map[string]interface{}{primaryipmap} + } getVirtualNetworkInterfaceOptions := &vpcv1.GetVirtualNetworkInterfaceOptions{ ID: pna.VirtualNetworkInterface.ID, } @@ -7325,6 +7426,24 @@ func resourceIBMIsInstanceReservedIPReferenceToMap(model *vpcv1.ReservedIPRefere } return modelMap, nil } +func resourceIBMIsInstancePrimaryIPReferenceToMap(model *vpcv1.ReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = model.Address + if model.Deleted != nil { + deletedMap, err := resourceIBMIsInstanceReservedIPReferenceDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + modelMap["href"] = model.Href + modelMap["id"] = model.ID + modelMap["name"] = model.Name + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil +} func resourceIBMIsInstanceReservedIPReferenceDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { modelMap := make(map[string]interface{}) From e965978d247b3c82bffbfb0cbbc879117f46dd37 Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Thu, 5 Dec 2024 10:38:59 +0530 Subject: [PATCH 2/3] Added the documents for primary_ip addition --- ibm/service/vpc/resource_ibm_is_instance.go | 2 +- website/docs/r/is_instance.html.markdown | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index 95ec9eb880..f8deb37e2b 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -7440,7 +7440,7 @@ func resourceIBMIsInstancePrimaryIPReferenceToMap(model *vpcv1.ReservedIPReferen modelMap["id"] = model.ID modelMap["name"] = model.Name if model.ResourceType != nil { - modelMap["resource_type"] = *model.ResourceType + modelMap["resource_type"] = model.ResourceType } return modelMap, nil } diff --git a/website/docs/r/is_instance.html.markdown b/website/docs/r/is_instance.html.markdown index e2398ebcb9..7622484510 100644 --- a/website/docs/r/is_instance.html.markdown +++ b/website/docs/r/is_instance.html.markdown @@ -917,6 +917,16 @@ In addition to all argument reference list, you can access the following attribu - `id` - (String) The ID of the instance. - `memory`- (Integer) The amount of memory that is allocated to the instance in gigabytes. - `numa_count` - (Integer) The number of NUMA nodes this instance is provisioned on. This property may be absent if the instance's status is not running. +- `network_attachments` - (List) The network attachments list for this virtual server instance. + Nested schema for **network_attachments**: + + - `primary_ip` - (List) The primary IP address to bind to the network interface. This can be specified using an existing reserved IP, or a prototype object for a new reserved IP. + + Nested scheme for `primary_ip`: + - `auto_delete` - (Bool) Indicates whether this reserved IP member will be automatically deleted when either target is deleted, or the reserved IP is unbound. + - `address` - (String) The IP address of the reserved IP. + - `name`- (String) The user-defined or system-provided name for this reserved IP + - `id`- (String) The unique identifier for this reserved IP. - `network_interfaces`- (List of Strings) A list of more network interfaces that are attached to the instance. Nested scheme for `network_interfaces`: @@ -933,6 +943,16 @@ In addition to all argument reference list, you can access the following attribu - `name`- (String) The user-defined or system-provided name for this reserved IP - `reserved_ip`- (String) The unique identifier for this reserved IP - `primary_ipv4_address` - (String, Deprecated) The primary IPv4 address. Same as `primary_ip.[0].address` +- `primary_network_attachment` - (List) The primary network attachment for this virtual server instance. + Nested schema for **primary_network_attachment**: + + - `primary_ip` - (List) The primary IP address to bind to the network interface. This can be specified using an existing reserved IP, or a prototype object for a new reserved IP. + + Nested scheme for `primary_ip`: + - `auto_delete` - (Bool) Indicates whether this reserved IP member will be automatically deleted when either target is deleted, or the reserved IP is unbound. + - `address` - (String) The IP address of the reserved IP. + - `name`- (String) The user-defined or system-provided name for this reserved IP + - `id`- (String) The unique identifier for this reserved IP. - `primary_network_interface`- (List of Strings) A list of primary network interfaces that are attached to the instance. Nested scheme for `primary_network_interface`: From 1fa20453b0be7860a1ee09308fbcad9283c92451 Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Thu, 5 Dec 2024 10:59:47 +0530 Subject: [PATCH 3/3] Added test cases --- ibm/acctest/acctest.go | 4 +- .../vpc/resource_ibm_is_instance_test.go | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/ibm/acctest/acctest.go b/ibm/acctest/acctest.go index dbcc0de99e..c851227cfb 100644 --- a/ibm/acctest/acctest.go +++ b/ibm/acctest/acctest.go @@ -841,8 +841,8 @@ func init() { IsImage = os.Getenv("IS_IMAGE") if IsImage == "" { // IsImage = "fc538f61-7dd6-4408-978c-c6b85b69fe76" // for classic infrastructure - IsImage = "r006-907911a7-0ffe-467e-8821-3cc9a0d82a39" // for next gen infrastructure ibm-centos-7-9-minimal-amd64-10 image - fmt.Println("[INFO] Set the environment variable IS_IMAGE for testing ibm_is_instance, ibm_is_floating_ip else it is set to default value 'r006-907911a7-0ffe-467e-8821-3cc9a0d82a39'") + IsImage = "r006-587a041d-9246-44f0-980b-56a327cf5bd7" // for next gen infrastructure ibm-ubuntu-24-04-6-minimal-amd64-1 us-south + fmt.Println("[INFO] Set the environment variable IS_IMAGE for testing ibm_is_instance, ibm_is_floating_ip else it is set to default value 'r006-587a041d-9246-44f0-980b-56a327cf5bd7'") } IsImage2 = os.Getenv("IS_IMAGE2") diff --git a/ibm/service/vpc/resource_ibm_is_instance_test.go b/ibm/service/vpc/resource_ibm_is_instance_test.go index 0d84a35495..a4c16d00f4 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_test.go @@ -3565,3 +3565,94 @@ func testAccCheckIBMISInstanceClusterNetworkAttachmentConfig(vpcname, clustersub } `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename, subnetName, acc.ISZoneName, sshKeyName, publicKey, instanceName, acc.IsImage, acc.ISInstanceGPUProfileName) } + +func TestAccIBMISInstance_primary_ip_consistency(t *testing.T) { + var instance string + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf-instnace-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tf-subnet-%d", acctest.RandIntRange(10, 100)) + publicKey := strings.TrimSpace(` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR +`) + sshname := fmt.Sprintf("tf-ssh-%d", acctest.RandIntRange(10, 100)) + userData1 := "a" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstancePrimaryIpConsistencyConfig(vpcname, subnetname, sshname, publicKey, name, userData1), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "user_data", userData1), + resource.TestCheckResourceAttr( + "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "vcpu.0.manufacturer"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "primary_network_attachment.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "primary_network_attachment.0.primary_ip.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "primary_network_attachment.0.primary_ip.0.address"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "network_attachments.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "network_attachments.0.primary_ip.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "network_attachments.0.primary_ip.0.address"), + ), + }, + }, + }) +} + +func testAccCheckIBMISInstancePrimaryIpConsistencyConfig(vpcname, subnetname, sshname, publicKey, name, userData string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "testacc_vpc" { + name = "%s" + } + + resource "ibm_is_subnet" "testacc_subnet" { + name = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + ipv4_cidr_block = "%s" + } + + resource "ibm_is_ssh_key" "testacc_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_instance" "testacc_instance" { + name = "%s" + image = "%s" + profile = "%s" + primary_network_attachment { + name = "example-primarynetwork-att" + virtual_network_interface { + auto_delete = true + subnet = ibm_is_subnet.testacc_subnet.id + } + } + user_data = "%s" + vpc = ibm_is_vpc.testacc_vpc.id + zone = "%s" + keys = [ibm_is_ssh_key.testacc_sshkey.id] + network_attachments { + name = "example-network-att" + virtual_network_interface { + auto_delete = true + subnet = ibm_is_subnet.testacc_subnet.id + } + } + }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, publicKey, name, acc.IsImage, acc.InstanceProfileName, userData, acc.ISZoneName) +}