diff --git a/examples/ibm-is-ng/main.tf b/examples/ibm-is-ng/main.tf index 4c34a38551..9c61f78672 100644 --- a/examples/ibm-is-ng/main.tf +++ b/examples/ibm-is-ng/main.tf @@ -1626,3 +1626,433 @@ data "ibm_is_reservations" "example" { data "ibm_is_reservation" "example" { identifier = ibm_is_reservation.example.id } + +// cluster examples +# ============================================================================================================= +variable prefix { + default = "test-cluster" +} +variable is_instances_resource_group_id { + default = "efhiorho4388yf348y83yvchrc083h0r30c" +} +variable region { + default = "us-east" +} +variable is_instances_name { + default = "test-vsi" +} +data "ibm_is_cluster_network_profile" "is_cluster_network_profile_instance" { + name = "h100" +} +data "ibm_is_cluster_network_profiles" "is_cluster_network_profiles_instance" { +} +# Create VPC +resource "ibm_is_vpc" "is_vpc" { + name = "${var.prefix}-vpc" +} +resource "ibm_is_vpc" "is_vpc2" { + name = "${var.prefix}-vpc2" +} + +# # # Create Subnet +resource "ibm_is_subnet" "is_subnet" { + name = "${var.prefix}-subnet" + vpc = ibm_is_vpc.is_vpc.id + total_ipv4_address_count = 64 + zone = "${var.region}-3" +} + +data ibm_is_instance_profile is_instance_profile_instance{ + name = "gx3d-160x1792x8h100" +} +data ibm_is_instance_profiles is_instance_profiles_instance{ +} +data "ibm_is_image" "is_image" { + name = "ibm-ubuntu-20-04-6-minimal-amd64-6" +} +resource "ibm_is_cluster_network" "is_cluster_network_instance" { + name = "${var.prefix}-cluster" + profile = "h100" + resource_group = var.is_instances_resource_group_id + subnet_prefixes { + cidr = "10.1.0.0/24" + } + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "${var.region}-3" +} +resource "ibm_is_cluster_network" "is_cluster_network_instance" { + name = "${var.prefix}-cluster-updated" + profile = "h100" + subnet_prefixes { + cidr = "10.0.0.0/24" + } + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = ibm_is_subnet.is_subnet.zone +} +resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "${var.prefix}-cluster-subnet" + total_ipv4_address_count = 64 +} + +resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + address = "10.1.0.4" + name = "${var.prefix}-cluster-subnet-r-ip" +} + +resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "${var.prefix}-cluster-ni" + primary_ip { + id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + } + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } +} + +resource "ibm_is_instance_template" "is_instance_template" { + name = "${var.prefix}-cluster-it" + image = data.ibm_is_image.is_image.id + profile = "gx3d-160x1792x8h100" + primary_network_attachment { + name = "my-pna-it" + virtual_network_interface { + auto_delete = true + subnet = ibm_is_subnet.is_subnet.id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + vpc = ibm_is_vpc.is_vpc.id + zone = ibm_is_subnet.is_subnet.zone + keys = [ibm_is_ssh_key.is_key.id] +} +resource "ibm_is_ssh_key" "is_key" { + name = "my-key" + public_key = file("~/.ssh/id_ed25519.pub") + type = "ed25519" +} + +resource "ibm_is_instance" "is_instance" { + name = "${var.prefix}-cluster-ins" + image = data.ibm_is_image.is_image.id + profile = "gx3d-160x1792x8h100" + primary_network_interface { + subnet = ibm_is_subnet.is_subnet.id + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-1" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-2" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-3" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-4" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-5" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-6" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-7" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-8" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + vpc = ibm_is_vpc.is_vpc.id + zone = ibm_is_subnet.is_subnet.zone + keys = [ibm_is_ssh_key.is_key.id] +} + +resource "ibm_is_instance_action" "is_instance_stop_before" { + action = "stop" + instance = ibm_is_instance.is_instance.id +} + +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance.is_instance.cluster_network_attachments.0.id + } + cluster_network_interface { + name = "my-cluster-network-interface" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-9" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance10" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface-10" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-10" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance11" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance10.instance_cluster_network_attachment_id +} + cluster_network_interface { + name = "my-cluster-network-interface-11" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-11" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance12" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance11.instance_cluster_network_attachment_id +} + cluster_network_interface { + name = "my-cluster-network-interface12" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-12" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance13" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance12.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface13" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-13" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance14" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance13.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface14" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-149" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance15" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance14.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface15" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-15" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance16" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance15.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface16" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-16" +} +resource "ibm_is_instance_action" "is_instance_start_after" { + # depends_on = [ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance16] + action = "start" + instance = ibm_is_instance.is_instance.id +} +resource "ibm_is_instance_action" "is_instance_stop_update" { + # depends_on = [ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance16] + action = "stop" + instance = ibm_is_instance.is_instance.id +} + +data "ibm_is_cluster_network" "is_cluster_network_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} +data "ibm_is_cluster_networks" "is_cluster_networks_instance" { +} + +data "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_interface_id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id +} +data "ibm_is_cluster_network_interfaces" "is_cluster_network_interfaces_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} + +data "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id +} +data "ibm_is_cluster_network_subnets" "is_cluster_network_subnets_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} +data "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id =ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + cluster_network_subnet_reserved_ip_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + +} +data "ibm_is_cluster_network_subnet_reserved_ips" "is_cluster_network_subnet_reserved_ips_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id +} + +data "ibm_is_instance_template" "is_instance_template_instance" { + name = ibm_is_instance_template.is_instance_template.name +} +data "ibm_is_instance" "is_instance_instance" { + name = ibm_is_instance.is_instance.name +} +data "ibm_is_instances" "is_instances_instance" { +} +data "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = ibm_is_instance.is_instance.id + instance_cluster_network_attachment_id = ibm_is_instance.is_instance.cluster_network_attachments.0.id +} +data "ibm_is_instance_cluster_network_attachments" "is_instance_cluster_network_attachments_instance" { + instance_id = ibm_is_instance.is_instance.id +} +data "ibm_is_instances" "is_instances_instance" { + # resource_group_id = var.is_instances_resource_group_id + name = var.is_instances_name + # cluster_network_id = var.is_instances_cluster_network_id + # cluster_network_crn = var.is_instances_cluster_network_crn + # cluster_network_name = var.is_instances_cluster_network_name + # dedicated_host_id = var.is_instances_dedicated_host_id + # dedicated_host_crn = var.is_instances_dedicated_host_crn + # dedicated_host_name = var.is_instances_dedicated_host_name + # placement_group_id = var.is_instances_placement_group_id + # placement_group_crn = var.is_instances_placement_group_crn + # placement_group_name = var.is_instances_placement_group_name + # reservation_id = var.is_instances_reservation_id + # reservation_crn = var.is_instances_reservation_crn + # reservation_name = var.is_instances_reservation_name + # vpc_id = var.is_instances_vpc_id + # vpc_crn = var.is_instances_vpc_crn + # vpc_name = var.is_instances_vpc_name +} \ No newline at end of file diff --git a/ibm/acctest/acctest.go b/ibm/acctest/acctest.go index d78f6ea5f8..f485d9eece 100644 --- a/ibm/acctest/acctest.go +++ b/ibm/acctest/acctest.go @@ -23,111 +23,114 @@ const ( ) var ( - AccountId string - AppIDTenantID string - AppIDTestUserEmail string - BackupPolicyJobID string - BackupPolicyID string - CfOrganization string - CfSpace string - CisDomainStatic string - CisDomainTest string - CisInstance string - CisResourceGroup string - CloudShellAccountID string - CosCRN string - BucketCRN string - ActivityTrackerInstanceCRN string - MetricsMonitoringCRN string - BucketName string - CosName string - Ibmid1 string - Ibmid2 string - IAMUser string - IAMAccountId string - IAMServiceId string - IAMTrustedProfileID string - Datacenter string - MachineType string - trustedMachineType string - PublicVlanID string - PrivateVlanID string - PrivateSubnetID string - PublicSubnetID string - SubnetID string - LbaasDatacenter string - LbaasSubnetId string - LbListerenerCertificateInstance string - IpsecDatacenter string - Customersubnetid string - Customerpeerip string - DedicatedHostName string - DedicatedHostID string - KubeVersion string - KubeUpdateVersion string - Zone string - ZonePrivateVlan string - ZonePublicVlan string - ZoneUpdatePrivateVlan string - ZoneUpdatePublicVlan string - WorkerPoolSecondaryStorage string - CsRegion string - ExtendedHardwareTesting bool - err error - placementGroupName string - CertCRN string - UpdatedCertCRN string - SecretCRN string - SecretCRN2 string - EnterpriseCRN string - InstanceCRN string - SecretGroupID string - RegionName string - ISZoneName string - ISZoneName2 string - ISZoneName3 string - IsResourceGroupID string - ISResourceCrn string - ISCIDR string - ISCIDR2 string - ISPublicSSHKeyFilePath string - ISPrivateSSHKeyFilePath string - ISAddressPrefixCIDR string - InstanceName string - InstanceProfileName string - InstanceProfileNameUpdate string - IsBareMetalServerProfileName string - IsBareMetalServerImage string - IsBareMetalServerImage2 string - DNSInstanceCRN string - DNSZoneID string - DNSInstanceCRN1 string - DNSZoneID1 string - DedicatedHostProfileName string - DedicatedHostGroupID string - InstanceDiskProfileName string - DedicatedHostGroupFamily string - DedicatedHostGroupClass string - ShareProfileName string - SourceShareCRN string - ShareEncryptionKey string - VNIId string - FloatingIpID string - VolumeProfileName string - VSIUnattachedBootVolumeID string - VSIDataVolumeID string - ISRouteDestination string - ISRouteNextHop string - ISSnapshotCRN string - WorkspaceID string - TemplateID string - ActionID string - JobID string - RepoURL string - RepoBranch string - imageName string - functionNamespace string - HpcsInstanceID string + AccountId string + AppIDTenantID string + AppIDTestUserEmail string + BackupPolicyJobID string + BackupPolicyID string + CfOrganization string + CfSpace string + CisDomainStatic string + CisDomainTest string + CisInstance string + CisResourceGroup string + CloudShellAccountID string + CosCRN string + BucketCRN string + ActivityTrackerInstanceCRN string + MetricsMonitoringCRN string + BucketName string + CosName string + Ibmid1 string + Ibmid2 string + IAMUser string + IAMAccountId string + IAMServiceId string + IAMTrustedProfileID string + Datacenter string + MachineType string + trustedMachineType string + PublicVlanID string + PrivateVlanID string + PrivateSubnetID string + PublicSubnetID string + SubnetID string + LbaasDatacenter string + LbaasSubnetId string + LbListerenerCertificateInstance string + IpsecDatacenter string + Customersubnetid string + Customerpeerip string + DedicatedHostName string + DedicatedHostID string + KubeVersion string + KubeUpdateVersion string + Zone string + ZonePrivateVlan string + ZonePublicVlan string + ZoneUpdatePrivateVlan string + ZoneUpdatePublicVlan string + WorkerPoolSecondaryStorage string + CsRegion string + ExtendedHardwareTesting bool + err error + placementGroupName string + CertCRN string + UpdatedCertCRN string + SecretCRN string + SecretCRN2 string + EnterpriseCRN string + InstanceCRN string + SecretGroupID string + RegionName string + ISZoneName string + ISZoneName2 string + ISZoneName3 string + IsResourceGroupID string + ISResourceCrn string + ISCIDR string + ISCIDR2 string + ISPublicSSHKeyFilePath string + ISPrivateSSHKeyFilePath string + ISAddressPrefixCIDR string + ISClusterNetworkProfileName string + ISInstanceGPUProfileName string + ISClusterNetworkSubnetPrefixesCidr string + InstanceName string + InstanceProfileName string + InstanceProfileNameUpdate string + IsBareMetalServerProfileName string + IsBareMetalServerImage string + IsBareMetalServerImage2 string + DNSInstanceCRN string + DNSZoneID string + DNSInstanceCRN1 string + DNSZoneID1 string + DedicatedHostProfileName string + DedicatedHostGroupID string + InstanceDiskProfileName string + DedicatedHostGroupFamily string + DedicatedHostGroupClass string + ShareProfileName string + SourceShareCRN string + ShareEncryptionKey string + VNIId string + FloatingIpID string + VolumeProfileName string + VSIUnattachedBootVolumeID string + VSIDataVolumeID string + ISRouteDestination string + ISRouteNextHop string + ISSnapshotCRN string + WorkspaceID string + TemplateID string + ActionID string + JobID string + RepoURL string + RepoBranch string + imageName string + functionNamespace string + HpcsInstanceID string ) // MQ on Cloud @@ -771,6 +774,23 @@ func init() { fmt.Println("[INFO] Set the environment variable IS_ACCOUNT_ID for testing private_path_service_gateway_account_policy else it is set to default value 'fee82deba12e4c0fb69c3b09d1f12345'") } + ISClusterNetworkProfileName = os.Getenv("IS_CLUSTER_NETWORK_PROFILE_NAME") + if ISClusterNetworkProfileName == "" { + ISClusterNetworkProfileName = "h100" + fmt.Println("[INFO] Set the environment variable IS_CLUSTER_NETWORK_PROFILE_NAME for testing cluster_network_profile else it is set to default value 'h100'") + } + ISInstanceGPUProfileName = os.Getenv("IS_INSTANCE_GPU_PROFILE_NAME") + if ISInstanceGPUProfileName == "" { + ISInstanceGPUProfileName = "gx3d-160x1792x8h100" + fmt.Println("[INFO] Set the environment variable IS_INSTANCE_GPU_PROFILE_NAME for testing cluster_network_attachments else it is set to default value 'gx3d-160x1792x8h100'") + } + + ISClusterNetworkSubnetPrefixesCidr = os.Getenv("IS_CLUSTER_NETWORK_SUBNET_PREFIXES_CIDR") + if ISClusterNetworkSubnetPrefixesCidr == "" { + ISClusterNetworkSubnetPrefixesCidr = "10.1.0.0/24" + fmt.Println("[INFO] Set the environment variable IS_CLUSTER_NETWORK_SUBNET_PREFIXES_CIDR for testing cluster_network else it is set to default value '10.1.0.0/24'") + } + ISAddressPrefixCIDR = os.Getenv("SL_ADDRESS_PREFIX_CIDR") if ISAddressPrefixCIDR == "" { ISAddressPrefixCIDR = "10.120.0.0/24" diff --git a/ibm/provider/provider.go b/ibm/provider/provider.go index 7e30cd4daa..c5a7d40cfd 100644 --- a/ibm/provider/provider.go +++ b/ibm/provider/provider.go @@ -428,6 +428,20 @@ func Provider() *schema.Provider { "ibm_is_bare_metal_server": vpc.DataSourceIBMIsBareMetalServer(), "ibm_is_bare_metal_servers": vpc.DataSourceIBMIsBareMetalServers(), + // cluster + "ibm_is_cluster_network": vpc.DataSourceIBMIsClusterNetwork(), + "ibm_is_cluster_networks": vpc.DataSourceIBMIsClusterNetworks(), + "ibm_is_cluster_network_interface": vpc.DataSourceIBMIsClusterNetworkInterface(), + "ibm_is_cluster_network_interfaces": vpc.DataSourceIBMIsClusterNetworkInterfaces(), + "ibm_is_cluster_network_profile": vpc.DataSourceIBMIsClusterNetworkProfile(), + "ibm_is_cluster_network_profiles": vpc.DataSourceIBMIsClusterNetworkProfiles(), + "ibm_is_cluster_network_subnet": vpc.DataSourceIBMIsClusterNetworkSubnet(), + "ibm_is_cluster_network_subnets": vpc.DataSourceIBMIsClusterNetworkSubnets(), + "ibm_is_cluster_network_subnet_reserved_ip": vpc.DataSourceIBMIsClusterNetworkSubnetReservedIP(), + "ibm_is_cluster_network_subnet_reserved_ips": vpc.DataSourceIBMIsClusterNetworkSubnetReservedIps(), + "ibm_is_instance_cluster_network_attachment": vpc.DataSourceIBMIsInstanceClusterNetworkAttachment(), + "ibm_is_instance_cluster_network_attachments": vpc.DataSourceIBMIsInstanceClusterNetworkAttachments(), + "ibm_is_dedicated_host": vpc.DataSourceIbmIsDedicatedHost(), "ibm_is_dedicated_hosts": vpc.DataSourceIbmIsDedicatedHosts(), "ibm_is_dedicated_host_profile": vpc.DataSourceIbmIsDedicatedHostProfile(), @@ -1174,6 +1188,13 @@ func Provider() *schema.Provider { "ibm_is_backup_policy": vpc.ResourceIBMIsBackupPolicy(), "ibm_is_backup_policy_plan": vpc.ResourceIBMIsBackupPolicyPlan(), + // cluster + "ibm_is_cluster_network_interface": vpc.ResourceIBMIsClusterNetworkInterface(), + "ibm_is_cluster_network_subnet_reserved_ip": vpc.ResourceIBMIsClusterNetworkSubnetReservedIP(), + "ibm_is_cluster_network_subnet": vpc.ResourceIBMIsClusterNetworkSubnet(), + "ibm_is_cluster_network": vpc.ResourceIBMIsClusterNetwork(), + "ibm_is_instance_cluster_network_attachment": vpc.ResourceIBMIsInstanceClusterNetworkAttachment(), + // bare_metal_server "ibm_is_bare_metal_server_action": vpc.ResourceIBMIsBareMetalServerAction(), "ibm_is_bare_metal_server_disk": vpc.ResourceIBMIsBareMetalServerDisk(), @@ -1876,6 +1897,14 @@ func Validator() validate.ValidatorDict { "ibm_is_bare_metal_server_network_interface": vpc.ResourceIBMIsBareMetalServerNetworkInterfaceValidator(), "ibm_is_bare_metal_server": vpc.ResourceIBMIsBareMetalServerValidator(), + // cluster + + "ibm_is_cluster_network_interface": vpc.ResourceIBMIsClusterNetworkInterfaceValidator(), + "ibm_is_cluster_network_subnet": vpc.ResourceIBMIsClusterNetworkSubnetValidator(), + "ibm_is_cluster_network_subnet_reserved_ip": vpc.ResourceIBMIsClusterNetworkSubnetReservedIPValidator(), + "ibm_is_cluster_network": vpc.ResourceIBMIsClusterNetworkValidator(), + "ibm_is_instance_cluster_network_attachment": vpc.ResourceIBMIsInstanceClusterNetworkAttachmentValidator(), + "ibm_is_dedicated_host_group": vpc.ResourceIbmIsDedicatedHostGroupValidator(), "ibm_is_dedicated_host": vpc.ResourceIbmIsDedicatedHostValidator(), "ibm_is_dedicated_host_disk_management": vpc.ResourceIBMISDedicatedHostDiskManagementValidator(), diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network.go b/ibm/service/vpc/data_source_ibm_is_cluster_network.go new file mode 100644 index 0000000000..439ab3f664 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network.go @@ -0,0 +1,394 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetwork() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network was created.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "profile": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The profile for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "resource_group": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The resource group for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this resource group.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this resource group.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this resource group.", + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet_prefixes": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The IP address ranges available for subnets for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allocation_policy": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The allocation policy for this subnet prefix:- `auto`: Subnets created by total count in this cluster network can use this prefix.", + }, + "cidr": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CIDR block for this prefix.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The VPC this cluster network resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The zone this cluster network resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkOptions := &vpcv1.GetClusterNetworkOptions{} + + getClusterNetworkOptions.SetID(d.Get("cluster_network_id").(string)) + + clusterNetwork, _, err := vpcClient.GetClusterNetworkWithContext(context, getClusterNetworkOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkWithContext failed: %s", err.Error()), "(Data) ibm_is_cluster_network", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*getClusterNetworkOptions.ID) + + if err = d.Set("created_at", flex.DateTimeToString(clusterNetwork.CreatedAt)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting created_at: %s", err), "(Data) ibm_is_cluster_network", "read", "set-created_at").GetDiag() + } + + if err = d.Set("crn", clusterNetwork.CRN); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting crn: %s", err), "(Data) ibm_is_cluster_network", "read", "set-crn").GetDiag() + } + + if err = d.Set("href", clusterNetwork.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_cluster_network", "read", "set-href").GetDiag() + } + + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetwork.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_reasons: %s", err), "(Data) ibm_is_cluster_network", "read", "set-lifecycle_reasons").GetDiag() + } + + if err = d.Set("lifecycle_state", clusterNetwork.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_cluster_network", "read", "set-lifecycle_state").GetDiag() + } + + if err = d.Set("name", clusterNetwork.Name); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_is_cluster_network", "read", "set-name").GetDiag() + } + + profile := []map[string]interface{}{} + profileMap, err := DataSourceIBMIsClusterNetworkClusterNetworkProfileReferenceToMap(clusterNetwork.Profile) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "profile-to-map").GetDiag() + } + profile = append(profile, profileMap) + if err = d.Set("profile", profile); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting profile: %s", err), "(Data) ibm_is_cluster_network", "read", "set-profile").GetDiag() + } + + resourceGroup := []map[string]interface{}{} + resourceGroupMap, err := DataSourceIBMIsClusterNetworkResourceGroupReferenceToMap(clusterNetwork.ResourceGroup) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "resource_group-to-map").GetDiag() + } + resourceGroup = append(resourceGroup, resourceGroupMap) + if err = d.Set("resource_group", resourceGroup); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_group: %s", err), "(Data) ibm_is_cluster_network", "read", "set-resource_group").GetDiag() + } + + if err = d.Set("resource_type", clusterNetwork.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_cluster_network", "read", "set-resource_type").GetDiag() + } + + subnetPrefixes := []map[string]interface{}{} + for _, subnetPrefixesItem := range clusterNetwork.SubnetPrefixes { + subnetPrefixesItemMap, err := DataSourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(&subnetPrefixesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "subnet_prefixes-to-map").GetDiag() + } + subnetPrefixes = append(subnetPrefixes, subnetPrefixesItemMap) + } + if err = d.Set("subnet_prefixes", subnetPrefixes); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting subnet_prefixes: %s", err), "(Data) ibm_is_cluster_network", "read", "set-subnet_prefixes").GetDiag() + } + + vpc := []map[string]interface{}{} + vpcMap, err := DataSourceIBMIsClusterNetworkVPCReferenceToMap(clusterNetwork.VPC) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "vpc-to-map").GetDiag() + } + vpc = append(vpc, vpcMap) + if err = d.Set("vpc", vpc); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting vpc: %s", err), "(Data) ibm_is_cluster_network", "read", "set-vpc").GetDiag() + } + + zone := []map[string]interface{}{} + zoneMap, err := DataSourceIBMIsClusterNetworkZoneReferenceToMap(clusterNetwork.Zone) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network", "read", "zone-to-map").GetDiag() + } + zone = append(zone, zoneMap) + if err = d.Set("zone", zone); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting zone: %s", err), "(Data) ibm_is_cluster_network", "read", "set-zone").GetDiag() + } + + return nil +} + +func DataSourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(model *vpcv1.ClusterNetworkLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkClusterNetworkProfileReferenceToMap(model *vpcv1.ClusterNetworkProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkResourceGroupReferenceToMap(model *vpcv1.ResourceGroupReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(model *vpcv1.ClusterNetworkSubnetPrefix) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["allocation_policy"] = *model.AllocationPolicy + modelMap["cidr"] = *model.CIDR + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_interface.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_interface.go new file mode 100644 index 0000000000..95cfa51fcc --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_interface.go @@ -0,0 +1,538 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkInterface() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkInterfaceRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "cluster_network_interface_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network interface identifier.", + }, + "allow_ip_spoofing": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network interface was created.", + }, + "enable_infrastructure_nat": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network interface.", + }, + "mac_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network subnet reserved IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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 cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + // "protocol_state_filtering_mode": &schema.Schema{ + // Type: schema.TypeString, + // Computed: true, + // Description: "The protocol state filtering mode used for this cluster network interface.Protocol state filtering monitors each network connection flowing over this cluster network interface, and drops any packets that are invalid based on the current connection state and protocol. See [Protocol state filtering mode](https://cloud.ibm.com/docs/vpc?topic=vpc-vni-about#protocol-state-filtering) for more information.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + // }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The VPC this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The zone this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkInterfaceRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkInterfaceOptions := &vpcv1.GetClusterNetworkInterfaceOptions{} + + getClusterNetworkInterfaceOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + getClusterNetworkInterfaceOptions.SetID(d.Get("cluster_network_interface_id").(string)) + + clusterNetworkInterface, _, err := vpcClient.GetClusterNetworkInterfaceWithContext(context, getClusterNetworkInterfaceOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkInterfaceWithContext failed: %s", err.Error()), "(Data) ibm_is_cluster_network_interface", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *getClusterNetworkInterfaceOptions.ClusterNetworkID, *getClusterNetworkInterfaceOptions.ID)) + + if err = d.Set("allow_ip_spoofing", clusterNetworkInterface.AllowIPSpoofing); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting allow_ip_spoofing: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-allow_ip_spoofing").GetDiag() + } + + if err = d.Set("auto_delete", clusterNetworkInterface.AutoDelete); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting auto_delete: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-auto_delete").GetDiag() + } + + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkInterface.CreatedAt)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting created_at: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-created_at").GetDiag() + } + + if err = d.Set("enable_infrastructure_nat", clusterNetworkInterface.EnableInfrastructureNat); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting enable_infrastructure_nat: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-enable_infrastructure_nat").GetDiag() + } + + if err = d.Set("href", clusterNetworkInterface.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-href").GetDiag() + } + + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkInterface.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_reasons: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-lifecycle_reasons").GetDiag() + } + + if err = d.Set("lifecycle_state", clusterNetworkInterface.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-lifecycle_state").GetDiag() + } + + if !core.IsNil(clusterNetworkInterface.MacAddress) { + if err = d.Set("mac_address", clusterNetworkInterface.MacAddress); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting mac_address: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-mac_address").GetDiag() + } + } + + if err = d.Set("name", clusterNetworkInterface.Name); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-name").GetDiag() + } + + primaryIP := []map[string]interface{}{} + primaryIPMap, err := DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(clusterNetworkInterface.PrimaryIP) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "primary_ip-to-map").GetDiag() + } + primaryIP = append(primaryIP, primaryIPMap) + if err = d.Set("primary_ip", primaryIP); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting primary_ip: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-primary_ip").GetDiag() + } + + // if !core.IsNil(clusterNetworkInterface.ProtocolStateFilteringMode) { + // if err = d.Set("protocol_state_filtering_mode", clusterNetworkInterface.ProtocolStateFilteringMode); err != nil { + // return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting protocol_state_filtering_mode: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-protocol_state_filtering_mode").GetDiag() + // } + // } + + if err = d.Set("resource_type", clusterNetworkInterface.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-resource_type").GetDiag() + } + + if !core.IsNil(clusterNetworkInterface.Subnet) { + subnet := []map[string]interface{}{} + subnetMap, err := DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(clusterNetworkInterface.Subnet) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "subnet-to-map").GetDiag() + } + subnet = append(subnet, subnetMap) + if err = d.Set("subnet", subnet); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting subnet: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-subnet").GetDiag() + } + } + + if !core.IsNil(clusterNetworkInterface.Target) { + target := []map[string]interface{}{} + targetMap, err := DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(clusterNetworkInterface.Target) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "target-to-map").GetDiag() + } + target = append(target, targetMap) + if err = d.Set("target", target); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting target: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-target").GetDiag() + } + } + + vpc := []map[string]interface{}{} + vpcMap, err := DataSourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(clusterNetworkInterface.VPC) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "vpc-to-map").GetDiag() + } + vpc = append(vpc, vpcMap) + if err = d.Set("vpc", vpc); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting vpc: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-vpc").GetDiag() + } + + zone := []map[string]interface{}{} + zoneMap, err := DataSourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(clusterNetworkInterface.Zone) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interface", "read", "zone-to-map").GetDiag() + } + zone = append(zone, zoneMap) + if err = d.Set("zone", zone); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting zone: %s", err), "(Data) ibm_is_cluster_network_interface", "read", "set-zone").GetDiag() + } + + return nil +} + +func DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(model *vpcv1.ClusterNetworkInterfaceLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(model vpcv1.ClusterNetworkInterfaceTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext); ok { + return DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfaceTarget) + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfaceTargetIntf subtype encountered") + } +} + +func DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model *vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_interface_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_interface_test.go new file mode 100644 index 0000000000..097cc19df8 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_interface_test.go @@ -0,0 +1,324 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkInterfaceDataSourceBasic(t *testing.T) { + clusterNetworkInterfaceClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfaceDataSourceConfigBasic(clusterNetworkInterfaceClusterNetworkID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_interface_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "mac_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "zone.#"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkInterfaceDataSourceAllArgs(t *testing.T) { + clusterNetworkInterfaceClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkInterfaceName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfaceDataSourceConfig(clusterNetworkInterfaceClusterNetworkID, clusterNetworkInterfaceName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_interface_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_reasons.0.code"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_reasons.0.message"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_reasons.0.more_info"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "mac_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "protocol_state_filtering_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "target.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "zone.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkInterfaceDataSourceConfigBasic(clusterNetworkInterfaceClusterNetworkID string) string { + return fmt.Sprintf(` + data "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + cluster_network_interface_id = "02c7-fcc6bdf2-56f5-40ad-abce-42950007857c" + } + `) +} + +func testAccCheckIBMIsClusterNetworkInterfaceDataSourceConfig(clusterNetworkInterfaceClusterNetworkID string, clusterNetworkInterfaceName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = "%s" + name = "%s" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + + data "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_id + cluster_network_interface_id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + `, clusterNetworkInterfaceClusterNetworkID, clusterNetworkInterfaceName) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["address"] = "10.1.0.6" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["id"] = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["name"] = "my-cluster-network-subnet-reserved-ip" + model["resource_type"] = "cluster_network_subnet_reserved_ip" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPReference) + model.Address = core.StringPtr("10.1.0.6") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.ID = core.StringPtr("6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.Name = core.StringPtr("my-cluster-network-subnet-reserved-ip") + model.ResourceType = core.StringPtr("cluster_network_subnet_reserved_ip") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["id"] = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["name"] = "my-cluster-network-subnet" + model["resource_type"] = "cluster_network_subnet" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReference) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.ID = core.StringPtr("0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.Name = core.StringPtr("my-cluster-network-subnet") + model.ResourceType = core.StringPtr("cluster_network_subnet") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + model["id"] = "0717-fb880975-db45-4459-8548-64e3995ac213" + model["name"] = "my-instance-network-attachment" + model["resource_type"] = "instance_cluster_network_attachment" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceTarget) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213") + model.ID = core.StringPtr("0717-fb880975-db45-4459-8548-64e3995ac213") + model.Name = core.StringPtr("my-instance-network-attachment") + model.ResourceType = core.StringPtr("instance_cluster_network_attachment") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + model["id"] = "0717-fb880975-db45-4459-8548-64e3995ac213" + model["name"] = "my-instance-network-attachment" + model["resource_type"] = "instance_cluster_network_attachment" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213") + model.ID = core.StringPtr("0717-fb880975-db45-4459-8548-64e3995ac213") + model.Name = core.StringPtr("my-instance-network-attachment") + model.ResourceType = core.StringPtr("instance_cluster_network_attachment") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["name"] = "my-vpc" + model["resource_type"] = "vpc" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.VPCReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Name = core.StringPtr("my-vpc") + model.ResourceType = core.StringPtr("vpc") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + model["name"] = "us-south-1" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ZoneReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + model.Name = core.StringPtr("us-south-1") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces.go new file mode 100644 index 0000000000..9734880bb6 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces.go @@ -0,0 +1,537 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkInterfaces() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkInterfacesRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `name` property matching the exact specified name.", + }, + "sort": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "-created_at", + Description: "Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order.", + }, + "interfaces": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of cluster network interfaces.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_ip_spoofing": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network interface was created.", + }, + "enable_infrastructure_nat": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network interface.", + }, + "mac_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network subnet reserved IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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 cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + // "protocol_state_filtering_mode": &schema.Schema{ + // Type: schema.TypeString, + // Computed: true, + // Description: "The protocol state filtering mode used for this cluster network interface.Protocol state filtering monitors each network connection flowing over this cluster network interface, and drops any packets that are invalid based on the current connection state and protocol. See [Protocol state filtering mode](https://cloud.ibm.com/docs/vpc?topic=vpc-vni-about#protocol-state-filtering) for more information.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + // }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The VPC this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The zone this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkInterfacesRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interfaces", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listClusterNetworkInterfacesOptions := &vpcv1.ListClusterNetworkInterfacesOptions{} + + listClusterNetworkInterfacesOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + if _, ok := d.GetOk("name"); ok { + listClusterNetworkInterfacesOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("sort"); ok { + listClusterNetworkInterfacesOptions.SetSort(d.Get("sort").(string)) + } + + var pager *vpcv1.ClusterNetworkInterfacesPager + pager, err = vpcClient.NewClusterNetworkInterfacesPager(listClusterNetworkInterfacesOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interfaces", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ClusterNetworkInterfacesPager.GetAll() failed %s", err), "(Data) ibm_is_cluster_network_interfaces", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsClusterNetworkInterfacesID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_interfaces", "read", "ClusterNetworks-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("interfaces", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting interfaces %s", err), "(Data) ibm_is_cluster_network_interfaces", "read", "interfaces-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsClusterNetworkInterfacesID returns a reasonable ID for the list. +func dataSourceIBMIsClusterNetworkInterfacesID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceToMap(model *vpcv1.ClusterNetworkInterface) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["allow_ip_spoofing"] = *model.AllowIPSpoofing + modelMap["auto_delete"] = *model.AutoDelete + modelMap["created_at"] = model.CreatedAt.String() + modelMap["enable_infrastructure_nat"] = *model.EnableInfrastructureNat + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range model.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + modelMap["lifecycle_reasons"] = lifecycleReasons + modelMap["lifecycle_state"] = *model.LifecycleState + if model.MacAddress != nil { + modelMap["mac_address"] = *model.MacAddress + } + modelMap["name"] = *model.Name + primaryIPMap, err := DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReservedIPReferenceToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + // if model.ProtocolStateFilteringMode != nil { + // modelMap["protocol_state_filtering_mode"] = *model.ProtocolStateFilteringMode + // } + modelMap["resource_type"] = *model.ResourceType + if model.Subnet != nil { + subnetMap, err := DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReferenceToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + if model.Target != nil { + targetMap, err := DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetToMap(model.Target) + if err != nil { + return modelMap, err + } + modelMap["target"] = []map[string]interface{}{targetMap} + } + vpcMap, err := DataSourceIBMIsClusterNetworkInterfacesVPCReferenceToMap(model.VPC) + if err != nil { + return modelMap, err + } + modelMap["vpc"] = []map[string]interface{}{vpcMap} + zoneMap, err := DataSourceIBMIsClusterNetworkInterfacesZoneReferenceToMap(model.Zone) + if err != nil { + return modelMap, err + } + modelMap["zone"] = []map[string]interface{}{zoneMap} + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceLifecycleReasonToMap(model *vpcv1.ClusterNetworkInterfaceLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfacesDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfacesDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetToMap(model vpcv1.ClusterNetworkInterfaceTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext); ok { + return DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfaceTarget) + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfaceTargetIntf subtype encountered") + } +} + +func DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model *vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkInterfacesDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkInterfacesZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces_test.go new file mode 100644 index 0000000000..d421399715 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_interfaces_test.go @@ -0,0 +1,452 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkInterfacesDataSourceBasic(t *testing.T) { + clusterNetworkInterfaceClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfacesDataSourceConfigBasic(clusterNetworkInterfaceClusterNetworkID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.mac_address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.target.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.zone.#"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkInterfacesDataSourceAllArgs(t *testing.T) { + clusterNetworkInterfaceClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkInterfaceName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfacesDataSourceConfig(clusterNetworkInterfaceClusterNetworkID, clusterNetworkInterfaceName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "sort"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.mac_address"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.name", clusterNetworkInterfaceName), + // resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.protocol_state_filtering_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_interfaces.is_cluster_network_interfaces_instance", "interfaces.0.resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkInterfacesDataSourceConfigBasic(clusterNetworkInterfaceClusterNetworkID string) string { + return fmt.Sprintf(` + + data "ibm_is_cluster_network_interfaces" "is_cluster_network_interfaces_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + } + `) +} + +func testAccCheckIBMIsClusterNetworkInterfacesDataSourceConfig(clusterNetworkInterfaceClusterNetworkID string, clusterNetworkInterfaceName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = "%s" + name = "%s" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + + data "ibm_is_cluster_network_interfaces" "is_cluster_network_interfaces_instance" { + cluster_network_id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_id + name = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.name + sort = "name" + } + `, clusterNetworkInterfaceClusterNetworkID, clusterNetworkInterfaceName) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + clusterNetworkInterfaceLifecycleReasonModel := make(map[string]interface{}) + clusterNetworkInterfaceLifecycleReasonModel["code"] = "resource_suspended_by_provider" + clusterNetworkInterfaceLifecycleReasonModel["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + clusterNetworkInterfaceLifecycleReasonModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + clusterNetworkSubnetReservedIPReferenceModel := make(map[string]interface{}) + clusterNetworkSubnetReservedIPReferenceModel["address"] = "10.1.0.6" + clusterNetworkSubnetReservedIPReferenceModel["deleted"] = []map[string]interface{}{deletedModel} + clusterNetworkSubnetReservedIPReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/63341ffa-1037-4b50-be40-676e3e9ac0c7" + clusterNetworkSubnetReservedIPReferenceModel["id"] = "63341ffa-1037-4b50-be40-676e3e9ac0c7" + clusterNetworkSubnetReservedIPReferenceModel["name"] = "my-cluster-network-subnet-reserved-ip" + clusterNetworkSubnetReservedIPReferenceModel["resource_type"] = "cluster_network_subnet_reserved_ip" + + clusterNetworkSubnetReferenceModel := make(map[string]interface{}) + clusterNetworkSubnetReferenceModel["deleted"] = []map[string]interface{}{deletedModel} + clusterNetworkSubnetReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + clusterNetworkSubnetReferenceModel["id"] = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + clusterNetworkSubnetReferenceModel["name"] = "my-cluster-network-subnet" + clusterNetworkSubnetReferenceModel["resource_type"] = "cluster_network_subnet" + + clusterNetworkInterfaceTargetModel := make(map[string]interface{}) + clusterNetworkInterfaceTargetModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + clusterNetworkInterfaceTargetModel["id"] = "0717-fb880975-db45-4459-8548-64e3995ac213" + clusterNetworkInterfaceTargetModel["name"] = "my-instance-network-attachment" + clusterNetworkInterfaceTargetModel["resource_type"] = "instance_cluster_network_attachment" + + vpcReferenceModel := make(map[string]interface{}) + vpcReferenceModel["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["deleted"] = []map[string]interface{}{deletedModel} + vpcReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["name"] = "my-vpc" + vpcReferenceModel["resource_type"] = "vpc" + + zoneReferenceModel := make(map[string]interface{}) + zoneReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + zoneReferenceModel["name"] = "us-south-1" + + model := make(map[string]interface{}) + model["allow_ip_spoofing"] = true + model["auto_delete"] = false + model["created_at"] = "2019-01-01T12:00:00.000Z" + model["enable_infrastructure_nat"] = false + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["lifecycle_reasons"] = []map[string]interface{}{clusterNetworkInterfaceLifecycleReasonModel} + model["lifecycle_state"] = "stable" + model["mac_address"] = "02:00:4D:45:45:4D" + model["name"] = "my-cluster-network-interface" + model["primary_ip"] = []map[string]interface{}{clusterNetworkSubnetReservedIPReferenceModel} + // model["protocol_state_filtering_mode"] = "enabled" + model["resource_type"] = "cluster_network_interface" + model["subnet"] = []map[string]interface{}{clusterNetworkSubnetReferenceModel} + model["target"] = []map[string]interface{}{clusterNetworkInterfaceTargetModel} + model["vpc"] = []map[string]interface{}{vpcReferenceModel} + model["zone"] = []map[string]interface{}{zoneReferenceModel} + + assert.Equal(t, result, model) + } + + clusterNetworkInterfaceLifecycleReasonModel := new(vpcv1.ClusterNetworkInterfaceLifecycleReason) + clusterNetworkInterfaceLifecycleReasonModel.Code = core.StringPtr("resource_suspended_by_provider") + clusterNetworkInterfaceLifecycleReasonModel.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + clusterNetworkInterfaceLifecycleReasonModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + clusterNetworkSubnetReservedIPReferenceModel := new(vpcv1.ClusterNetworkSubnetReservedIPReference) + clusterNetworkSubnetReservedIPReferenceModel.Address = core.StringPtr("10.1.0.6") + clusterNetworkSubnetReservedIPReferenceModel.Deleted = deletedModel + clusterNetworkSubnetReservedIPReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/63341ffa-1037-4b50-be40-676e3e9ac0c7") + clusterNetworkSubnetReservedIPReferenceModel.ID = core.StringPtr("63341ffa-1037-4b50-be40-676e3e9ac0c7") + clusterNetworkSubnetReservedIPReferenceModel.Name = core.StringPtr("my-cluster-network-subnet-reserved-ip") + clusterNetworkSubnetReservedIPReferenceModel.ResourceType = core.StringPtr("cluster_network_subnet_reserved_ip") + + clusterNetworkSubnetReferenceModel := new(vpcv1.ClusterNetworkSubnetReference) + clusterNetworkSubnetReferenceModel.Deleted = deletedModel + clusterNetworkSubnetReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + clusterNetworkSubnetReferenceModel.ID = core.StringPtr("0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + clusterNetworkSubnetReferenceModel.Name = core.StringPtr("my-cluster-network-subnet") + clusterNetworkSubnetReferenceModel.ResourceType = core.StringPtr("cluster_network_subnet") + + clusterNetworkInterfaceTargetModel := new(vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) + clusterNetworkInterfaceTargetModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213") + clusterNetworkInterfaceTargetModel.ID = core.StringPtr("0717-fb880975-db45-4459-8548-64e3995ac213") + clusterNetworkInterfaceTargetModel.Name = core.StringPtr("my-instance-network-attachment") + clusterNetworkInterfaceTargetModel.ResourceType = core.StringPtr("instance_cluster_network_attachment") + + vpcReferenceModel := new(vpcv1.VPCReference) + vpcReferenceModel.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.Deleted = deletedModel + vpcReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.Name = core.StringPtr("my-vpc") + vpcReferenceModel.ResourceType = core.StringPtr("vpc") + + zoneReferenceModel := new(vpcv1.ZoneReference) + zoneReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + zoneReferenceModel.Name = core.StringPtr("us-south-1") + + model := new(vpcv1.ClusterNetworkInterface) + model.AllowIPSpoofing = core.BoolPtr(true) + model.AutoDelete = core.BoolPtr(false) + model.CreatedAt = CreateMockDateTime("2019-01-01T12:00:00.000Z") + model.EnableInfrastructureNat = core.BoolPtr(false) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.LifecycleReasons = []vpcv1.ClusterNetworkInterfaceLifecycleReason{*clusterNetworkInterfaceLifecycleReasonModel} + model.LifecycleState = core.StringPtr("stable") + model.MacAddress = core.StringPtr("02:00:4D:45:45:4D") + model.Name = core.StringPtr("my-cluster-network-interface") + model.PrimaryIP = clusterNetworkSubnetReservedIPReferenceModel + // model.ProtocolStateFilteringMode = core.StringPtr("enabled") + model.ResourceType = core.StringPtr("cluster_network_interface") + model.Subnet = clusterNetworkSubnetReferenceModel + model.Target = clusterNetworkInterfaceTargetModel + model.VPC = vpcReferenceModel + model.Zone = zoneReferenceModel + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReservedIPReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["address"] = "10.1.0.6" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["id"] = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["name"] = "my-cluster-network-subnet-reserved-ip" + model["resource_type"] = "cluster_network_subnet_reserved_ip" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPReference) + model.Address = core.StringPtr("10.1.0.6") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.ID = core.StringPtr("6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.Name = core.StringPtr("my-cluster-network-subnet-reserved-ip") + model.ResourceType = core.StringPtr("cluster_network_subnet_reserved_ip") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReservedIPReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["id"] = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["name"] = "my-cluster-network-subnet" + model["resource_type"] = "cluster_network_subnet" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReference) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.ID = core.StringPtr("0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.Name = core.StringPtr("my-cluster-network-subnet") + model.ResourceType = core.StringPtr("cluster_network_subnet") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkSubnetReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + model["id"] = "0717-fb880975-db45-4459-8548-64e3995ac213" + model["name"] = "my-instance-network-attachment" + model["resource_type"] = "instance_cluster_network_attachment" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceTarget) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213") + model.ID = core.StringPtr("0717-fb880975-db45-4459-8548-64e3995ac213") + model.Name = core.StringPtr("my-instance-network-attachment") + model.ResourceType = core.StringPtr("instance_cluster_network_attachment") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + model["id"] = "0717-fb880975-db45-4459-8548-64e3995ac213" + model["name"] = "my-instance-network-attachment" + model["resource_type"] = "instance_cluster_network_attachment" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213") + model.ID = core.StringPtr("0717-fb880975-db45-4459-8548-64e3995ac213") + model.Name = core.StringPtr("my-instance-network-attachment") + model.ResourceType = core.StringPtr("instance_cluster_network_attachment") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesVPCReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["name"] = "my-vpc" + model["resource_type"] = "vpc" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.VPCReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Name = core.StringPtr("my-vpc") + model.ResourceType = core.StringPtr("vpc") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesVPCReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkInterfacesZoneReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + model["name"] = "us-south-1" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ZoneReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + model.Name = core.StringPtr("us-south-1") + + result, err := vpc.DataSourceIBMIsClusterNetworkInterfacesZoneReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_profile.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_profile.go new file mode 100644 index 0000000000..3acf8ea15a --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_profile.go @@ -0,0 +1,164 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkProfile() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkProfileRead, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network profile name.", + }, + "family": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The product family this cluster network profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "supported_instance_profiles": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The instance profiles that support this cluster network profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual server instance profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this virtual server instance profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zones": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "Zones in this region that support this cluster network profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkProfileRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profile", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkProfileOptions := &vpcv1.GetClusterNetworkProfileOptions{} + + getClusterNetworkProfileOptions.SetName(d.Get("name").(string)) + + clusterNetworkProfile, _, err := vpcClient.GetClusterNetworkProfileWithContext(context, getClusterNetworkProfileOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkProfileWithContext failed: %s", err.Error()), "(Data) ibm_is_cluster_network_profile", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*clusterNetworkProfile.Name) + + if err = d.Set("family", clusterNetworkProfile.Family); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting family: %s", err), "(Data) ibm_is_cluster_network_profile", "read", "set-family").GetDiag() + } + + if err = d.Set("href", clusterNetworkProfile.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_cluster_network_profile", "read", "set-href").GetDiag() + } + + if err = d.Set("resource_type", clusterNetworkProfile.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_cluster_network_profile", "read", "set-resource_type").GetDiag() + } + + supportedInstanceProfiles := []map[string]interface{}{} + for _, supportedInstanceProfilesItem := range clusterNetworkProfile.SupportedInstanceProfiles { + supportedInstanceProfilesItemMap, err := DataSourceIBMIsClusterNetworkProfileInstanceProfileReferenceToMap(&supportedInstanceProfilesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profile", "read", "supported_instance_profiles-to-map").GetDiag() + } + supportedInstanceProfiles = append(supportedInstanceProfiles, supportedInstanceProfilesItemMap) + } + if err = d.Set("supported_instance_profiles", supportedInstanceProfiles); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting supported_instance_profiles: %s", err), "(Data) ibm_is_cluster_network_profile", "read", "set-supported_instance_profiles").GetDiag() + } + + zones := []map[string]interface{}{} + for _, zonesItem := range clusterNetworkProfile.Zones { + zonesItemMap, err := DataSourceIBMIsClusterNetworkProfileZoneReferenceToMap(&zonesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profile", "read", "zones-to-map").GetDiag() + } + zones = append(zones, zonesItemMap) + } + if err = d.Set("zones", zones); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting zones: %s", err), "(Data) ibm_is_cluster_network_profile", "read", "set-zones").GetDiag() + } + + return nil +} + +func DataSourceIBMIsClusterNetworkProfileInstanceProfileReferenceToMap(model *vpcv1.InstanceProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkProfileZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_profile_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_profile_test.go new file mode 100644 index 0000000000..b3c887ab8e --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_profile_test.go @@ -0,0 +1,87 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkProfileDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkProfileDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "family"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "supported_instance_profiles.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "supported_instance_profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "supported_instance_profiles.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "supported_instance_profiles.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profile.is_cluster_network_profile_instance", "zones.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkProfileDataSourceConfigBasic() string { + return fmt.Sprintf(` + data "ibm_is_cluster_network_profile" "is_cluster_network_profile_instance" { + name = "%s" + } + `, acc.ISClusterNetworkProfileName) +} + +func TestDataSourceIBMIsClusterNetworkProfileInstanceProfileReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/instance/profiles/bx2-4x16" + model["name"] = "bx2-4x16" + model["resource_type"] = "instance_profile" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.InstanceProfileReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/instance/profiles/bx2-4x16") + model.Name = core.StringPtr("bx2-4x16") + model.ResourceType = core.StringPtr("instance_profile") + + result, err := vpc.DataSourceIBMIsClusterNetworkProfileInstanceProfileReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkProfileZoneReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + model["name"] = "us-south-1" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ZoneReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + model.Name = core.StringPtr("us-south-1") + + result, err := vpc.DataSourceIBMIsClusterNetworkProfileZoneReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles.go new file mode 100644 index 0000000000..9f3a64f134 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles.go @@ -0,0 +1,189 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkProfiles() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkProfilesRead, + + Schema: map[string]*schema.Schema{ + "profiles": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of cluster network profiles.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "family": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The product family this cluster network profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "supported_instance_profiles": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The instance profiles that support this cluster network profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this virtual server instance profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this virtual server instance profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zones": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "Zones in this region that support this cluster network profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkProfilesRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profiles", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listClusterNetworkProfilesOptions := &vpcv1.ListClusterNetworkProfilesOptions{} + + var pager *vpcv1.ClusterNetworkProfilesPager + pager, err = vpcClient.NewClusterNetworkProfilesPager(listClusterNetworkProfilesOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profiles", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ClusterNetworkProfilesPager.GetAll() failed %s", err), "(Data) ibm_is_cluster_network_profiles", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsClusterNetworkProfilesID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsClusterNetworkProfilesClusterNetworkProfileToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_profiles", "read", "ClusterNetworks-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("profiles", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting profiles %s", err), "(Data) ibm_is_cluster_network_profiles", "read", "profiles-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsClusterNetworkProfilesID returns a reasonable ID for the list. +func dataSourceIBMIsClusterNetworkProfilesID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsClusterNetworkProfilesClusterNetworkProfileToMap(model *vpcv1.ClusterNetworkProfile) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["family"] = *model.Family + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + supportedInstanceProfiles := []map[string]interface{}{} + for _, supportedInstanceProfilesItem := range model.SupportedInstanceProfiles { + supportedInstanceProfilesItemMap, err := DataSourceIBMIsClusterNetworkProfilesInstanceProfileReferenceToMap(&supportedInstanceProfilesItem) // #nosec G601 + if err != nil { + return modelMap, err + } + supportedInstanceProfiles = append(supportedInstanceProfiles, supportedInstanceProfilesItemMap) + } + modelMap["supported_instance_profiles"] = supportedInstanceProfiles + zones := []map[string]interface{}{} + for _, zonesItem := range model.Zones { + zonesItemMap, err := DataSourceIBMIsClusterNetworkProfilesZoneReferenceToMap(&zonesItem) // #nosec G601 + if err != nil { + return modelMap, err + } + zones = append(zones, zonesItemMap) + } + modelMap["zones"] = zones + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkProfilesInstanceProfileReferenceToMap(model *vpcv1.InstanceProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkProfilesZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles_test.go new file mode 100644 index 0000000000..d7edf24b50 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_profiles_test.go @@ -0,0 +1,45 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMIsClusterNetworkProfilesDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkProfilesDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.family"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.supported_instance_profiles.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.supported_instance_profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.supported_instance_profiles.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.supported_instance_profiles.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_profiles.is_cluster_network_profiles_instance", "profiles.0.zones.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkProfilesDataSourceConfigBasic() string { + return fmt.Sprintf(` + data "ibm_is_cluster_network_profiles" "is_cluster_network_profiles_instance" { + } + `) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet.go new file mode 100644 index 0000000000..0ad8f109f6 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet.go @@ -0,0 +1,188 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkSubnet() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkSubnetRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "cluster_network_subnet_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network subnet identifier.", + }, + "available_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + "ip_version": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "ipv4_cidr_block": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IPv4 range of this cluster network subnet, expressed in CIDR format.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "total_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses.", + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkSubnetRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkSubnetOptions := &vpcv1.GetClusterNetworkSubnetOptions{} + + getClusterNetworkSubnetOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + getClusterNetworkSubnetOptions.SetID(d.Get("cluster_network_subnet_id").(string)) + + clusterNetworkSubnet, _, err := vpcClient.GetClusterNetworkSubnetWithContext(context, getClusterNetworkSubnetOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkSubnetWithContext failed: %s", err.Error()), "(Data) ibm_is_cluster_network_subnet", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *getClusterNetworkSubnetOptions.ClusterNetworkID, *getClusterNetworkSubnetOptions.ID)) + + if err = d.Set("available_ipv4_address_count", flex.IntValue(clusterNetworkSubnet.AvailableIpv4AddressCount)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting available_ipv4_address_count: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-available_ipv4_address_count").GetDiag() + } + + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkSubnet.CreatedAt)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting created_at: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-created_at").GetDiag() + } + + if err = d.Set("href", clusterNetworkSubnet.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-href").GetDiag() + } + + if err = d.Set("ip_version", clusterNetworkSubnet.IPVersion); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting ip_version: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-ip_version").GetDiag() + } + + if err = d.Set("ipv4_cidr_block", clusterNetworkSubnet.Ipv4CIDRBlock); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting ipv4_cidr_block: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-ipv4_cidr_block").GetDiag() + } + + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkSubnet.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_reasons: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-lifecycle_reasons").GetDiag() + } + + if err = d.Set("lifecycle_state", clusterNetworkSubnet.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-lifecycle_state").GetDiag() + } + + if err = d.Set("name", clusterNetworkSubnet.Name); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-name").GetDiag() + } + + if err = d.Set("resource_type", clusterNetworkSubnet.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-resource_type").GetDiag() + } + + if err = d.Set("total_ipv4_address_count", flex.IntValue(clusterNetworkSubnet.TotalIpv4AddressCount)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting total_ipv4_address_count: %s", err), "(Data) ibm_is_cluster_network_subnet", "read", "set-total_ipv4_address_count").GetDiag() + } + + return nil +} + +func DataSourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip.go new file mode 100644 index 0000000000..ea2e8109a8 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip.go @@ -0,0 +1,294 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkSubnetReservedIP() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkSubnetReservedIPRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "cluster_network_subnet_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network subnet identifier.", + }, + "cluster_network_subnet_reserved_ip_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network subnet reserved IP identifier.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet reserved IP was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "owner": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkSubnetReservedIPRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkSubnetReservedIPOptions := &vpcv1.GetClusterNetworkSubnetReservedIPOptions{} + + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(d.Get("cluster_network_subnet_id").(string)) + getClusterNetworkSubnetReservedIPOptions.SetID(d.Get("cluster_network_subnet_reserved_ip_id").(string)) + + clusterNetworkSubnetReservedIP, _, err := vpcClient.GetClusterNetworkSubnetReservedIPWithContext(context, getClusterNetworkSubnetReservedIPOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkSubnetReservedIPWithContext failed: %s", err.Error()), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s/%s", *getClusterNetworkSubnetReservedIPOptions.ClusterNetworkID, *getClusterNetworkSubnetReservedIPOptions.ClusterNetworkSubnetID, *getClusterNetworkSubnetReservedIPOptions.ID)) + + if err = d.Set("address", clusterNetworkSubnetReservedIP.Address); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting address: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-address").GetDiag() + } + + if err = d.Set("auto_delete", clusterNetworkSubnetReservedIP.AutoDelete); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting auto_delete: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-auto_delete").GetDiag() + } + + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkSubnetReservedIP.CreatedAt)); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting created_at: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-created_at").GetDiag() + } + + if err = d.Set("href", clusterNetworkSubnetReservedIP.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-href").GetDiag() + } + + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkSubnetReservedIP.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_reasons: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-lifecycle_reasons").GetDiag() + } + + if err = d.Set("lifecycle_state", clusterNetworkSubnetReservedIP.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-lifecycle_state").GetDiag() + } + + if err = d.Set("name", clusterNetworkSubnetReservedIP.Name); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-name").GetDiag() + } + + if err = d.Set("owner", clusterNetworkSubnetReservedIP.Owner); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting owner: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-owner").GetDiag() + } + + if err = d.Set("resource_type", clusterNetworkSubnetReservedIP.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-resource_type").GetDiag() + } + + if !core.IsNil(clusterNetworkSubnetReservedIP.Target) { + target := []map[string]interface{}{} + targetMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(clusterNetworkSubnetReservedIP.Target) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "target-to-map").GetDiag() + } + target = append(target, targetMap) + if err = d.Set("target", target); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting target: %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ip", "read", "set-target").GetDiag() + } + } + + return nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(model vpcv1.ClusterNetworkSubnetReservedIPTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext); ok { + return DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetReservedIPTargetIntf subtype encountered") + } +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model *vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip_test.go new file mode 100644 index 0000000000..bbeb647db1 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ip_test.go @@ -0,0 +1,207 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkSubnetReservedIPDataSourceBasic(t *testing.T) { + clusterNetworkSubnetReservedIPClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPClusterNetworkSubnetID := fmt.Sprintf("tf_cluster_network_subnet_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetReservedIPDataSourceConfigBasic(clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_reserved_ip_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "owner"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "resource_type"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkSubnetReservedIPDataSourceAllArgs(t *testing.T) { + clusterNetworkSubnetReservedIPClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPClusterNetworkSubnetID := fmt.Sprintf("tf_cluster_network_subnet_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPAddress := fmt.Sprintf("tf_address_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetReservedIPDataSourceConfig(clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID, clusterNetworkSubnetReservedIPAddress, clusterNetworkSubnetReservedIPName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_reserved_ip_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_reasons.0.code"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_reasons.0.message"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_reasons.0.more_info"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "owner"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "target.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIPDataSourceConfigBasic(clusterNetworkSubnetReservedIPClusterNetworkID string, clusterNetworkSubnetReservedIPClusterNetworkSubnetID string) string { + return fmt.Sprintf(` + data "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + cluster_network_subnet_id = "02c7-27ca8206-f73b-4d8f-b996-913711b98ff0" + cluster_network_subnet_reserved_ip_id = "02c7-111099cc-39e2-4c2f-9a32-109bb5a2ae7e" + } + `) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIPDataSourceConfig(clusterNetworkSubnetReservedIPClusterNetworkID string, clusterNetworkSubnetReservedIPClusterNetworkSubnetID string, clusterNetworkSubnetReservedIPAddress string, clusterNetworkSubnetReservedIPName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = "%s" + cluster_network_subnet_id = "%s" + address = "%s" + name = "%s" + } + + data "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_id + cluster_network_subnet_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_id + cluster_network_subnet_reserved_ip_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + } + `, clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID, clusterNetworkSubnetReservedIPAddress, clusterNetworkSubnetReservedIPName) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["name"] = "my-cluster-network-interface" + model["resource_type"] = "cluster_network_interface" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPTarget) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.Name = core.StringPtr("my-cluster-network-interface") + model.ResourceType = core.StringPtr("cluster_network_interface") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["name"] = "my-cluster-network-interface" + model["resource_type"] = "cluster_network_interface" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.Name = core.StringPtr("my-cluster-network-interface") + model.ResourceType = core.StringPtr("cluster_network_interface") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips.go new file mode 100644 index 0000000000..0d778a5c3d --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips.go @@ -0,0 +1,319 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkSubnetReservedIps() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkSubnetReservedIpsRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "cluster_network_subnet_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network subnet identifier.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `name` property matching the exact specified name.", + }, + "sort": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "address", + Description: "Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order.", + }, + "reserved_ips": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of reserved IPs for the cluster network subnet.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet reserved IP was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "owner": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkSubnetReservedIpsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ips", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listClusterNetworkSubnetReservedIpsOptions := &vpcv1.ListClusterNetworkSubnetReservedIpsOptions{} + + listClusterNetworkSubnetReservedIpsOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + listClusterNetworkSubnetReservedIpsOptions.SetClusterNetworkSubnetID(d.Get("cluster_network_subnet_id").(string)) + if _, ok := d.GetOk("name"); ok { + listClusterNetworkSubnetReservedIpsOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("sort"); ok { + listClusterNetworkSubnetReservedIpsOptions.SetSort(d.Get("sort").(string)) + } + + var pager *vpcv1.ClusterNetworkSubnetReservedIpsPager + pager, err = vpcClient.NewClusterNetworkSubnetReservedIpsPager(listClusterNetworkSubnetReservedIpsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ips", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ClusterNetworkSubnetReservedIpsPager.GetAll() failed %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ips", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsClusterNetworkSubnetReservedIpsID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnet_reserved_ips", "read", "ClusterNetworks-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("reserved_ips", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting reserved_ips %s", err), "(Data) ibm_is_cluster_network_subnet_reserved_ips", "read", "reserved_ips-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsClusterNetworkSubnetReservedIpsID returns a reasonable ID for the list. +func dataSourceIBMIsClusterNetworkSubnetReservedIpsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPToMap(model *vpcv1.ClusterNetworkSubnetReservedIP) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + modelMap["auto_delete"] = *model.AutoDelete + modelMap["created_at"] = model.CreatedAt.String() + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range model.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + modelMap["lifecycle_reasons"] = lifecycleReasons + modelMap["lifecycle_state"] = *model.LifecycleState + modelMap["name"] = *model.Name + modelMap["owner"] = *model.Owner + modelMap["resource_type"] = *model.ResourceType + if model.Target != nil { + targetMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetToMap(model.Target) + if err != nil { + return modelMap, err + } + modelMap["target"] = []map[string]interface{}{targetMap} + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetToMap(model vpcv1.ClusterNetworkSubnetReservedIPTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext); ok { + return DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIpsDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetReservedIPTargetIntf subtype encountered") + } +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIpsDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model *vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworkSubnetReservedIpsDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips_test.go new file mode 100644 index 0000000000..b41667ff5e --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_reserved_ips_test.go @@ -0,0 +1,274 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkSubnetReservedIpsDataSourceBasic(t *testing.T) { + clusterNetworkSubnetReservedIPClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPClusterNetworkSubnetID := fmt.Sprintf("tf_cluster_network_subnet_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetReservedIpsDataSourceConfigBasic(clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.address"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.owner"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.resource_type"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkSubnetReservedIpsDataSourceAllArgs(t *testing.T) { + clusterNetworkSubnetReservedIPClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPClusterNetworkSubnetID := fmt.Sprintf("tf_cluster_network_subnet_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPAddress := fmt.Sprintf("tf_address_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetReservedIPName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetReservedIpsDataSourceConfig(clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID, clusterNetworkSubnetReservedIPAddress, clusterNetworkSubnetReservedIPName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "sort"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.#"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.address", clusterNetworkSubnetReservedIPAddress), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.auto_delete"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.lifecycle_state"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.name", clusterNetworkSubnetReservedIPName), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.owner"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet_reserved_ips.is_cluster_network_subnet_reserved_ips_instance", "reserved_ips.0.resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIpsDataSourceConfigBasic(clusterNetworkSubnetReservedIPClusterNetworkID string, clusterNetworkSubnetReservedIPClusterNetworkSubnetID string) string { + return fmt.Sprintf(` + + data "ibm_is_cluster_network_subnet_reserved_ips" "is_cluster_network_subnet_reserved_ips_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + cluster_network_subnet_id = "02c7-27ca8206-f73b-4d8f-b996-913711b98ff0" + } + `) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIpsDataSourceConfig(clusterNetworkSubnetReservedIPClusterNetworkID string, clusterNetworkSubnetReservedIPClusterNetworkSubnetID string, clusterNetworkSubnetReservedIPAddress string, clusterNetworkSubnetReservedIPName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = "%s" + cluster_network_subnet_id = "%s" + address = "%s" + name = "%s" + } + + data "ibm_is_cluster_network_subnet_reserved_ips" "is_cluster_network_subnet_reserved_ips_instance" { + cluster_network_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_id + cluster_network_subnet_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_id + name = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.name + sort = "name" + } + `, clusterNetworkSubnetReservedIPClusterNetworkID, clusterNetworkSubnetReservedIPClusterNetworkSubnetID, clusterNetworkSubnetReservedIPAddress, clusterNetworkSubnetReservedIPName) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + clusterNetworkSubnetReservedIPLifecycleReasonModel := make(map[string]interface{}) + clusterNetworkSubnetReservedIPLifecycleReasonModel["code"] = "resource_suspended_by_provider" + clusterNetworkSubnetReservedIPLifecycleReasonModel["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + clusterNetworkSubnetReservedIPLifecycleReasonModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + clusterNetworkSubnetReservedIPTargetModel := make(map[string]interface{}) + clusterNetworkSubnetReservedIPTargetModel["deleted"] = []map[string]interface{}{deletedModel} + clusterNetworkSubnetReservedIPTargetModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + clusterNetworkSubnetReservedIPTargetModel["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + clusterNetworkSubnetReservedIPTargetModel["name"] = "my-cluster-network-interface" + clusterNetworkSubnetReservedIPTargetModel["resource_type"] = "cluster_network_interface" + + model := make(map[string]interface{}) + model["address"] = "10.1.0.6" + model["auto_delete"] = false + model["created_at"] = "2019-01-01T12:00:00.000Z" + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["id"] = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + model["lifecycle_reasons"] = []map[string]interface{}{clusterNetworkSubnetReservedIPLifecycleReasonModel} + model["lifecycle_state"] = "stable" + model["name"] = "my-cluster-network-subnet-reserved-ip" + model["owner"] = "user" + model["resource_type"] = "cluster_network_subnet_reserved_ip" + model["target"] = []map[string]interface{}{clusterNetworkSubnetReservedIPTargetModel} + + assert.Equal(t, result, model) + } + + clusterNetworkSubnetReservedIPLifecycleReasonModel := new(vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) + clusterNetworkSubnetReservedIPLifecycleReasonModel.Code = core.StringPtr("resource_suspended_by_provider") + clusterNetworkSubnetReservedIPLifecycleReasonModel.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + clusterNetworkSubnetReservedIPLifecycleReasonModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + clusterNetworkSubnetReservedIPTargetModel := new(vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) + clusterNetworkSubnetReservedIPTargetModel.Deleted = deletedModel + clusterNetworkSubnetReservedIPTargetModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + clusterNetworkSubnetReservedIPTargetModel.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + clusterNetworkSubnetReservedIPTargetModel.Name = core.StringPtr("my-cluster-network-interface") + clusterNetworkSubnetReservedIPTargetModel.ResourceType = core.StringPtr("cluster_network_interface") + + model := new(vpcv1.ClusterNetworkSubnetReservedIP) + model.Address = core.StringPtr("10.1.0.6") + model.AutoDelete = core.BoolPtr(false) + model.CreatedAt = CreateMockDateTime("2019-01-01T12:00:00.000Z") + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.ID = core.StringPtr("6d353a0f-aeb1-4ae1-832e-1110d10981bb") + model.LifecycleReasons = []vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason{*clusterNetworkSubnetReservedIPLifecycleReasonModel} + model.LifecycleState = core.StringPtr("stable") + model.Name = core.StringPtr("my-cluster-network-subnet-reserved-ip") + model.Owner = core.StringPtr("user") + model.ResourceType = core.StringPtr("cluster_network_subnet_reserved_ip") + model.Target = clusterNetworkSubnetReservedIPTargetModel + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["name"] = "my-cluster-network-interface" + model["resource_type"] = "cluster_network_interface" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPTarget) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.Name = core.StringPtr("my-cluster-network-interface") + model.ResourceType = core.StringPtr("cluster_network_interface") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIpsDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIpsDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["id"] = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + model["name"] = "my-cluster-network-interface" + model["resource_type"] = "cluster_network_interface" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.ID = core.StringPtr("0717-ffc092f7-5d02-4b93-ab69-26860529b9fb") + model.Name = core.StringPtr("my-cluster-network-interface") + model.ResourceType = core.StringPtr("cluster_network_interface") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetReservedIpsClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_test.go new file mode 100644 index 0000000000..471f984d7d --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnet_test.go @@ -0,0 +1,130 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkSubnetDataSourceBasic(t *testing.T) { + clusterNetworkSubnetClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetDataSourceConfigBasic(clusterNetworkSubnetClusterNetworkID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ip_version"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkSubnetDataSourceAllArgs(t *testing.T) { + clusterNetworkSubnetClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetIPVersion := "ipv4" + clusterNetworkSubnetIpv4CIDRBlock := fmt.Sprintf("tf_ipv4_cidr_block_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetTotalIpv4AddressCount := fmt.Sprintf("%d", acctest.RandIntRange(8, 16777216)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetDataSourceConfig(clusterNetworkSubnetClusterNetworkID, clusterNetworkSubnetIPVersion, clusterNetworkSubnetIpv4CIDRBlock, clusterNetworkSubnetName, clusterNetworkSubnetTotalIpv4AddressCount), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ip_version"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_reasons.0.code"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_reasons.0.message"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_reasons.0.more_info"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetDataSourceConfigBasic(clusterNetworkSubnetClusterNetworkID string) string { + return fmt.Sprintf(` + + data "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + cluster_network_subnet_id = "02c7-27ca8206-f73b-4d8f-b996-913711b98ff0" + } + `) +} + +func testAccCheckIBMIsClusterNetworkSubnetDataSourceConfig(clusterNetworkSubnetClusterNetworkID string, clusterNetworkSubnetIPVersion string, clusterNetworkSubnetIpv4CIDRBlock string, clusterNetworkSubnetName string, clusterNetworkSubnetTotalIpv4AddressCount string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = "%s" + ip_version = "%s" + ipv4_cidr_block = "%s" + name = "%s" + total_ipv4_address_count = %s + } + + data "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + `, clusterNetworkSubnetClusterNetworkID, clusterNetworkSubnetIPVersion, clusterNetworkSubnetIpv4CIDRBlock, clusterNetworkSubnetName, clusterNetworkSubnetTotalIpv4AddressCount) +} + +func TestDataSourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets.go new file mode 100644 index 0000000000..7922db0149 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets.go @@ -0,0 +1,216 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworkSubnets() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworkSubnetsRead, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The cluster network identifier.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `name` property matching the exact specified name.", + }, + "sort": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "-created_at", + Description: "Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order.", + }, + "subnets": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of subnets for the cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "available_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "ip_version": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "ipv4_cidr_block": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IPv4 range of this cluster network subnet, expressed in CIDR format.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "total_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworkSubnetsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnets", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listClusterNetworkSubnetsOptions := &vpcv1.ListClusterNetworkSubnetsOptions{} + + listClusterNetworkSubnetsOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + if _, ok := d.GetOk("name"); ok { + listClusterNetworkSubnetsOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("sort"); ok { + listClusterNetworkSubnetsOptions.SetSort(d.Get("sort").(string)) + } + + var pager *vpcv1.ClusterNetworkSubnetsPager + pager, err = vpcClient.NewClusterNetworkSubnetsPager(listClusterNetworkSubnetsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnets", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ClusterNetworkSubnetsPager.GetAll() failed %s", err), "(Data) ibm_is_cluster_network_subnets", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsClusterNetworkSubnetsID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_network_subnets", "read", "ClusterNetworks-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("subnets", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting subnets %s", err), "(Data) ibm_is_cluster_network_subnets", "read", "subnets-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsClusterNetworkSubnetsID returns a reasonable ID for the list. +func dataSourceIBMIsClusterNetworkSubnetsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetToMap(model *vpcv1.ClusterNetworkSubnet) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["available_ipv4_address_count"] = flex.IntValue(model.AvailableIpv4AddressCount) + modelMap["created_at"] = model.CreatedAt.String() + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["ip_version"] = *model.IPVersion + modelMap["ipv4_cidr_block"] = *model.Ipv4CIDRBlock + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range model.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + modelMap["lifecycle_reasons"] = lifecycleReasons + modelMap["lifecycle_state"] = *model.LifecycleState + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + modelMap["total_ipv4_address_count"] = flex.IntValue(model.TotalIpv4AddressCount) + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets_test.go new file mode 100644 index 0000000000..d58a0917bb --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_subnets_test.go @@ -0,0 +1,177 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkSubnetsDataSourceBasic(t *testing.T) { + clusterNetworkSubnetClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetsDataSourceConfigBasic(clusterNetworkSubnetClusterNetworkID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.ip_version"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.total_ipv4_address_count"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkSubnetsDataSourceAllArgs(t *testing.T) { + clusterNetworkSubnetClusterNetworkID := fmt.Sprintf("tf_cluster_network_id_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetIPVersion := "ipv4" + clusterNetworkSubnetIpv4CIDRBlock := fmt.Sprintf("tf_ipv4_cidr_block_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + clusterNetworkSubnetTotalIpv4AddressCount := fmt.Sprintf("%d", acctest.RandIntRange(8, 16777216)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetsDataSourceConfig(clusterNetworkSubnetClusterNetworkID, clusterNetworkSubnetIPVersion, clusterNetworkSubnetIpv4CIDRBlock, clusterNetworkSubnetName, clusterNetworkSubnetTotalIpv4AddressCount), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "sort"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.id"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.ip_version", clusterNetworkSubnetIPVersion), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.ipv4_cidr_block", clusterNetworkSubnetIpv4CIDRBlock), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.lifecycle_state"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.name", clusterNetworkSubnetName), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.resource_type"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_network_subnets.is_cluster_network_subnets_instance", "subnets.0.total_ipv4_address_count", clusterNetworkSubnetTotalIpv4AddressCount), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetsDataSourceConfigBasic(clusterNetworkSubnetClusterNetworkID string) string { + return fmt.Sprintf(` + + data "ibm_is_cluster_network_subnets" "is_cluster_network_subnets_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + } + `) +} + +func testAccCheckIBMIsClusterNetworkSubnetsDataSourceConfig(clusterNetworkSubnetClusterNetworkID string, clusterNetworkSubnetIPVersion string, clusterNetworkSubnetIpv4CIDRBlock string, clusterNetworkSubnetName string, clusterNetworkSubnetTotalIpv4AddressCount string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = "%s" + ip_version = "%s" + ipv4_cidr_block = "%s" + name = "%s" + total_ipv4_address_count = %s + } + + data "ibm_is_cluster_network_subnets" "is_cluster_network_subnets_instance" { + cluster_network_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_id + name = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.name + sort = "name" + } + `, clusterNetworkSubnetClusterNetworkID, clusterNetworkSubnetIPVersion, clusterNetworkSubnetIpv4CIDRBlock, clusterNetworkSubnetName, clusterNetworkSubnetTotalIpv4AddressCount) +} + +func TestDataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + clusterNetworkSubnetLifecycleReasonModel := make(map[string]interface{}) + clusterNetworkSubnetLifecycleReasonModel["code"] = "resource_suspended_by_provider" + clusterNetworkSubnetLifecycleReasonModel["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + clusterNetworkSubnetLifecycleReasonModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + model := make(map[string]interface{}) + model["available_ipv4_address_count"] = int(15) + model["created_at"] = "2019-01-01T12:00:00.000Z" + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["id"] = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + model["ip_version"] = "ipv4" + model["ipv4_cidr_block"] = "10.0.0.0/24" + model["lifecycle_reasons"] = []map[string]interface{}{clusterNetworkSubnetLifecycleReasonModel} + model["lifecycle_state"] = "stable" + model["name"] = "my-cluster-network-subnet" + model["resource_type"] = "cluster_network_subnet" + model["total_ipv4_address_count"] = int(256) + + assert.Equal(t, result, model) + } + + clusterNetworkSubnetLifecycleReasonModel := new(vpcv1.ClusterNetworkSubnetLifecycleReason) + clusterNetworkSubnetLifecycleReasonModel.Code = core.StringPtr("resource_suspended_by_provider") + clusterNetworkSubnetLifecycleReasonModel.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + clusterNetworkSubnetLifecycleReasonModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + model := new(vpcv1.ClusterNetworkSubnet) + model.AvailableIpv4AddressCount = core.Int64Ptr(int64(15)) + model.CreatedAt = CreateMockDateTime("2019-01-01T12:00:00.000Z") + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.ID = core.StringPtr("0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930") + model.IPVersion = core.StringPtr("ipv4") + model.Ipv4CIDRBlock = core.StringPtr("10.0.0.0/24") + model.LifecycleReasons = []vpcv1.ClusterNetworkSubnetLifecycleReason{*clusterNetworkSubnetLifecycleReasonModel} + model.LifecycleState = core.StringPtr("stable") + model.Name = core.StringPtr("my-cluster-network-subnet") + model.ResourceType = core.StringPtr("cluster_network_subnet") + model.TotalIpv4AddressCount = core.Int64Ptr(int64(256)) + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkSubnetsClusterNetworkSubnetLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_network_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_network_test.go new file mode 100644 index 0000000000..ed53d12cb3 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_network_test.go @@ -0,0 +1,287 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworkDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "profile.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "profile.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "profile.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "profile.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_group.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_group.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_group.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_group.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.allocation_policy"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.cidr"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "zone.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "zone.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "zone.0.name"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkDataSourceAllArgs(t *testing.T) { + clusterNetworkName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkDataSourceConfig(clusterNetworkName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_reasons.0.code"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_reasons.0.message"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_reasons.0.more_info"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "profile.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_group.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.allocation_policy"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.cidr"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_network.is_cluster_network_instance", "zone.#"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkDataSourceConfigBasic() string { + return fmt.Sprintf(` + data "ibm_is_cluster_network" "is_cluster_network_instance" { + cluster_network_id = "02c7-10274052-f495-4920-a67f-870eb3b87003" + } + `) +} + +func testAccCheckIBMIsClusterNetworkDataSourceConfig(clusterNetworkName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + name = "%s" + profile { + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100" + name = "h100" + resource_type = "cluster_network_profile" + } + resource_group { + href = "https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345" + id = "fee82deba12e4c0fb69c3b09d1f12345" + name = "my-resource-group" + } + subnet_prefixes { + allocation_policy = "auto" + cidr = "10.0.0.0/24" + } + vpc { + crn = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + id = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + name = "my-vpc" + resource_type = "vpc" + } + zone { + href = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + name = "us-south-1" + } + } + + data "ibm_is_cluster_network" "is_cluster_network_instance" { + cluster_network_id = "cluster_network_id" + } + `, clusterNetworkName) +} + +func TestDataSourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkClusterNetworkProfileReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100" + model["name"] = "h100" + model["resource_type"] = "cluster_network_profile" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkProfileReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100") + model.Name = core.StringPtr("h100") + model.ResourceType = core.StringPtr("cluster_network_profile") + + result, err := vpc.DataSourceIBMIsClusterNetworkClusterNetworkProfileReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkResourceGroupReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345" + model["id"] = "fee82deba12e4c0fb69c3b09d1f12345" + model["name"] = "my-resource-group" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ResourceGroupReference) + model.Href = core.StringPtr("https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345") + model.ID = core.StringPtr("fee82deba12e4c0fb69c3b09d1f12345") + model.Name = core.StringPtr("my-resource-group") + + result, err := vpc.DataSourceIBMIsClusterNetworkResourceGroupReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["allocation_policy"] = "auto" + model["cidr"] = "10.0.0.0/24" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetPrefix) + model.AllocationPolicy = core.StringPtr("auto") + model.CIDR = core.StringPtr("10.0.0.0/24") + + result, err := vpc.DataSourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkVPCReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["name"] = "my-vpc" + model["resource_type"] = "vpc" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.VPCReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Name = core.StringPtr("my-vpc") + model.ResourceType = core.StringPtr("vpc") + + result, err := vpc.DataSourceIBMIsClusterNetworkVPCReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworkDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworkZoneReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + model["name"] = "us-south-1" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ZoneReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + model.Name = core.StringPtr("us-south-1") + + result, err := vpc.DataSourceIBMIsClusterNetworkZoneReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_networks.go b/ibm/service/vpc/data_source_ibm_is_cluster_networks.go new file mode 100644 index 0000000000..6d5bef64a1 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_networks.go @@ -0,0 +1,440 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsClusterNetworks() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsClusterNetworksRead, + + Schema: map[string]*schema.Schema{ + "resource_group_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `resource_group.id` property matching the specified identifier.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `name` property matching the exact specified name.", + }, + "sort": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "-created_at", + Description: "Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order.", + }, + "vpc_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to cluster networks with a `vpc.id` property matching the specified id.", + }, + "vpc_crn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to cluster networks with a `vpc.crn` property matching the specified CRN.", + }, + "vpc_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to cluster networks with a `vpc.name` property matching the specified name.", + }, + "cluster_networks": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of cluster networks.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network was created.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "profile": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The profile for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "resource_group": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The resource group for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this resource group.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this resource group.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this resource group.", + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet_prefixes": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The IP address ranges available for subnets for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allocation_policy": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The allocation policy for this subnet prefix:- `auto`: Subnets created by total count in this cluster network can use this prefix.", + }, + "cidr": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CIDR block for this prefix.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The VPC this cluster network resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The zone this cluster network resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsClusterNetworksRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_networks", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listClusterNetworksOptions := &vpcv1.ListClusterNetworksOptions{} + + if _, ok := d.GetOk("resource_group_id"); ok { + listClusterNetworksOptions.SetResourceGroupID(d.Get("resource_group_id").(string)) + } + if _, ok := d.GetOk("name"); ok { + listClusterNetworksOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("sort"); ok { + listClusterNetworksOptions.SetSort(d.Get("sort").(string)) + } + if _, ok := d.GetOk("vpc_id"); ok { + listClusterNetworksOptions.SetVPCID(d.Get("vpc_id").(string)) + } + if _, ok := d.GetOk("vpc_crn"); ok { + listClusterNetworksOptions.SetVPCCRN(d.Get("vpc_crn").(string)) + } + if _, ok := d.GetOk("vpc_name"); ok { + listClusterNetworksOptions.SetVPCName(d.Get("vpc_name").(string)) + } + + var pager *vpcv1.ClusterNetworksPager + pager, err = vpcClient.NewClusterNetworksPager(listClusterNetworksOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_networks", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("ClusterNetworksPager.GetAll() failed %s", err), "(Data) ibm_is_cluster_networks", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsClusterNetworksID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsClusterNetworksClusterNetworkToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_cluster_networks", "read", "ClusterNetworks-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("cluster_networks", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_networks %s", err), "(Data) ibm_is_cluster_networks", "read", "cluster_networks-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsClusterNetworksID returns a reasonable ID for the list. +func dataSourceIBMIsClusterNetworksID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsClusterNetworksClusterNetworkToMap(model *vpcv1.ClusterNetwork) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["created_at"] = model.CreatedAt.String() + modelMap["crn"] = *model.CRN + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range model.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsClusterNetworksClusterNetworkLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + modelMap["lifecycle_reasons"] = lifecycleReasons + modelMap["lifecycle_state"] = *model.LifecycleState + modelMap["name"] = *model.Name + profileMap, err := DataSourceIBMIsClusterNetworksClusterNetworkProfileReferenceToMap(model.Profile) + if err != nil { + return modelMap, err + } + modelMap["profile"] = []map[string]interface{}{profileMap} + resourceGroupMap, err := DataSourceIBMIsClusterNetworksResourceGroupReferenceToMap(model.ResourceGroup) + if err != nil { + return modelMap, err + } + modelMap["resource_group"] = []map[string]interface{}{resourceGroupMap} + modelMap["resource_type"] = *model.ResourceType + subnetPrefixes := []map[string]interface{}{} + for _, subnetPrefixesItem := range model.SubnetPrefixes { + subnetPrefixesItemMap, err := DataSourceIBMIsClusterNetworksClusterNetworkSubnetPrefixToMap(&subnetPrefixesItem) // #nosec G601 + if err != nil { + return modelMap, err + } + subnetPrefixes = append(subnetPrefixes, subnetPrefixesItemMap) + } + modelMap["subnet_prefixes"] = subnetPrefixes + vpcMap, err := DataSourceIBMIsClusterNetworksVPCReferenceToMap(model.VPC) + if err != nil { + return modelMap, err + } + modelMap["vpc"] = []map[string]interface{}{vpcMap} + zoneMap, err := DataSourceIBMIsClusterNetworksZoneReferenceToMap(model.Zone) + if err != nil { + return modelMap, err + } + modelMap["zone"] = []map[string]interface{}{zoneMap} + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksClusterNetworkLifecycleReasonToMap(model *vpcv1.ClusterNetworkLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksClusterNetworkProfileReferenceToMap(model *vpcv1.ClusterNetworkProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksResourceGroupReferenceToMap(model *vpcv1.ResourceGroupReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksClusterNetworkSubnetPrefixToMap(model *vpcv1.ClusterNetworkSubnetPrefix) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["allocation_policy"] = *model.AllocationPolicy + modelMap["cidr"] = *model.CIDR + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsClusterNetworksDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsClusterNetworksZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_cluster_networks_test.go b/ibm/service/vpc/data_source_ibm_is_cluster_networks_test.go new file mode 100644 index 0000000000..0c673f98bf --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_cluster_networks_test.go @@ -0,0 +1,398 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/service/vpc" + . "github.com/IBM-Cloud/terraform-provider-ibm/ibm/unittest" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/stretchr/testify/assert" +) + +func TestAccIBMIsClusterNetworksDataSourceBasic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworksDataSourceConfigBasic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.profile.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.profile.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.profile.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.profile.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_group.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_group.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_group.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_group.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.subnet_prefixes.0.allocation_policy"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.subnet_prefixes.0.cidr"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.vpc.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.vpc.0.crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.vpc.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.vpc.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.vpc.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.zone.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.zone.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.zone.0.name"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworksDataSourceAllArgs(t *testing.T) { + clusterNetworkName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworksDataSourceConfig(clusterNetworkName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "resource_group_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "sort"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "vpc_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "vpc_crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "vpc_name"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.lifecycle_state"), + resource.TestCheckResourceAttr("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.name", clusterNetworkName), + resource.TestCheckResourceAttrSet("data.ibm_is_cluster_networks.is_cluster_networks_instance", "cluster_networks.0.resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworksDataSourceConfigBasic() string { + return fmt.Sprintf(` + + data "ibm_is_cluster_networks" "is_cluster_networks_instance" { + } + `) +} + +func testAccCheckIBMIsClusterNetworksDataSourceConfig(clusterNetworkName string) string { + return fmt.Sprintf(` + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + name = "%s" + profile { + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100" + name = "h100" + resource_type = "cluster_network_profile" + } + resource_group { + href = "https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345" + id = "fee82deba12e4c0fb69c3b09d1f12345" + name = "my-resource-group" + } + subnet_prefixes { + allocation_policy = "auto" + cidr = "10.0.0.0/24" + } + vpc { + crn = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + id = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + name = "my-vpc" + resource_type = "vpc" + } + zone { + href = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + name = "us-south-1" + } + } + + data "ibm_is_cluster_networks" "is_cluster_networks_instance" { + resource_group_id = "resource_group_id" + name = ibm_is_cluster_network.is_cluster_network_instance.name + sort = "name" + vpc_id = "vpc_id" + vpc_crn = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpc_name = "my-vpc" + } + `, clusterNetworkName) +} + +func TestDataSourceIBMIsClusterNetworksClusterNetworkToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + clusterNetworkLifecycleReasonModel := make(map[string]interface{}) + clusterNetworkLifecycleReasonModel["code"] = "resource_suspended_by_provider" + clusterNetworkLifecycleReasonModel["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + clusterNetworkLifecycleReasonModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + clusterNetworkProfileReferenceModel := make(map[string]interface{}) + clusterNetworkProfileReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100" + clusterNetworkProfileReferenceModel["name"] = "h100" + clusterNetworkProfileReferenceModel["resource_type"] = "cluster_network_profile" + + resourceGroupReferenceModel := make(map[string]interface{}) + resourceGroupReferenceModel["href"] = "https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345" + resourceGroupReferenceModel["id"] = "fee82deba12e4c0fb69c3b09d1f12345" + resourceGroupReferenceModel["name"] = "Default" + + clusterNetworkSubnetPrefixModel := make(map[string]interface{}) + clusterNetworkSubnetPrefixModel["allocation_policy"] = "auto" + clusterNetworkSubnetPrefixModel["cidr"] = "10.0.0.0/9" + + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + vpcReferenceModel := make(map[string]interface{}) + vpcReferenceModel["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["deleted"] = []map[string]interface{}{deletedModel} + vpcReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + vpcReferenceModel["name"] = "my-vpc" + vpcReferenceModel["resource_type"] = "vpc" + + zoneReferenceModel := make(map[string]interface{}) + zoneReferenceModel["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + zoneReferenceModel["name"] = "us-south-1" + + model := make(map[string]interface{}) + model["created_at"] = "2019-01-01T12:00:00.000Z" + model["crn"] = "crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::cluster-network:0717-da0df18c-7598-4633-a648-fdaac28a5573" + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573" + model["id"] = "0717-da0df18c-7598-4633-a648-fdaac28a5573" + model["lifecycle_reasons"] = []map[string]interface{}{clusterNetworkLifecycleReasonModel} + model["lifecycle_state"] = "stable" + model["name"] = "my-cluster-network" + model["profile"] = []map[string]interface{}{clusterNetworkProfileReferenceModel} + model["resource_group"] = []map[string]interface{}{resourceGroupReferenceModel} + model["resource_type"] = "cluster_network" + model["subnet_prefixes"] = []map[string]interface{}{clusterNetworkSubnetPrefixModel} + model["vpc"] = []map[string]interface{}{vpcReferenceModel} + model["zone"] = []map[string]interface{}{zoneReferenceModel} + + assert.Equal(t, result, model) + } + + clusterNetworkLifecycleReasonModel := new(vpcv1.ClusterNetworkLifecycleReason) + clusterNetworkLifecycleReasonModel.Code = core.StringPtr("resource_suspended_by_provider") + clusterNetworkLifecycleReasonModel.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + clusterNetworkLifecycleReasonModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + clusterNetworkProfileReferenceModel := new(vpcv1.ClusterNetworkProfileReference) + clusterNetworkProfileReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100") + clusterNetworkProfileReferenceModel.Name = core.StringPtr("h100") + clusterNetworkProfileReferenceModel.ResourceType = core.StringPtr("cluster_network_profile") + + resourceGroupReferenceModel := new(vpcv1.ResourceGroupReference) + resourceGroupReferenceModel.Href = core.StringPtr("https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345") + resourceGroupReferenceModel.ID = core.StringPtr("fee82deba12e4c0fb69c3b09d1f12345") + resourceGroupReferenceModel.Name = core.StringPtr("Default") + + clusterNetworkSubnetPrefixModel := new(vpcv1.ClusterNetworkSubnetPrefix) + clusterNetworkSubnetPrefixModel.AllocationPolicy = core.StringPtr("auto") + clusterNetworkSubnetPrefixModel.CIDR = core.StringPtr("10.0.0.0/9") + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + vpcReferenceModel := new(vpcv1.VPCReference) + vpcReferenceModel.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.Deleted = deletedModel + vpcReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + vpcReferenceModel.Name = core.StringPtr("my-vpc") + vpcReferenceModel.ResourceType = core.StringPtr("vpc") + + zoneReferenceModel := new(vpcv1.ZoneReference) + zoneReferenceModel.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + zoneReferenceModel.Name = core.StringPtr("us-south-1") + + model := new(vpcv1.ClusterNetwork) + model.CreatedAt = CreateMockDateTime("2019-01-01T12:00:00.000Z") + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south-1:a/aa2432b1fa4d4ace891e9b80fc104e34::cluster-network:0717-da0df18c-7598-4633-a648-fdaac28a5573") + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573") + model.ID = core.StringPtr("0717-da0df18c-7598-4633-a648-fdaac28a5573") + model.LifecycleReasons = []vpcv1.ClusterNetworkLifecycleReason{*clusterNetworkLifecycleReasonModel} + model.LifecycleState = core.StringPtr("stable") + model.Name = core.StringPtr("my-cluster-network") + model.Profile = clusterNetworkProfileReferenceModel + model.ResourceGroup = resourceGroupReferenceModel + model.ResourceType = core.StringPtr("cluster_network") + model.SubnetPrefixes = []vpcv1.ClusterNetworkSubnetPrefix{*clusterNetworkSubnetPrefixModel} + model.VPC = vpcReferenceModel + model.Zone = zoneReferenceModel + + result, err := vpc.DataSourceIBMIsClusterNetworksClusterNetworkToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksClusterNetworkLifecycleReasonToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["code"] = "resource_suspended_by_provider" + model["message"] = "The resource has been suspended. Contact IBM support with the CRN for next steps." + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#resource-suspension" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkLifecycleReason) + model.Code = core.StringPtr("resource_suspended_by_provider") + model.Message = core.StringPtr("The resource has been suspended. Contact IBM support with the CRN for next steps.") + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#resource-suspension") + + result, err := vpc.DataSourceIBMIsClusterNetworksClusterNetworkLifecycleReasonToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksClusterNetworkProfileReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100" + model["name"] = "h100" + model["resource_type"] = "cluster_network_profile" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkProfileReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/cluster_network/profiles/h100") + model.Name = core.StringPtr("h100") + model.ResourceType = core.StringPtr("cluster_network_profile") + + result, err := vpc.DataSourceIBMIsClusterNetworksClusterNetworkProfileReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksResourceGroupReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345" + model["id"] = "fee82deba12e4c0fb69c3b09d1f12345" + model["name"] = "my-resource-group" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ResourceGroupReference) + model.Href = core.StringPtr("https://resource-controller.cloud.ibm.com/v2/resource_groups/fee82deba12e4c0fb69c3b09d1f12345") + model.ID = core.StringPtr("fee82deba12e4c0fb69c3b09d1f12345") + model.Name = core.StringPtr("my-resource-group") + + result, err := vpc.DataSourceIBMIsClusterNetworksResourceGroupReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksClusterNetworkSubnetPrefixToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["allocation_policy"] = "auto" + model["cidr"] = "10.0.0.0/24" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ClusterNetworkSubnetPrefix) + model.AllocationPolicy = core.StringPtr("auto") + model.CIDR = core.StringPtr("10.0.0.0/24") + + result, err := vpc.DataSourceIBMIsClusterNetworksClusterNetworkSubnetPrefixToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksVPCReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + deletedModel := make(map[string]interface{}) + deletedModel["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + model := make(map[string]interface{}) + model["crn"] = "crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["deleted"] = []map[string]interface{}{deletedModel} + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["id"] = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + model["name"] = "my-vpc" + model["resource_type"] = "vpc" + + assert.Equal(t, result, model) + } + + deletedModel := new(vpcv1.Deleted) + deletedModel.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + model := new(vpcv1.VPCReference) + model.CRN = core.StringPtr("crn:v1:bluemix:public:is:us-south:a/aa2432b1fa4d4ace891e9b80fc104e34::vpc:r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Deleted = deletedModel + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/vpcs/r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.ID = core.StringPtr("r006-4727d842-f94f-4a2d-824a-9bc9b02c523b") + model.Name = core.StringPtr("my-vpc") + model.ResourceType = core.StringPtr("vpc") + + result, err := vpc.DataSourceIBMIsClusterNetworksVPCReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksDeletedToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["more_info"] = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.Deleted) + model.MoreInfo = core.StringPtr("https://cloud.ibm.com/apidocs/vpc#deleted-resources") + + result, err := vpc.DataSourceIBMIsClusterNetworksDeletedToMap(model) + assert.Nil(t, err) + checkResult(result) +} + +func TestDataSourceIBMIsClusterNetworksZoneReferenceToMap(t *testing.T) { + checkResult := func(result map[string]interface{}) { + model := make(map[string]interface{}) + model["href"] = "https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1" + model["name"] = "us-south-1" + + assert.Equal(t, result, model) + } + + model := new(vpcv1.ZoneReference) + model.Href = core.StringPtr("https://us-south.iaas.cloud.ibm.com/v1/regions/us-south/zones/us-south-1") + model.Name = core.StringPtr("us-south-1") + + result, err := vpc.DataSourceIBMIsClusterNetworksZoneReferenceToMap(model) + assert.Nil(t, err) + checkResult(result) +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance.go b/ibm/service/vpc/data_source_ibm_is_instance.go index cbae0937a4..9de35b62af 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance.go +++ b/ibm/service/vpc/data_source_ibm_is_instance.go @@ -17,6 +17,7 @@ import ( "strings" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/vpc-go-sdk/vpcv1" "github.com/ScaleFT/sshkeys" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -62,6 +63,84 @@ func DataSourceIBMISInstance() *schema.Resource { Required: true, Description: "Instance name", }, + // cluster changes + "cluster_network": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, the cluster network that this virtual server instance resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "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 cluster network.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -1263,6 +1342,32 @@ func instanceGetByName(d *schema.ResourceData, meta interface{}, name string) er d.SetId(*instance.ID) id := *instance.ID + // cluster changes + + if !core.IsNil(instance.ClusterNetwork) { + clusterNetwork := []map[string]interface{}{} + clusterNetworkMap, err := DataSourceIBMIsInstanceClusterNetworkReferenceToMap(instance.ClusterNetwork) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance", "read", "cluster_network-to-map") + } + clusterNetwork = append(clusterNetwork, clusterNetworkMap) + if err = d.Set("cluster_network", clusterNetwork); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network: %s", err), "(Data) ibm_is_instance", "read", "set-cluster_network") + } + } + + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := DataSourceIBMIsInstanceInstanceClusterNetworkAttachmentReferenceToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance", "read", "cluster_network_attachments-to-map") + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + if err = d.Set("cluster_network_attachments", clusterNetworkAttachments); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_attachments: %s", err), "(Data) ibm_is_instance", "read", "set-cluster_network_attachments") + } + // catalog if instance.CatalogOffering != nil { versionCrn := *instance.CatalogOffering.Version.CRN @@ -1927,3 +2032,33 @@ func dataSourceIBMIsInstanceReservedIPReferenceDeletedToMap(model *vpcv1.Deleted modelMap["more_info"] = model.MoreInfo return modelMap, nil } +func DataSourceIBMIsInstanceClusterNetworkReferenceToMap(model *vpcv1.ClusterNetworkReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceInstanceClusterNetworkAttachmentReferenceToMap(model *vpcv1.InstanceClusterNetworkAttachmentReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} +func DataSourceIBMIsInstanceDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment.go b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment.go new file mode 100644 index 0000000000..0bfe21e2d1 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment.go @@ -0,0 +1,402 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsInstanceClusterNetworkAttachment() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsInstanceClusterNetworkAttachmentRead, + + Schema: map[string]*schema.Schema{ + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The virtual server instance identifier.", + }, + "instance_cluster_network_attachment_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The instance cluster network attachment identifier.", + }, + "before": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network interface for this instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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 cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + } +} + +func dataSourceIBMIsInstanceClusterNetworkAttachmentRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachment", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getInstanceClusterNetworkAttachmentOptions := &vpcv1.GetInstanceClusterNetworkAttachmentOptions{} + + getInstanceClusterNetworkAttachmentOptions.SetInstanceID(d.Get("instance_id").(string)) + getInstanceClusterNetworkAttachmentOptions.SetID(d.Get("instance_cluster_network_attachment_id").(string)) + + instanceClusterNetworkAttachment, _, err := vpcClient.GetInstanceClusterNetworkAttachmentWithContext(context, getInstanceClusterNetworkAttachmentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetInstanceClusterNetworkAttachmentWithContext failed: %s", err.Error()), "(Data) ibm_is_instance_cluster_network_attachment", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *getInstanceClusterNetworkAttachmentOptions.InstanceID, *getInstanceClusterNetworkAttachmentOptions.ID)) + + if !core.IsNil(instanceClusterNetworkAttachment.Before) { + before := []map[string]interface{}{} + beforeMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentBeforeToMap(instanceClusterNetworkAttachment.Before) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachment", "read", "before-to-map").GetDiag() + } + before = append(before, beforeMap) + if err = d.Set("before", before); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting before: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-before").GetDiag() + } + } + + clusterNetworkInterface := []map[string]interface{}{} + clusterNetworkInterfaceMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkInterfaceReferenceToMap(instanceClusterNetworkAttachment.ClusterNetworkInterface) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachment", "read", "cluster_network_interface-to-map").GetDiag() + } + clusterNetworkInterface = append(clusterNetworkInterface, clusterNetworkInterfaceMap) + if err = d.Set("cluster_network_interface", clusterNetworkInterface); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_interface: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-cluster_network_interface").GetDiag() + } + + if err = d.Set("href", instanceClusterNetworkAttachment.Href); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-href").GetDiag() + } + + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range instanceClusterNetworkAttachment.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachment", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_reasons: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-lifecycle_reasons").GetDiag() + } + + if err = d.Set("lifecycle_state", instanceClusterNetworkAttachment.LifecycleState); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting lifecycle_state: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-lifecycle_state").GetDiag() + } + + if err = d.Set("name", instanceClusterNetworkAttachment.Name); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting name: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-name").GetDiag() + } + + if err = d.Set("resource_type", instanceClusterNetworkAttachment.ResourceType); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting resource_type: %s", err), "(Data) ibm_is_instance_cluster_network_attachment", "read", "set-resource_type").GetDiag() + } + + return nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentBeforeToMap(model *vpcv1.InstanceClusterNetworkAttachmentBefore) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkInterfaceReferenceToMap(model *vpcv1.ClusterNetworkInterfaceReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + primaryIPMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReservedIPReferenceToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + modelMap["resource_type"] = *model.ResourceType + subnetMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReferenceToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentLifecycleReasonToMap(model *vpcv1.InstanceClusterNetworkAttachmentLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment_test.go b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment_test.go new file mode 100644 index 0000000000..d832370b86 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachment_test.go @@ -0,0 +1,123 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMIsInstanceClusterNetworkAttachmentDataSourceBasic(t *testing.T) { + instanceClusterNetworkAttachmentInstanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentDataSourceConfigBasic(instanceClusterNetworkAttachmentInstanceID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_cluster_network_attachment_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "resource_type"), + ), + }, + }, + }) +} + +func TestAccIBMIsInstanceClusterNetworkAttachmentDataSourceAllArgs(t *testing.T) { + instanceClusterNetworkAttachmentInstanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + instanceClusterNetworkAttachmentName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentDataSourceConfig(instanceClusterNetworkAttachmentInstanceID, instanceClusterNetworkAttachmentName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_cluster_network_attachment_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "before.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "cluster_network_interface.0.subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentDataSourceConfigBasic(instanceClusterNetworkAttachmentInstanceID string) string { + return fmt.Sprintf(` + resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = "%s" + cluster_network_interface { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + id = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + name = "my-cluster-network-interface" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + resource_type = "cluster_network_interface" + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + } + + data "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_id + instance_cluster_network_attachment_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_cluster_network_attachment_id + } + `, instanceClusterNetworkAttachmentInstanceID) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentDataSourceConfig(instanceClusterNetworkAttachmentInstanceID string, instanceClusterNetworkAttachmentName string) string { + return fmt.Sprintf(` + data "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = "02c7_a8850825-23f1-43f5-92cc-8e97b1c86313" + instance_cluster_network_attachment_id = "02c7-3750a5b5-3efb-46c4-a34e-21f512d99c9d" + } + `) +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments.go b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments.go new file mode 100644 index 0000000000..a90de62693 --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments.go @@ -0,0 +1,417 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func DataSourceIBMIsInstanceClusterNetworkAttachments() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceIBMIsInstanceClusterNetworkAttachmentsRead, + + Schema: map[string]*schema.Schema{ + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The virtual server instance identifier.", + }, + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A page of ordered cluster network attachments (sorted based on the `before` property) for the instance. A cluster network attachment represents a device to which a cluster network interface is attached.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "before": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network interface for this instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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 cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + }, + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMIsInstanceClusterNetworkAttachmentsRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachments", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + listInstanceClusterNetworkAttachmentsOptions := &vpcv1.ListInstanceClusterNetworkAttachmentsOptions{} + + listInstanceClusterNetworkAttachmentsOptions.SetInstanceID(d.Get("instance_id").(string)) + + var pager *vpcv1.InstanceClusterNetworkAttachmentsPager + pager, err = vpcClient.NewInstanceClusterNetworkAttachmentsPager(listInstanceClusterNetworkAttachmentsOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachments", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + allItems, err := pager.GetAll() + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("InstanceClusterNetworkAttachmentsPager.GetAll() failed %s", err), "(Data) ibm_is_instance_cluster_network_attachments", "read") + log.Printf("[DEBUG] %s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(dataSourceIBMIsInstanceClusterNetworkAttachmentsID(d)) + + mapSlice := []map[string]interface{}{} + for _, modelItem := range allItems { + modelMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentToMap(&modelItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_cluster_network_attachments", "read", "Instances-to-map").GetDiag() + } + mapSlice = append(mapSlice, modelMap) + } + + if err = d.Set("cluster_network_attachments", mapSlice); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_attachments %s", err), "(Data) ibm_is_instance_cluster_network_attachments", "read", "cluster_network_attachments-set").GetDiag() + } + + return nil +} + +// dataSourceIBMIsInstanceClusterNetworkAttachmentsID returns a reasonable ID for the list. +func dataSourceIBMIsInstanceClusterNetworkAttachmentsID(d *schema.ResourceData) string { + return time.Now().UTC().String() +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentToMap(model *vpcv1.InstanceClusterNetworkAttachment) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Before != nil { + beforeMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentBeforeToMap(model.Before) + if err != nil { + return modelMap, err + } + modelMap["before"] = []map[string]interface{}{beforeMap} + } + clusterNetworkInterfaceMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkInterfaceReferenceToMap(model.ClusterNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["cluster_network_interface"] = []map[string]interface{}{clusterNetworkInterfaceMap} + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range model.LifecycleReasons { + lifecycleReasonsItemMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return modelMap, err + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + modelMap["lifecycle_reasons"] = lifecycleReasons + modelMap["lifecycle_state"] = *model.LifecycleState + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentBeforeToMap(model *vpcv1.InstanceClusterNetworkAttachmentBefore) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkInterfaceReferenceToMap(model *vpcv1.ClusterNetworkInterfaceReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsDeletedToMap(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 + primaryIPMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkSubnetReservedIPReferenceToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + modelMap["resource_type"] = *model.ResourceType + subnetMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkSubnetReferenceToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstanceClusterNetworkAttachmentsDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceClusterNetworkAttachmentsInstanceClusterNetworkAttachmentLifecycleReasonToMap(model *vpcv1.InstanceClusterNetworkAttachmentLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments_test.go b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments_test.go new file mode 100644 index 0000000000..7928e038ce --- /dev/null +++ b/ibm/service/vpc/data_source_ibm_is_instance_cluster_network_attachments_test.go @@ -0,0 +1,114 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" +) + +func TestAccIBMIsInstanceClusterNetworkAttachmentsDataSourceBasic(t *testing.T) { + instanceClusterNetworkAttachmentInstanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentsDataSourceConfigBasic(instanceClusterNetworkAttachmentInstanceID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.#"), + ), + }, + }, + }) +} + +func TestAccIBMIsInstanceClusterNetworkAttachmentsDataSourceAllArgs(t *testing.T) { + instanceClusterNetworkAttachmentInstanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + instanceClusterNetworkAttachmentName := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentsDataSourceConfig(instanceClusterNetworkAttachmentInstanceID, instanceClusterNetworkAttachmentName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "instance_id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.primary_ip.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.cluster_network_interface.0.subnet.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_cluster_network_attachments.is_instance_cluster_network_attachments_instance", "cluster_network_attachments.0.resource_type"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentsDataSourceConfigBasic(instanceClusterNetworkAttachmentInstanceID string) string { + return fmt.Sprintf(` + resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = "%s" + cluster_network_interface { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + id = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + name = "my-cluster-network-interface" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + resource_type = "cluster_network_interface" + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + } + + data "ibm_is_instance_cluster_network_attachments" "is_instance_cluster_network_attachments_instance" { + instance_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_id + } + `, instanceClusterNetworkAttachmentInstanceID) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentsDataSourceConfig(instanceClusterNetworkAttachmentInstanceID string, instanceClusterNetworkAttachmentName string) string { + return fmt.Sprintf(` + data "ibm_is_instance_cluster_network_attachments" "is_instance_cluster_network_attachments_instance" { + instance_id = "02c7_a8850825-23f1-43f5-92cc-8e97b1c86313" + } + `) +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profile.go b/ibm/service/vpc/data_source_ibm_is_instance_profile.go index 8dcafcc12a..741e27d93b 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profile.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profile.go @@ -6,6 +6,7 @@ package vpc import ( "fmt" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/vpc-go-sdk/vpcv1" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -29,6 +30,72 @@ func DataSourceIBMISInstanceProfile() *schema.Resource { Required: true, }, + // cluster changes + "cluster_network_attachment_count": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + + "supported_cluster_network_profiles": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network profiles that support this instance profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "confidential_compute_modes": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -766,6 +833,29 @@ func instanceProfileGet(d *schema.ResourceData, meta interface{}, name string) e d.Set("status", profile.Status) } + // cluster changes + clusterNetworkAttachmentCount := []map[string]interface{}{} + clusterNetworkAttachmentCountMap, err := DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountToMap(profile.ClusterNetworkAttachmentCount) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_profile", "read", "cluster_network_attachment_count-to-map") + } + clusterNetworkAttachmentCount = append(clusterNetworkAttachmentCount, clusterNetworkAttachmentCountMap) + if err = d.Set("cluster_network_attachment_count", clusterNetworkAttachmentCount); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_attachment_count: %s", err), "(Data) ibm_is_instance_profile", "read", "set-cluster_network_attachment_count") + } + + supportedClusterNetworkProfiles := []map[string]interface{}{} + for _, supportedClusterNetworkProfilesItem := range profile.SupportedClusterNetworkProfiles { + supportedClusterNetworkProfilesItemMap, err := DataSourceIBMIsInstanceProfileClusterNetworkProfileReferenceToMap(&supportedClusterNetworkProfilesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_profile", "read", "supported_cluster_network_profiles-to-map") + } + supportedClusterNetworkProfiles = append(supportedClusterNetworkProfiles, supportedClusterNetworkProfilesItemMap) + } + if err = d.Set("supported_cluster_network_profiles", supportedClusterNetworkProfiles); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting supported_cluster_network_profiles: %s", err), "(Data) ibm_is_instance_profile", "read", "set-supported_cluster_network_profiles") + } + confidentialComputeModes := []map[string]interface{}{} if profile.ConfidentialComputeModes != nil { modelMap, err := dataSourceIBMIsInstanceProfileInstanceProfileSupportedConfidentialComputeModesToMap(profile.ConfidentialComputeModes) @@ -1432,3 +1522,76 @@ func dataSourceIBMIsInstanceProfileInstanceProfileSupportedConfidentialComputeMo modelMap["values"] = model.Values return modelMap, nil } + +func DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountToMap(model vpcv1.InstanceProfileClusterNetworkAttachmentCountIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent); ok { + return DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountDependentToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum); ok { + return DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountEnumToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountRange); ok { + return DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountRangeToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountRange)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCount); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCount) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceProfileClusterNetworkAttachmentCountIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountDependentToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountEnumToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfileInstanceProfileClusterNetworkAttachmentCountRangeToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfileClusterNetworkProfileReferenceToMap(model *vpcv1.ClusterNetworkProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go b/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go index 416b6d8e64..a43c45e14b 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profile_test.go @@ -46,6 +46,47 @@ func TestAccIBMISInstanceProfileDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISInstanceProfileDataSource_cluster(t *testing.T) { + resName := "data.ibm_is_instance_profile.test1" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceProfileDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resName, "name", acc.InstanceProfileName), + resource.TestCheckResourceAttrSet(resName, "family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "bandwidth.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "cluster_network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "cluster_network_attachment_count.0.values.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "confidential_compute_modes.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "disks.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "memory.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "network_interface_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "port_speed.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "reservation_terms.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "secure_boot_modes.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "supported_cluster_network_profiles.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "supported_cluster_network_profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "supported_cluster_network_profiles.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "supported_cluster_network_profiles.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "total_volume_bandwidth.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_architecture.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profile.test1", "vcpu_manufacturer.#"), + ), + }, + }, + }) +} func TestAccIBMISInstanceProfileDataSource_concom(t *testing.T) { resName := "data.ibm_is_instance_profile.test1" diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profiles.go b/ibm/service/vpc/data_source_ibm_is_instance_profiles.go index 8fce1b1da1..d4d18ef1c2 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profiles.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profiles.go @@ -7,6 +7,7 @@ import ( "fmt" "time" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/vpc-go-sdk/vpcv1" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -36,6 +37,71 @@ func DataSourceIBMISInstanceProfiles() *schema.Resource { Computed: true, Description: "The product family this virtual server instance profile belongs to.", }, + + // cluster changes + "cluster_network_attachment_count": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "supported_cluster_network_profiles": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network profiles that support this instance profile.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network profile.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "confidential_compute_modes": &schema.Schema{ Type: schema.TypeList, Computed: true, @@ -771,6 +837,24 @@ func instanceProfilesList(d *schema.ResourceData, meta interface{}) error { l["bandwidth"] = bandwidthList } + // cluster changes + + supportedClusterNetworkProfiles := []map[string]interface{}{} + for _, supportedClusterNetworkProfilesItem := range profile.SupportedClusterNetworkProfiles { + supportedClusterNetworkProfilesItemMap, err := DataSourceIBMIsInstanceProfilesClusterNetworkProfileReferenceToMap(&supportedClusterNetworkProfilesItem) // #nosec G601 + if err != nil { + return err + } + supportedClusterNetworkProfiles = append(supportedClusterNetworkProfiles, supportedClusterNetworkProfilesItemMap) + } + l["supported_cluster_network_profiles"] = supportedClusterNetworkProfiles + + clusterNetworkAttachmentCountMap, err := DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountToMap(profile.ClusterNetworkAttachmentCount) + if err != nil { + return err + } + l["cluster_network_attachment_count"] = []map[string]interface{}{clusterNetworkAttachmentCountMap} + if profile.GpuCount != nil { l["gpu_count"] = dataSourceInstanceProfileFlattenGPUCount(*profile.GpuCount.(*vpcv1.InstanceProfileGpu)) } @@ -893,3 +977,76 @@ func instanceProfilesList(d *schema.ResourceData, meta interface{}) error { func dataSourceIBMISInstanceProfilesID(d *schema.ResourceData) string { return time.Now().UTC().String() } + +func DataSourceIBMIsInstanceProfilesClusterNetworkProfileReferenceToMap(model *vpcv1.ClusterNetworkProfileReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountToMap(model vpcv1.InstanceProfileClusterNetworkAttachmentCountIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent); ok { + return DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountDependentToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum); ok { + return DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountEnumToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountRange); ok { + return DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountRangeToMap(model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCountRange)) + } else if _, ok := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCount); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceProfileClusterNetworkAttachmentCount) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceProfileClusterNetworkAttachmentCountIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountDependentToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountDependent) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountEnumToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsInstanceProfilesInstanceProfileClusterNetworkAttachmentCountRangeToMap(model *vpcv1.InstanceProfileClusterNetworkAttachmentCountRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + modelMap["type"] = *model.Type + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go b/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go index f14b6e9222..0bea56e11e 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_profiles_test.go @@ -47,6 +47,44 @@ func TestAccIBMISInstanceProfilesDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISInstanceProfilesDataSource_cluster(t *testing.T) { + resName := "data.ibm_is_instance_profiles.test1" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceProfilesDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "profiles.0.name"), + resource.TestCheckResourceAttrSet(resName, "profiles.0.family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.bandwidth.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.family"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.memory.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.architecture"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.port_speed.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_architecture.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_interface_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_interface_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.network_attachment_count.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.vcpu_manufacturer.0.value"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.0.type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.reservation_terms.0.values.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.cluster_network_attachment_count.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.cluster_network_attachment_count.0.values.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance_profiles.test1", "profiles.0.supported_cluster_network_profiles.#"), + ), + }, + }, + }) +} func TestAccIBMISInstanceProfilesDataSource_concom(t *testing.T) { resName := "data.ibm_is_instance_profiles.test1" diff --git a/ibm/service/vpc/data_source_ibm_is_instance_template.go b/ibm/service/vpc/data_source_ibm_is_instance_template.go index ff34bfbc8d..ffa5b16e8d 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_template.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_template.go @@ -5,12 +5,14 @@ package vpc import ( "context" + "encoding/json" "fmt" "log" "reflect" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/vpc-go-sdk/vpcv1" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -75,6 +77,104 @@ func DataSourceIBMISInstanceTemplate() *schema.Resource { Computed: true, ExactlyOneOf: []string{"identifier", isInstanceTemplateName}, }, + + // cluster changes + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + }, + }, + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + }, + }, + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed.", + }, + }, + }, + }, "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -821,6 +921,14 @@ func DataSourceIBMISInstanceTemplate() *schema.Resource { } } +func prettifyResponse(response interface{}) string { + output, err := json.MarshalIndent(response, "", " ") + if err == nil { + return fmt.Sprintf("%+v\n", string(output)) + } + return fmt.Sprintf("Error : %#v", response) +} + func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { instanceC, err := meta.(conns.ClientSession).VpcV1API() if err != nil { @@ -895,6 +1003,21 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso } } + // cluster changes + if !core.IsNil(instance.ClusterNetworkAttachments) { + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_template", "read", "cluster_network_attachments-to-map").GetDiag() + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + if err = d.Set("cluster_network_attachments", clusterNetworkAttachments); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_attachments: %s", err), "(Data) ibm_is_instance_template", "read", "set-cluster_network_attachments").GetDiag() + } + } + // catalog offering if any if instance.CatalogOffering != nil { catOfferingList := make([]map[string]interface{}, 0) @@ -1205,6 +1328,21 @@ func dataSourceIBMISInstanceTemplateRead(context context.Context, d *schema.Reso if err = d.Set("enable_secure_boot", instance.EnableSecureBoot); err != nil { return diag.FromErr(fmt.Errorf("[ERROR] Error setting enable_secure_boot: %s", err)) } + // cluster changes + if !core.IsNil(instance.ClusterNetworkAttachments) { + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_instance_template", "read", "cluster_network_attachments-to-map").GetDiag() + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + if err = d.Set("cluster_network_attachments", clusterNetworkAttachments); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting cluster_network_attachments: %s", err), "(Data) ibm_is_instance_template", "read", "set-cluster_network_attachments").GetDiag() + } + } + // catalog offering if any if instance.CatalogOffering != nil { catOfferingList := make([]map[string]interface{}, 0) @@ -2175,3 +2313,220 @@ func dataSourceIBMIsInstanceTemplateInstanceCatalogOfferingPrototypeCatalogOffer modelMap["version"] = []map[string]interface{}{versionMap} return modelMap, nil } + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + clusterNetworkInterfaceMap, err := DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model.ClusterNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["cluster_network_interface"] = []map[string]interface{}{clusterNetworkInterfaceMap} + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment); ok { + return DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + return DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model vpcv1.ClusterNetworkSubnetIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByID); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByIDToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByHref); ok { + return DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByHrefToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetIdentityIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByIDToMap(model *vpcv1.ClusterNetworkSubnetIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByHrefToMap(model *vpcv1.ClusterNetworkSubnetIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := DataSourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := DataSourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID); ok { + return DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref); ok { + return DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_template_test.go b/ibm/service/vpc/data_source_ibm_is_instance_template_test.go index d1f560f3ba..4846a776d0 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_template_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_template_test.go @@ -40,6 +40,61 @@ func TestAccIBMISInstanceTemplate_dataBasic(t *testing.T) { }, }) } +func TestAccIBMISInstanceTemplateDatasourceCluster(t *testing.T) { + randInt := acctest.RandIntRange(600, 700) + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQ+WiiUR1Jg3oGSmB/2//GJ3XnotriBiGN6t3iwGces6sUsvRkza1t0Mf05DKZxC/zp0WvDTvbit2gTkF9sD37OZSn5aCJk1F5URk/JNPmz25ZogkICFL4OUfhrE3mnyKio6Bk1JIEIypR5PRtGxY9vFDUfruADDLfRi+dGwHF6U9RpvrDRo3FNtI8T0GwvWwFE7bg63vLz65CjYY5XqH9z/YWz/asH6BKumkwiphLGhuGn03+DV6DkIZqr3Oh13UDjMnTdgv1y/Kou5UM3CK1dVsmLRXPEf2KUWUq1EwRfrJXkPOrBwn8to+Yydo57FgrRM9Qw8uzvKmnVxfKW6iG3oSGA0L6ROuCq1lq0MD8ySLd56+d1ftSDaUq+0/Yt9vK3olzVP0/iZobD7chbGqTLMCzL4/CaIUR/UmX08EA0Oh0DdyAdj3UUNETAj3W8gBrV6xLR7fZAJ8roX2BKb4K8Ed3YqzgiY0zgjqvpBYl9xZl0jgVX0qMFaEa6+CeGI8= root@ffd8363b1226 + `) + vpcName := fmt.Sprintf("testvpc%d", randInt) + subnetName := fmt.Sprintf("testsubnet%d", randInt) + // templateName := fmt.Sprintf("testtemplate%d", randInt) + templateName := "eu-de-test-cluster-it" + sshKeyName := fmt.Sprintf("testsshkey%d", randInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplateDatasourceClusterConfig(vpcName, subnetName, sshKeyName, publicKey, templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.ibm_is_instance_template.instance_template_data_name", "name", templateName), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "boot_volume_attachment.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "cluster_network_attachments.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "cluster_network_attachments.0.cluster_network_interface.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "crn"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "enable_secure_boot"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "id"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "image"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "keys.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "name"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "network_attachments.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "primary_network_attachment.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "profile"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "resource_group"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "vpc"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_template.instance_template_data_name", "zone"), + ), + }, + }, + }) +} func TestAccIBMISInstanceTemplate_dataconcom(t *testing.T) { randInt := acctest.RandIntRange(600, 700) publicKey := strings.TrimSpace(` @@ -192,6 +247,16 @@ func testAccCheckIBMISInstanceTemplateDConfig(vpcName, subnetName, sshKeyName, p } `) } +func testAccCheckIBMISInstanceTemplateDatasourceClusterConfig(vpcName, subnetName, sshKeyName, publicKey, templateName string) string { + return fmt.Sprintf(` + data "ibm_is_instance_template" "instance_template_data_name" { + name = "eu-de-test-cluster-it" + } + data "ibm_is_instance_template" "instance_template_data_identifier" { + identifier = "02c7-4a2d29da-429a-4355-9354-31af7c2e6627" + } + `) +} func testAccCheckIBMISInstanceTemplateDconcomConfig(vpcName, subnetName, sshKeyName, publicKey, templateName, ccmode string, esb bool) string { return testAccCheckIBMISInstanceTemplateConComConfig(vpcName, subnetName, sshKeyName, publicKey, templateName, ccmode, esb) + fmt.Sprintf(` data "ibm_is_instance_template" "instance_template_data" { diff --git a/ibm/service/vpc/data_source_ibm_is_instance_templates.go b/ibm/service/vpc/data_source_ibm_is_instance_templates.go index e2cfe87374..890c3df1e6 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_templates.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_templates.go @@ -4,6 +4,7 @@ package vpc import ( + "fmt" "reflect" "time" @@ -97,6 +98,103 @@ func DataSourceIBMISInstanceTemplates() *schema.Resource { Type: schema.TypeString, Computed: true, }, + // cluster changes + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + }, + }, + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + }, + }, + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed.", + }, + }, + }, + }, "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -925,7 +1023,17 @@ func dataSourceIBMISInstanceTemplatesRead(d *schema.ResourceData, meta interface } template["confidential_compute_mode"] = instance.ConfidentialComputeMode - + if instance.ClusterNetworkAttachments != nil { + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + template["cluster_network_attachments"] = clusterNetworkAttachments + } template["enable_secure_boot"] = instance.EnableSecureBoot if instance.MetadataService != nil { @@ -1232,3 +1340,220 @@ func dataSourceInstanceTemplateCollectionTemplatesPlacementTargetToMap(placement return placementTargetMap } + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + clusterNetworkInterfaceMap, err := DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model.ClusterNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["cluster_network_interface"] = []map[string]interface{}{clusterNetworkInterfaceMap} + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment); ok { + return DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + return DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityToMap(model vpcv1.ClusterNetworkSubnetIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByID); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityByIDToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByHref); ok { + return DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityByHrefToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetIdentityIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityByIDToMap(model *vpcv1.ClusterNetworkSubnetIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityByHrefToMap(model *vpcv1.ClusterNetworkSubnetIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := DataSourceIBMIsInstanceTemplatesClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := DataSourceIBMIsInstanceTemplatesClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID); ok { + return DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref); ok { + return DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf subtype encountered") + } +} + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func DataSourceIBMIsInstanceTemplatesInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go b/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go index 12526dd29a..567e44a7c9 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_templates_test.go @@ -40,6 +40,60 @@ func TestAccIBMISInstanceTemplates_dataBasic(t *testing.T) { }, }) } +func TestAccIBMISInstanceTemplatesDataSourceCluster(t *testing.T) { + randInt := acctest.RandIntRange(600, 700) + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQ+WiiUR1Jg3oGSmB/2//GJ3XnotriBiGN6t3iwGces6sUsvRkza1t0Mf05DKZxC/zp0WvDTvbit2gTkF9sD37OZSn5aCJk1F5URk/JNPmz25ZogkICFL4OUfhrE3mnyKio6Bk1JIEIypR5PRtGxY9vFDUfruADDLfRi+dGwHF6U9RpvrDRo3FNtI8T0GwvWwFE7bg63vLz65CjYY5XqH9z/YWz/asH6BKumkwiphLGhuGn03+DV6DkIZqr3Oh13UDjMnTdgv1y/Kou5UM3CK1dVsmLRXPEf2KUWUq1EwRfrJXkPOrBwn8to+Yydo57FgrRM9Qw8uzvKmnVxfKW6iG3oSGA0L6ROuCq1lq0MD8ySLd56+d1ftSDaUq+0/Yt9vK3olzVP0/iZobD7chbGqTLMCzL4/CaIUR/UmX08EA0Oh0DdyAdj3UUNETAj3W8gBrV6xLR7fZAJ8roX2BKb4K8Ed3YqzgiY0zgjqvpBYl9xZl0jgVX0qMFaEa6+CeGI8= root@ffd8363b1226 + `) + vpcName := fmt.Sprintf("testvpc%d", randInt) + subnetName := fmt.Sprintf("testsubnet%d", randInt) + templateName := fmt.Sprintf("testtemplate%d", randInt) + sshKeyName := fmt.Sprintf("testsshkey%d", randInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplatesDatasourceClusterConfig(vpcName, subnetName, sshKeyName, publicKey, templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "id"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.boot_volume_attachment.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.cluster_network_attachments.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.cluster_network_attachments.0.cluster_network_interface.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.crn"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.enable_secure_boot"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.id"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.image"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.keys.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.name"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.network_attachments.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.primary_network_attachment.#"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.profile"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.resource_group"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.vpc"), + resource.TestCheckResourceAttrSet( + "data.ibm_is_instance_templates.instance_templates_data", "templates.0.zone"), + ), + }, + }, + }) +} func TestAccIBMISInstanceTemplates_dataconcom(t *testing.T) { randInt := acctest.RandIntRange(600, 700) publicKey := strings.TrimSpace(` @@ -169,6 +223,12 @@ func testAccCheckIBMISInstanceTemplatesDConfig(vpcName, subnetName, sshKeyName, } `) } +func testAccCheckIBMISInstanceTemplatesDatasourceClusterConfig(vpcName, subnetName, sshKeyName, publicKey, templateName string) string { + return fmt.Sprintf(` + data "ibm_is_instance_templates" "instance_templates_data" { + } + `) +} func testAccCheckIBMISInstanceTemplatesDconcomConfig(vpcName, subnetName, sshKeyName, publicKey, templateName, ccmode string, esb bool) string { return testAccCheckIBMISInstanceTemplateConComConfig(vpcName, subnetName, sshKeyName, publicKey, templateName, ccmode, esb) + fmt.Sprintf(` diff --git a/ibm/service/vpc/data_source_ibm_is_instance_test.go b/ibm/service/vpc/data_source_ibm_is_instance_test.go index 325f292f73..0355b59432 100644 --- a/ibm/service/vpc/data_source_ibm_is_instance_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instance_test.go @@ -50,6 +50,77 @@ func TestAccIBMISInstanceDataSource_basic(t *testing.T) { }, }) } +func TestAccIBMISInstanceDS_BasicCluster(t *testing.T) { + + vpcname := fmt.Sprintf("tfins-vpc-%d", acctest.RandIntRange(10, 100)) + subnetname := fmt.Sprintf("tfins-subnet-%d", acctest.RandIntRange(10, 100)) + sshname := fmt.Sprintf("tfins-ssh-%d", acctest.RandIntRange(10, 100)) + // instanceName := fmt.Sprintf("tfins-name-%d", acctest.RandIntRange(10, 100)) + instanceName := "eu-de-test-cluster-ins" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceDataSourceClusterConfig(vpcname, subnetname, sshname, instanceName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "access_tags.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "availability_policy_host_failure"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "bandwidth"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "boot_volume.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.0.resource_type"), + resource.TestCheckResourceAttr("data.ibm_is_instance.is_instance_instance", "name", instanceName), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "cluster_network_attachments.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "confidential_compute_mode"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "crn"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.created_at"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.href"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.interface_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.resource_type"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "disks.0.size"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "enable_secure_boot"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "gpu.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "keys.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "keys.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "keys.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "image"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "lifecycle_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "memory"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "metadata_service.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "metadata_service_enabled"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "network_attachments.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "network_interfaces.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "primary_network_attachment.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "primary_network_interface.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "profile"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "reservation_affinity.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "resource_group"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "status"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "status_reasons.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "status_reasons.0.more_info"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "total_network_bandwidth"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "total_volume_bandwidth"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "vcpu.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "volume_attachments.#"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "volume_attachments.0.id"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "volume_attachments.0.name"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "vpc"), + resource.TestCheckResourceAttrSet("data.ibm_is_instance.is_instance_instance", "zone"), + ), + }, + }, + }) +} func TestAccIBMISInstanceDataSourceWithCatalogOffering(t *testing.T) { @@ -251,6 +322,12 @@ data "ibm_is_instance" "ds_instance" { passphrase = "" }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, instanceName, acc.IsWinImage, acc.InstanceProfileName, acc.ISZoneName) } +func testAccCheckIBMISInstanceDataSourceClusterConfig(vpcname, subnetname, sshname, instanceName string) string { + return fmt.Sprintf(` + data "ibm_is_instance" "is_instance_instance" { + name = "eu-de-test-cluster-ins" + }`) +} func testAccCheckIBMISInstanceDataSourceConfigWithCatalogOffering(vpcname, subnetname, sshname, instanceName, planCrn, versionCrn string) string { return fmt.Sprintf(` diff --git a/ibm/service/vpc/data_source_ibm_is_instances.go b/ibm/service/vpc/data_source_ibm_is_instances.go index 455b597aa3..29a1185aa9 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances.go +++ b/ibm/service/vpc/data_source_ibm_is_instances.go @@ -62,6 +62,23 @@ func DataSourceIBMISInstances() *schema.Resource { Description: "Instance resource group", }, + // cluster changes + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to instances with a `cluster_network.id` property matching the specified identifier.", + }, + "cluster_network_crn": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to instances with a `cluster_network.crn` property matching the specified CRN.", + }, + "cluster_network_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Filters the collection to resources with a `cluster_network.name` property matching the exact specified name.", + }, + "dedicated_host_name": { Type: schema.TypeString, Optional: true, @@ -111,6 +128,84 @@ func DataSourceIBMISInstances() *schema.Resource { Computed: true, Description: "The crn for this Instance", }, + // cluster changes + "cluster_network": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, the cluster network that this virtual server instance resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "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 cluster network.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -1261,6 +1356,17 @@ func instancesList(d *schema.ResourceData, meta interface{}) error { listInstancesOptions := &vpcv1.ListInstancesOptions{} + // cluster changes + if _, ok := d.GetOk("cluster_network_id"); ok { + listInstancesOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + } + if _, ok := d.GetOk("cluster_network_crn"); ok { + listInstancesOptions.SetClusterNetworkCRN(d.Get("cluster_network_crn").(string)) + } + if _, ok := d.GetOk("cluster_network_name"); ok { + listInstancesOptions.SetClusterNetworkName(d.Get("cluster_network_name").(string)) + } + if vpcName != "" { listInstancesOptions.VPCName = &vpcName } @@ -1418,6 +1524,23 @@ func instancesList(d *schema.ResourceData, meta interface{}) error { l[isInstanceCatalogOffering] = catalogList } + if instance.ClusterNetwork != nil { + clusterNetworkMap, err := DataSourceIBMIsInstancesClusterNetworkReferenceToMap(instance.ClusterNetwork) + if err != nil { + return err + } + l["cluster_network"] = []map[string]interface{}{clusterNetworkMap} + } + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := DataSourceIBMIsInstancesInstanceClusterNetworkAttachmentReferenceToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + l["cluster_network_attachments"] = clusterNetworkAttachments + if instance.BootVolumeAttachment != nil { bootVolList := make([]map[string]interface{}, 0) bootVol := map[string]interface{}{} @@ -1711,6 +1834,38 @@ func dataSourceIBMISInstancesID(d *schema.ResourceData) string { return time.Now().UTC().String() } +func DataSourceIBMIsInstancesClusterNetworkReferenceToMap(model *vpcv1.ClusterNetworkReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := DataSourceIBMIsInstancesDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstancesInstanceClusterNetworkAttachmentReferenceToMap(model *vpcv1.InstanceClusterNetworkAttachmentReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func DataSourceIBMIsInstancesDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + func dataSourceInstancesCollectionHealthReasonsToMap(statusReasonsItem vpcv1.InstanceHealthReason) (healthReasonsMap map[string]interface{}) { healthReasonsMap = map[string]interface{}{} diff --git a/ibm/service/vpc/data_source_ibm_is_instances_test.go b/ibm/service/vpc/data_source_ibm_is_instances_test.go index ef027ed2c9..b9cbbfe570 100644 --- a/ibm/service/vpc/data_source_ibm_is_instances_test.go +++ b/ibm/service/vpc/data_source_ibm_is_instances_test.go @@ -63,6 +63,62 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE }, }) } +func TestAccIBMISInstancesDS_basicCluster(t *testing.T) { + // var instance string + // vpcname := fmt.Sprintf("tfins-vpc-%d", acctest.RandIntRange(10, 100)) + // subnetname := fmt.Sprintf("tfins-subnet-%d", acctest.RandIntRange(10, 100)) + // publicKey := strings.TrimSpace(` + // ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR + // `) + // sshname := fmt.Sprintf("tfins-ssh-%d", acctest.RandIntRange(10, 100)) + // instanceName := fmt.Sprintf("tfins-name-%d", acctest.RandIntRange(10, 100)) + resName := "data.ibm_is_instances.ds_instances" + // userData := "a" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + Steps: []resource.TestStep{ + // { + // Config: testAccCheckIBMISInstanceConfig(vpcname, subnetname, sshname, publicKey, instanceName, userData), + // Check: resource.ComposeTestCheckFunc( + // testAccCheckIBMISInstanceExists("ibm_is_instance.testacc_instance", instance), + // resource.TestCheckResourceAttr( + // "ibm_is_instance.testacc_instance", "name", instanceName), + // resource.TestCheckResourceAttr( + // "ibm_is_instance.testacc_instance", "zone", acc.ISZoneName), + // ), + // }, + { + Config: testAccCheckIBMISInstancesDataSourceConfig(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resName, "instances.0.name"), + resource.TestCheckResourceAttrSet(resName, "instances.0.memory"), + resource.TestCheckResourceAttrSet(resName, "instances.0.status"), + resource.TestCheckResourceAttrSet(resName, "instances.0.resource_group"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vpc"), + resource.TestCheckResourceAttrSet(resName, "instances.0.boot_volume.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.volume_attachments.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.primary_network_interface.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.network_interfaces.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.profile"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vcpu.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.zone"), + resource.TestCheckResourceAttrSet(resName, "instances.0.availability_policy_host_failure"), + resource.TestCheckResourceAttrSet(resName, "instances.0.lifecycle_state"), + resource.TestCheckResourceAttr(resName, "instances.0.lifecycle_reasons.#", "0"), + resource.TestCheckResourceAttrSet(resName, "instances.0.vcpu.0.manufacturer"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.#"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.0.href"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.0.id"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.0.name"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.0.resource_type"), + resource.TestCheckResourceAttrSet(resName, "instances.0.cluster_network_attachments.0.resource_type"), + ), + }, + }, + }) +} func TestAccIBMISInstancesDataSourceWithCatalogOffering(t *testing.T) { vpcname := fmt.Sprintf("tfins-vpc-%d", acctest.RandIntRange(10, 100)) diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network.go b/ibm/service/vpc/resource_ibm_is_cluster_network.go new file mode 100644 index 0000000000..e475e73330 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network.go @@ -0,0 +1,549 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIBMIsClusterNetwork() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIsClusterNetworkCreate, + ReadContext: resourceIBMIsClusterNetworkRead, + UpdateContext: resourceIBMIsClusterNetworkUpdate, + DeleteContext: resourceIBMIsClusterNetworkDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network", "name"), + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "profile": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The globally unique name for this cluster network profile.", + }, + "resource_group": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "The unique identifier for this resource group for this cluster network.", + }, + "subnet_prefixes": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + // Default: [{"cidr":"10.0.0.0/9"}], + Description: "The IP address ranges available for subnets for this cluster network.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allocation_policy": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The allocation policy for this subnet prefix:- `auto`: Subnets created by total count in this cluster network can use this prefix.", + }, + "cidr": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The CIDR block for this prefix.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: "The VPC this cluster network resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The globally unique name for the zone this cluster network resides in.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network was created.", + }, + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceIBMIsClusterNetworkValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$`, + MinValueLength: 1, + MaxValueLength: 63, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_cluster_network", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIsClusterNetworkCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createClusterNetworkOptions := &vpcv1.CreateClusterNetworkOptions{} + + createClusterNetworkOptions.Profile = &vpcv1.ClusterNetworkProfileIdentity{ + Name: core.StringPtr(d.Get("profile").(string)), + } + vpcModel, err := ResourceIBMIsClusterNetworkMapToVPCIdentity(d.Get("vpc.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "create", "parse-vpc").GetDiag() + } + createClusterNetworkOptions.SetVPC(vpcModel) + createClusterNetworkOptions.Zone = &vpcv1.ZoneIdentity{ + Name: core.StringPtr(d.Get("zone").(string)), + } + if _, ok := d.GetOk("name"); ok { + createClusterNetworkOptions.SetName(d.Get("name").(string)) + } + if rgOk, ok := d.GetOk("resource_group"); ok { + + createClusterNetworkOptions.ResourceGroup = &vpcv1.ResourceGroupIdentity{ + ID: core.StringPtr(rgOk.(string)), + } + } + if _, ok := d.GetOk("subnet_prefixes"); ok { + var subnetPrefixes []vpcv1.ClusterNetworkSubnetPrefixPrototype + for _, v := range d.Get("subnet_prefixes").([]interface{}) { + value := v.(map[string]interface{}) + subnetPrefixesItem, err := ResourceIBMIsClusterNetworkMapToClusterNetworkSubnetPrefixPrototype(value) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "create", "parse-subnet_prefixes").GetDiag() + } + subnetPrefixes = append(subnetPrefixes, *subnetPrefixesItem) + } + createClusterNetworkOptions.SetSubnetPrefixes(subnetPrefixes) + } + + clusterNetwork, _, err := vpcClient.CreateClusterNetworkWithContext(context, createClusterNetworkOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateClusterNetworkWithContext failed: %s", err.Error()), "ibm_is_cluster_network", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(*clusterNetwork.ID) + + return resourceIBMIsClusterNetworkRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkOptions := &vpcv1.GetClusterNetworkOptions{} + + getClusterNetworkOptions.SetID(d.Id()) + + clusterNetwork, response, err := vpcClient.GetClusterNetworkWithContext(context, getClusterNetworkOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkWithContext failed: %s", err.Error()), "ibm_is_cluster_network", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(clusterNetwork.Name) { + if err = d.Set("name", clusterNetwork.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-name").GetDiag() + } + } + if err = d.Set("profile", clusterNetwork.Profile.Name); err != nil { + err = fmt.Errorf("Error setting profile: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-profile").GetDiag() + } + if !core.IsNil(clusterNetwork.ResourceGroup) { + if err = d.Set("resource_group", clusterNetwork.ResourceGroup.ID); err != nil { + err = fmt.Errorf("Error setting resource_group: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-resource_group").GetDiag() + } + } + if !core.IsNil(clusterNetwork.SubnetPrefixes) { + subnetPrefixes := []map[string]interface{}{} + for _, subnetPrefixesItem := range clusterNetwork.SubnetPrefixes { + subnetPrefixesItemMap, err := ResourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(&subnetPrefixesItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "subnet_prefixes-to-map").GetDiag() + } + subnetPrefixes = append(subnetPrefixes, subnetPrefixesItemMap) + } + if err = d.Set("subnet_prefixes", subnetPrefixes); err != nil { + err = fmt.Errorf("Error setting subnet_prefixes: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-subnet_prefixes").GetDiag() + } + } + vpcMap, err := ResourceIBMIsClusterNetworkVPCReferenceToMap(clusterNetwork.VPC) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "vpc-to-map").GetDiag() + } + if err = d.Set("vpc", []map[string]interface{}{vpcMap}); err != nil { + err = fmt.Errorf("Error setting vpc: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-vpc").GetDiag() + } + if err = d.Set("zone", clusterNetwork.Zone.Name); err != nil { + err = fmt.Errorf("Error setting zone: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-zone").GetDiag() + } + if err = d.Set("created_at", flex.DateTimeToString(clusterNetwork.CreatedAt)); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-created_at").GetDiag() + } + if err = d.Set("crn", clusterNetwork.CRN); err != nil { + err = fmt.Errorf("Error setting crn: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-crn").GetDiag() + } + if err = d.Set("href", clusterNetwork.Href); err != nil { + err = fmt.Errorf("Error setting href: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-href").GetDiag() + } + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetwork.LifecycleReasons { + lifecycleReasonsItemMap, err := ResourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + err = fmt.Errorf("Error setting lifecycle_reasons: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-lifecycle_reasons").GetDiag() + } + if err = d.Set("lifecycle_state", clusterNetwork.LifecycleState); err != nil { + err = fmt.Errorf("Error setting lifecycle_state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-lifecycle_state").GetDiag() + } + if err = d.Set("resource_type", clusterNetwork.ResourceType); err != nil { + err = fmt.Errorf("Error setting resource_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "read", "set-resource_type").GetDiag() + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting etag: %s", err), "ibm_is_cluster_network", "read", "set-etag").GetDiag() + } + + return nil +} + +func resourceIBMIsClusterNetworkUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateClusterNetworkOptions := &vpcv1.UpdateClusterNetworkOptions{} + + updateClusterNetworkOptions.SetID(d.Id()) + + hasChange := false + + patchVals := &vpcv1.ClusterNetworkPatch{} + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + // updateClusterNetworkOptions.SetIfMatch(d.Get("etag").(string)) + + if hasChange { + updateClusterNetworkOptions.ClusterNetworkPatch = ResourceIBMIsClusterNetworkClusterNetworkPatchAsPatch(patchVals, d) + + _, response, err := vpcClient.UpdateClusterNetworkWithContext(context, updateClusterNetworkOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateClusterNetworkWithContext failed: %s", err.Error()), "ibm_is_cluster_network", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting etag: %s", err), "ibm_is_cluster_network", "update", "set-etag").GetDiag() + } + } + + return resourceIBMIsClusterNetworkRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteClusterNetworkOptions := &vpcv1.DeleteClusterNetworkOptions{} + + deleteClusterNetworkOptions.SetID(d.Id()) + + _, _, err = vpcClient.DeleteClusterNetworkWithContext(context, deleteClusterNetworkOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteClusterNetworkWithContext failed: %s", err.Error()), "ibm_is_cluster_network", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMIsClusterNetworkMapToClusterNetworkProfileIdentityByName(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkProfileIdentityByName, error) { + model := &vpcv1.ClusterNetworkProfileIdentityByName{} + model.Name = core.StringPtr(modelMap["name"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToClusterNetworkProfileIdentityByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkProfileIdentityByHref, error) { + model := &vpcv1.ClusterNetworkProfileIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToVPCIdentity(modelMap map[string]interface{}) (vpcv1.VPCIdentityIntf, error) { + model := &vpcv1.VPCIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToVPCIdentityByID(modelMap map[string]interface{}) (*vpcv1.VPCIdentityByID, error) { + model := &vpcv1.VPCIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToVPCIdentityByCRN(modelMap map[string]interface{}) (*vpcv1.VPCIdentityByCRN, error) { + model := &vpcv1.VPCIdentityByCRN{} + model.CRN = core.StringPtr(modelMap["crn"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToVPCIdentityByHref(modelMap map[string]interface{}) (*vpcv1.VPCIdentityByHref, error) { + model := &vpcv1.VPCIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToZoneIdentityByName(modelMap map[string]interface{}) (*vpcv1.ZoneIdentityByName, error) { + model := &vpcv1.ZoneIdentityByName{} + model.Name = core.StringPtr(modelMap["name"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToZoneIdentityByHref(modelMap map[string]interface{}) (*vpcv1.ZoneIdentityByHref, error) { + model := &vpcv1.ZoneIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToResourceGroupIdentityByID(modelMap map[string]interface{}) (*vpcv1.ResourceGroupIdentityByID, error) { + model := &vpcv1.ResourceGroupIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkMapToClusterNetworkSubnetPrefixPrototype(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetPrefixPrototype, error) { + model := &vpcv1.ClusterNetworkSubnetPrefixPrototype{} + if modelMap["cidr"] != nil && modelMap["cidr"].(string) != "" { + model.CIDR = core.StringPtr(modelMap["cidr"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkClusterNetworkSubnetPrefixToMap(model *vpcv1.ClusterNetworkSubnetPrefix) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["allocation_policy"] = *model.AllocationPolicy + modelMap["cidr"] = *model.CIDR + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkClusterNetworkLifecycleReasonToMap(model *vpcv1.ClusterNetworkLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkClusterNetworkPatchAsPatch(patchVals *vpcv1.ClusterNetworkPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + + return patch +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_interface.go b/ibm/service/vpc/resource_ibm_is_cluster_network_interface.go new file mode 100644 index 0000000000..5e24ca7d8f --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_interface.go @@ -0,0 +1,843 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIBMIsClusterNetworkInterface() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIsClusterNetworkInterfaceCreate, + ReadContext: resourceIBMIsClusterNetworkInterfaceRead, + UpdateContext: resourceIBMIsClusterNetworkInterfaceUpdate, + DeleteContext: resourceIBMIsClusterNetworkInterfaceDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_interface", "cluster_network_id"), + Description: "The cluster network identifier.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_interface", "name"), + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The cluster network subnet reserved IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ConflictsWith: []string{"primary_ip.0.id", "primary_ip.0.href"}, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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, + Optional: true, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Computed: true, + ConflictsWith: []string{"primary_ip.0.address", "primary_ip.0.href"}, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"primary_ip.0.id", "primary_ip.0.href"}, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"primary_ip.0.id", "primary_ip.0.href"}, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either target is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + AtLeastOneOf: []string{"subnet", "primary_ip.0.id", "primary_ip.0.href"}, + Optional: true, + Computed: true, + Description: "The associated cluster network subnet. Required if `primary_ip` does not specify a clusternetwork subnet reserved IP identity.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"subnet.0.id"}, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Computed: true, + ConflictsWith: []string{"subnet.0.href"}, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "allow_ip_spoofing": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network interface was created.", + }, + "enable_infrastructure_nat": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + Description: "If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network interface.", + }, + "mac_address": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`.", + }, + // "protocol_state_filtering_mode": &schema.Schema{ + // Type: schema.TypeString, + // Computed: true, + // Description: "The protocol state filtering mode used for this cluster network interface.Protocol state filtering monitors each network connection flowing over this cluster network interface, and drops any packets that are invalid based on the current connection state and protocol. See [Protocol state filtering mode](https://cloud.ibm.com/docs/vpc?topic=vpc-vni-about#protocol-state-filtering) for more information.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + // }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "vpc": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The VPC this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this VPC.", + }, + "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 VPC.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this VPC.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this VPC. The name is unique across all VPCs in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "zone": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The zone this cluster network interface resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this zone.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this zone.", + }, + }, + }, + }, + "cluster_network_interface_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceIBMIsClusterNetworkInterfaceValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cluster_network_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[-0-9a-z_]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$`, + MinValueLength: 1, + MaxValueLength: 63, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_cluster_network_interface", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIsClusterNetworkInterfaceCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createClusterNetworkInterfaceOptions := &vpcv1.CreateClusterNetworkInterfaceOptions{} + + createClusterNetworkInterfaceOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + if _, ok := d.GetOk("name"); ok { + createClusterNetworkInterfaceOptions.SetName(d.Get("name").(string)) + } + if _, ok := d.GetOk("primary_ip"); ok { + primaryIPModel, err := ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototype(d.Get("primary_ip.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "create", "parse-primary_ip").GetDiag() + } + createClusterNetworkInterfaceOptions.SetPrimaryIP(primaryIPModel) + } + if _, ok := d.GetOk("subnet"); ok { + subnetModel, err := ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkSubnetIdentity(d.Get("subnet.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "create", "parse-subnet").GetDiag() + } + createClusterNetworkInterfaceOptions.SetSubnet(subnetModel) + } + + clusterNetworkInterface, _, err := vpcClient.CreateClusterNetworkInterfaceWithContext(context, createClusterNetworkInterfaceOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateClusterNetworkInterfaceWithContext failed: %s", err.Error()), "ibm_is_cluster_network_interface", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *createClusterNetworkInterfaceOptions.ClusterNetworkID, *clusterNetworkInterface.ID)) + + return resourceIBMIsClusterNetworkInterfaceRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkInterfaceRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkInterfaceOptions := &vpcv1.GetClusterNetworkInterfaceOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "sep-id-parts").GetDiag() + } + + getClusterNetworkInterfaceOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkInterfaceOptions.SetID(parts[1]) + + clusterNetworkInterface, response, err := vpcClient.GetClusterNetworkInterfaceWithContext(context, getClusterNetworkInterfaceOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkInterfaceWithContext failed: %s", err.Error()), "ibm_is_cluster_network_interface", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(clusterNetworkInterface.Name) { + if err = d.Set("name", clusterNetworkInterface.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-name").GetDiag() + } + } + if !core.IsNil(clusterNetworkInterface.PrimaryIP) { + primaryIPMap, err := ResourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(clusterNetworkInterface.PrimaryIP) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "primary_ip-to-map").GetDiag() + } + if err = d.Set("primary_ip", []map[string]interface{}{primaryIPMap}); err != nil { + err = fmt.Errorf("Error setting primary_ip: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-primary_ip").GetDiag() + } + } + if !core.IsNil(clusterNetworkInterface.Subnet) { + subnetMap, err := ResourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(clusterNetworkInterface.Subnet) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "subnet-to-map").GetDiag() + } + if err = d.Set("subnet", []map[string]interface{}{subnetMap}); err != nil { + err = fmt.Errorf("Error setting subnet: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-subnet").GetDiag() + } + } + if err = d.Set("allow_ip_spoofing", clusterNetworkInterface.AllowIPSpoofing); err != nil { + err = fmt.Errorf("Error setting allow_ip_spoofing: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-allow_ip_spoofing").GetDiag() + } + if err = d.Set("auto_delete", clusterNetworkInterface.AutoDelete); err != nil { + err = fmt.Errorf("Error setting auto_delete: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-auto_delete").GetDiag() + } + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkInterface.CreatedAt)); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-created_at").GetDiag() + } + if err = d.Set("enable_infrastructure_nat", clusterNetworkInterface.EnableInfrastructureNat); err != nil { + err = fmt.Errorf("Error setting enable_infrastructure_nat: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-enable_infrastructure_nat").GetDiag() + } + if err = d.Set("href", clusterNetworkInterface.Href); err != nil { + err = fmt.Errorf("Error setting href: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-href").GetDiag() + } + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkInterface.LifecycleReasons { + lifecycleReasonsItemMap, err := ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + err = fmt.Errorf("Error setting lifecycle_reasons: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-lifecycle_reasons").GetDiag() + } + if err = d.Set("lifecycle_state", clusterNetworkInterface.LifecycleState); err != nil { + err = fmt.Errorf("Error setting lifecycle_state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-lifecycle_state").GetDiag() + } + if !core.IsNil(clusterNetworkInterface.MacAddress) { + if err = d.Set("mac_address", clusterNetworkInterface.MacAddress); err != nil { + err = fmt.Errorf("Error setting mac_address: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-mac_address").GetDiag() + } + } + // if !core.IsNil(clusterNetworkInterface.ProtocolStateFilteringMode) { + // if err = d.Set("protocol_state_filtering_mode", clusterNetworkInterface.ProtocolStateFilteringMode); err != nil { + // err = fmt.Errorf("Error setting protocol_state_filtering_mode: %s", err) + // return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-protocol_state_filtering_mode").GetDiag() + // } + // } + if err = d.Set("resource_type", clusterNetworkInterface.ResourceType); err != nil { + err = fmt.Errorf("Error setting resource_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-resource_type").GetDiag() + } + targetMap := make(map[string]interface{}) + if !core.IsNil(clusterNetworkInterface.Target) { + targetMap, err = ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(clusterNetworkInterface.Target) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "target-to-map").GetDiag() + } + } + if err = d.Set("target", []map[string]interface{}{targetMap}); err != nil { + err = fmt.Errorf("Error setting target: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-target").GetDiag() + } + vpcMap, err := ResourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(clusterNetworkInterface.VPC) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "vpc-to-map").GetDiag() + } + if err = d.Set("vpc", []map[string]interface{}{vpcMap}); err != nil { + err = fmt.Errorf("Error setting vpc: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-vpc").GetDiag() + } + zoneMap, err := ResourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(clusterNetworkInterface.Zone) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "zone-to-map").GetDiag() + } + if err = d.Set("zone", []map[string]interface{}{zoneMap}); err != nil { + err = fmt.Errorf("Error setting zone: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-zone").GetDiag() + } + if err = d.Set("cluster_network_interface_id", clusterNetworkInterface.ID); err != nil { + err = fmt.Errorf("Error setting cluster_network_interface_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "read", "set-cluster_network_interface_id").GetDiag() + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting etag: %s", err), "ibm_is_cluster_network_interface", "read", "set-etag").GetDiag() + } + + return nil +} + +func resourceIBMIsClusterNetworkInterfaceUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateClusterNetworkInterfaceOptions := &vpcv1.UpdateClusterNetworkInterfaceOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "update", "sep-id-parts").GetDiag() + } + + updateClusterNetworkInterfaceOptions.SetClusterNetworkID(parts[0]) + updateClusterNetworkInterfaceOptions.SetID(parts[1]) + + hasChange := false + + patchVals := &vpcv1.ClusterNetworkInterfacePatch{} + if d.HasChange("cluster_network_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "cluster_network_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_is_cluster_network_interface", "update", "cluster_network_id-forces-new").GetDiag() + } + if d.HasChange("auto_delete") { + newAutoDelete := d.Get("auto_delete").(bool) + patchVals.AutoDelete = &newAutoDelete + hasChange = true + } + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + // updateClusterNetworkInterfaceOptions.SetIfMatch(d.Get("etag").(string)) + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateClusterNetworkInterfaceOptions.ClusterNetworkInterfacePatch = ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfacePatchAsPatch(patchVals, d) + + _, _, err = vpcClient.UpdateClusterNetworkInterfaceWithContext(context, updateClusterNetworkInterfaceOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateClusterNetworkInterfaceWithContext failed: %s", err.Error()), "ibm_is_cluster_network_interface", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIBMIsClusterNetworkInterfaceRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkInterfaceDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteClusterNetworkInterfaceOptions := &vpcv1.DeleteClusterNetworkInterfaceOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_interface", "delete", "sep-id-parts").GetDiag() + } + + deleteClusterNetworkInterfaceOptions.SetClusterNetworkID(parts[0]) + deleteClusterNetworkInterfaceOptions.SetID(parts[1]) + + _, _, err = vpcClient.DeleteClusterNetworkInterfaceWithContext(context, deleteClusterNetworkInterfaceOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteClusterNetworkInterfaceWithContext failed: %s", err.Error()), "ibm_is_cluster_network_interface", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototype{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext{} + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkSubnetIdentity(modelMap map[string]interface{}) (vpcv1.ClusterNetworkSubnetIdentityIntf, error) { + model := &vpcv1.ClusterNetworkSubnetIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkSubnetIdentityByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByID, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceMapToClusterNetworkSubnetIdentityByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByHref, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceLifecycleReasonToMap(model *vpcv1.ClusterNetworkInterfaceLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetToMap(model vpcv1.ClusterNetworkInterfaceTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext); ok { + return ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model.(*vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfaceTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfaceTarget) + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfaceTargetIntf subtype encountered") + } +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContextToMap(model *vpcv1.ClusterNetworkInterfaceTargetInstanceClusterNetworkAttachmentReferenceClusterNetworkInterfaceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceVPCReferenceToMap(model *vpcv1.VPCReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkInterfaceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceZoneReferenceToMap(model *vpcv1.ZoneReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["name"] = *model.Name + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkInterfaceClusterNetworkInterfacePatchAsPatch(patchVals *vpcv1.ClusterNetworkInterfacePatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "auto_delete" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["auto_delete"] = nil + } + path = "name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + + return patch +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_interface_test.go b/ibm/service/vpc/resource_ibm_is_cluster_network_interface_test.go new file mode 100644 index 0000000000..5f2f712661 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_interface_test.go @@ -0,0 +1,197 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func TestAccIBMIsClusterNetworkInterfaceBasic(t *testing.T) { + var conf vpcv1.ClusterNetworkInterface + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + clustersubnetname := fmt.Sprintf("tf-clustersubnet-%d", acctest.RandIntRange(10, 100)) + clustersubnetreservedipname := fmt.Sprintf("tf-clustersubnet-reservedip-%d", acctest.RandIntRange(10, 100)) + clusterinterfacename := fmt.Sprintf("tf-clusterinterface-%d", acctest.RandIntRange(10, 100)) + clusterinterfacenameupdated := fmt.Sprintf("tf-clusterinterfaceupdated-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfaceConfigBasic(vpcname, clustersubnetname, clustersubnetreservedipname, clusterinterfacename), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkInterfaceExists("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_interface_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "mac_address"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type", "cluster_network_interface"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "primary_ip.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "zone.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "subnet.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name", clusterinterfacename), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkInterfaceConfigBasic(vpcname, clustersubnetname, clustersubnetreservedipname, clusterinterfacenameupdated), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkInterfaceExists("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "allow_ip_spoofing"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "cluster_network_interface_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "enable_infrastructure_nat"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "mac_address"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "resource_type", "cluster_network_interface"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "primary_ip.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "zone.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "subnet.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name", clusterinterfacenameupdated), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkInterfaceConfigBasic(vpcname, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + total_ipv4_address_count = 64 + } + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + address = "${replace(ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.ipv4_cidr_block, "0/26", "11")}" + name = "%s" + } + resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + primary_ip { + id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + } + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename) +} + +func testAccCheckIBMIsClusterNetworkInterfaceExists(n string, obj vpcv1.ClusterNetworkInterface) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + + getClusterNetworkInterfaceOptions := &vpcv1.GetClusterNetworkInterfaceOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkInterfaceOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkInterfaceOptions.SetID(parts[1]) + + clusterNetworkInterface, _, err := vpcClient.GetClusterNetworkInterface(getClusterNetworkInterfaceOptions) + if err != nil { + return err + } + + obj = *clusterNetworkInterface + return nil + } +} + +func testAccCheckIBMIsClusterNetworkInterfaceDestroy(s *terraform.State) error { + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_cluster_network_interface" { + continue + } + + getClusterNetworkInterfaceOptions := &vpcv1.GetClusterNetworkInterfaceOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkInterfaceOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkInterfaceOptions.SetID(parts[1]) + + // Try to find the key + _, response, err := vpcClient.GetClusterNetworkInterface(getClusterNetworkInterfaceOptions) + + if err == nil { + return fmt.Errorf("ClusterNetworkInterface still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for ClusterNetworkInterface (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_subnet.go b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet.go new file mode 100644 index 0000000000..6415090c4f --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet.go @@ -0,0 +1,457 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIBMIsClusterNetworkSubnet() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIsClusterNetworkSubnetCreate, + ReadContext: resourceIBMIsClusterNetworkSubnetRead, + UpdateContext: resourceIBMIsClusterNetworkSubnetUpdate, + DeleteContext: resourceIBMIsClusterNetworkSubnetDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet", "cluster_network_id"), + Description: "The cluster network identifier.", + }, + "ip_version": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet", "ip_version"), + Description: "The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "ipv4_cidr_block": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ExactlyOneOf: []string{"ipv4_cidr_block", "total_ipv4_address_count"}, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet", "ipv4_cidr_block"), + Description: "The IPv4 range of this cluster network subnet, expressed in CIDR format.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet", "name"), + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "total_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + ForceNew: true, + ExactlyOneOf: []string{"ipv4_cidr_block", "total_ipv4_address_count"}, + Description: "The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses.", + }, + "available_ipv4_address_count": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "cluster_network_subnet_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceIBMIsClusterNetworkSubnetValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cluster_network_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[-0-9a-z_]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "ip_version", + ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, + Type: validate.TypeString, + Optional: true, + AllowedValues: "ipv4", + Regexp: `^[a-z][a-z0-9]*(_[a-z0-9]+)*$`, + MinValueLength: 1, + MaxValueLength: 128, + }, + validate.ValidateSchema{ + Identifier: "ipv4_cidr_block", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$`, + MinValueLength: 9, + MaxValueLength: 18, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$`, + MinValueLength: 1, + MaxValueLength: 63, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_cluster_network_subnet", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIsClusterNetworkSubnetCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + bodyModelMap := map[string]interface{}{} + createClusterNetworkSubnetOptions := &vpcv1.CreateClusterNetworkSubnetOptions{} + + if _, ok := d.GetOk("ip_version"); ok { + bodyModelMap["ip_version"] = d.Get("ip_version") + } + if _, ok := d.GetOk("name"); ok { + bodyModelMap["name"] = d.Get("name") + } + if _, ok := d.GetOk("total_ipv4_address_count"); ok { + bodyModelMap["total_ipv4_address_count"] = d.Get("total_ipv4_address_count") + } + if _, ok := d.GetOk("ipv4_cidr_block"); ok { + bodyModelMap["ipv4_cidr_block"] = d.Get("ipv4_cidr_block") + } + createClusterNetworkSubnetOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + convertedModel, err := ResourceIBMIsClusterNetworkSubnetMapToClusterNetworkSubnetPrototype(bodyModelMap) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "create", "parse-request-body").GetDiag() + } + createClusterNetworkSubnetOptions.ClusterNetworkSubnetPrototype = convertedModel + + clusterNetworkSubnet, _, err := vpcClient.CreateClusterNetworkSubnetWithContext(context, createClusterNetworkSubnetOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateClusterNetworkSubnetWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *createClusterNetworkSubnetOptions.ClusterNetworkID, *clusterNetworkSubnet.ID)) + + return resourceIBMIsClusterNetworkSubnetRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkSubnetRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkSubnetOptions := &vpcv1.GetClusterNetworkSubnetOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "sep-id-parts").GetDiag() + } + + getClusterNetworkSubnetOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetOptions.SetID(parts[1]) + + clusterNetworkSubnet, response, err := vpcClient.GetClusterNetworkSubnetWithContext(context, getClusterNetworkSubnetOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkSubnetWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(clusterNetworkSubnet.IPVersion) { + if err = d.Set("ip_version", clusterNetworkSubnet.IPVersion); err != nil { + err = fmt.Errorf("Error setting ip_version: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-ip_version").GetDiag() + } + } + if !core.IsNil(clusterNetworkSubnet.Ipv4CIDRBlock) { + if err = d.Set("ipv4_cidr_block", clusterNetworkSubnet.Ipv4CIDRBlock); err != nil { + err = fmt.Errorf("Error setting ipv4_cidr_block: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-ipv4_cidr_block").GetDiag() + } + } + if !core.IsNil(clusterNetworkSubnet.Name) { + if err = d.Set("name", clusterNetworkSubnet.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-name").GetDiag() + } + } + if !core.IsNil(clusterNetworkSubnet.TotalIpv4AddressCount) { + if err = d.Set("total_ipv4_address_count", flex.IntValue(clusterNetworkSubnet.TotalIpv4AddressCount)); err != nil { + err = fmt.Errorf("Error setting total_ipv4_address_count: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-total_ipv4_address_count").GetDiag() + } + } + if err = d.Set("available_ipv4_address_count", flex.IntValue(clusterNetworkSubnet.AvailableIpv4AddressCount)); err != nil { + err = fmt.Errorf("Error setting available_ipv4_address_count: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-available_ipv4_address_count").GetDiag() + } + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkSubnet.CreatedAt)); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-created_at").GetDiag() + } + if err = d.Set("href", clusterNetworkSubnet.Href); err != nil { + err = fmt.Errorf("Error setting href: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-href").GetDiag() + } + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkSubnet.LifecycleReasons { + lifecycleReasonsItemMap, err := ResourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + err = fmt.Errorf("Error setting lifecycle_reasons: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-lifecycle_reasons").GetDiag() + } + if err = d.Set("lifecycle_state", clusterNetworkSubnet.LifecycleState); err != nil { + err = fmt.Errorf("Error setting lifecycle_state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-lifecycle_state").GetDiag() + } + if err = d.Set("resource_type", clusterNetworkSubnet.ResourceType); err != nil { + err = fmt.Errorf("Error setting resource_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-resource_type").GetDiag() + } + if err = d.Set("cluster_network_subnet_id", clusterNetworkSubnet.ID); err != nil { + err = fmt.Errorf("Error setting cluster_network_subnet_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "read", "set-cluster_network_subnet_id").GetDiag() + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting etag: %s", err), "ibm_is_cluster_network_subnet", "read", "set-etag").GetDiag() + } + + return nil +} + +func resourceIBMIsClusterNetworkSubnetUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateClusterNetworkSubnetOptions := &vpcv1.UpdateClusterNetworkSubnetOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "update", "sep-id-parts").GetDiag() + } + + updateClusterNetworkSubnetOptions.SetClusterNetworkID(parts[0]) + updateClusterNetworkSubnetOptions.SetID(parts[1]) + + hasChange := false + + patchVals := &vpcv1.ClusterNetworkSubnetPatch{} + if d.HasChange("cluster_network_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "cluster_network_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_is_cluster_network_subnet", "update", "cluster_network_id-forces-new").GetDiag() + } + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + // updateClusterNetworkSubnetOptions.SetIfMatch(d.Get("etag").(string)) + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateClusterNetworkSubnetOptions.ClusterNetworkSubnetPatch = ResourceIBMIsClusterNetworkSubnetClusterNetworkSubnetPatchAsPatch(patchVals, d) + + _, _, err = vpcClient.UpdateClusterNetworkSubnetWithContext(context, updateClusterNetworkSubnetOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateClusterNetworkSubnetWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIBMIsClusterNetworkSubnetRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkSubnetDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteClusterNetworkSubnetOptions := &vpcv1.DeleteClusterNetworkSubnetOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet", "delete", "sep-id-parts").GetDiag() + } + + deleteClusterNetworkSubnetOptions.SetClusterNetworkID(parts[0]) + deleteClusterNetworkSubnetOptions.SetID(parts[1]) + + _, _, err = vpcClient.DeleteClusterNetworkSubnetWithContext(context, deleteClusterNetworkSubnetOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteClusterNetworkSubnetWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMIsClusterNetworkSubnetMapToClusterNetworkSubnetPrototype(modelMap map[string]interface{}) (vpcv1.ClusterNetworkSubnetPrototypeIntf, error) { + model := &vpcv1.ClusterNetworkSubnetPrototype{} + if modelMap["ip_version"] != nil && modelMap["ip_version"].(string) != "" { + model.IPVersion = core.StringPtr(modelMap["ip_version"].(string)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["total_ipv4_address_count"] != nil { + model.TotalIpv4AddressCount = core.Int64Ptr(int64(modelMap["total_ipv4_address_count"].(int))) + } + if modelMap["ipv4_cidr_block"] != nil && modelMap["ipv4_cidr_block"].(string) != "" { + model.Ipv4CIDRBlock = core.StringPtr(modelMap["ipv4_cidr_block"].(string)) + } + return model, nil +} + +func ResourceIBMIsClusterNetworkSubnetMapToClusterNetworkSubnetPrototypeClusterNetworkSubnetByTotalCountPrototype(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetPrototypeClusterNetworkSubnetByTotalCountPrototype, error) { + model := &vpcv1.ClusterNetworkSubnetPrototypeClusterNetworkSubnetByTotalCountPrototype{} + if modelMap["ip_version"] != nil && modelMap["ip_version"].(string) != "" { + model.IPVersion = core.StringPtr(modelMap["ip_version"].(string)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + model.TotalIpv4AddressCount = core.Int64Ptr(int64(modelMap["total_ipv4_address_count"].(int))) + return model, nil +} + +func ResourceIBMIsClusterNetworkSubnetMapToClusterNetworkSubnetPrototypeClusterNetworkSubnetByIPv4CIDRBlockPrototype(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetPrototypeClusterNetworkSubnetByIPv4CIDRBlockPrototype, error) { + model := &vpcv1.ClusterNetworkSubnetPrototypeClusterNetworkSubnetByIPv4CIDRBlockPrototype{} + if modelMap["ip_version"] != nil && modelMap["ip_version"].(string) != "" { + model.IPVersion = core.StringPtr(modelMap["ip_version"].(string)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + model.Ipv4CIDRBlock = core.StringPtr(modelMap["ipv4_cidr_block"].(string)) + return model, nil +} + +func ResourceIBMIsClusterNetworkSubnetClusterNetworkSubnetLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkSubnetClusterNetworkSubnetPatchAsPatch(patchVals *vpcv1.ClusterNetworkSubnetPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + + return patch +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip.go b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip.go new file mode 100644 index 0000000000..45e227f599 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip.go @@ -0,0 +1,517 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIBMIsClusterNetworkSubnetReservedIP() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIsClusterNetworkSubnetReservedIPCreate, + ReadContext: resourceIBMIsClusterNetworkSubnetReservedIPRead, + UpdateContext: resourceIBMIsClusterNetworkSubnetReservedIPUpdate, + DeleteContext: resourceIBMIsClusterNetworkSubnetReservedIPDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "cluster_network_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet_reserved_ip", "cluster_network_id"), + Description: "The cluster network identifier.", + }, + "cluster_network_subnet_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet_reserved_ip", "cluster_network_subnet_id"), + Description: "The cluster network subnet identifier.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet_reserved_ip", "address"), + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.InvokeValidator("ibm_is_cluster_network_subnet_reserved_ip", "name"), + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "created_at": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The date and time that the cluster network subnet reserved IP was created.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the cluster network subnet reserved IP.", + }, + "owner": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "target": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "deleted": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + 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, + Optional: true, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_subnet_reserved_ip_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "etag": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "cluster_network_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[-0-9a-z_]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "cluster_network_subnet_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[-0-9a-z_]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "address", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$`, + MinValueLength: 7, + MaxValueLength: 15, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$`, + MinValueLength: 1, + MaxValueLength: 63, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_cluster_network_subnet_reserved_ip", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIsClusterNetworkSubnetReservedIPCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createClusterNetworkSubnetReservedIPOptions := &vpcv1.CreateClusterNetworkSubnetReservedIPOptions{} + + createClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(d.Get("cluster_network_id").(string)) + createClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(d.Get("cluster_network_subnet_id").(string)) + if _, ok := d.GetOk("address"); ok { + createClusterNetworkSubnetReservedIPOptions.SetAddress(d.Get("address").(string)) + } + if _, ok := d.GetOk("name"); ok { + createClusterNetworkSubnetReservedIPOptions.SetName(d.Get("name").(string)) + } + + clusterNetworkSubnetReservedIP, _, err := vpcClient.CreateClusterNetworkSubnetReservedIPWithContext(context, createClusterNetworkSubnetReservedIPOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateClusterNetworkSubnetReservedIPWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet_reserved_ip", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s/%s", *createClusterNetworkSubnetReservedIPOptions.ClusterNetworkID, *createClusterNetworkSubnetReservedIPOptions.ClusterNetworkSubnetID, *clusterNetworkSubnetReservedIP.ID)) + + return resourceIBMIsClusterNetworkSubnetReservedIPRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkSubnetReservedIPRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getClusterNetworkSubnetReservedIPOptions := &vpcv1.GetClusterNetworkSubnetReservedIPOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "sep-id-parts").GetDiag() + } + + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(parts[1]) + getClusterNetworkSubnetReservedIPOptions.SetID(parts[2]) + + clusterNetworkSubnetReservedIP, response, err := vpcClient.GetClusterNetworkSubnetReservedIPWithContext(context, getClusterNetworkSubnetReservedIPOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetClusterNetworkSubnetReservedIPWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet_reserved_ip", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(clusterNetworkSubnetReservedIP.Address) { + if err = d.Set("address", clusterNetworkSubnetReservedIP.Address); err != nil { + err = fmt.Errorf("Error setting address: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-address").GetDiag() + } + } + if !core.IsNil(clusterNetworkSubnetReservedIP.Name) { + if err = d.Set("name", clusterNetworkSubnetReservedIP.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-name").GetDiag() + } + } + if err = d.Set("auto_delete", clusterNetworkSubnetReservedIP.AutoDelete); err != nil { + err = fmt.Errorf("Error setting auto_delete: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-auto_delete").GetDiag() + } + if err = d.Set("created_at", flex.DateTimeToString(clusterNetworkSubnetReservedIP.CreatedAt)); err != nil { + err = fmt.Errorf("Error setting created_at: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-created_at").GetDiag() + } + if err = d.Set("href", clusterNetworkSubnetReservedIP.Href); err != nil { + err = fmt.Errorf("Error setting href: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-href").GetDiag() + } + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range clusterNetworkSubnetReservedIP.LifecycleReasons { + lifecycleReasonsItemMap, err := ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + err = fmt.Errorf("Error setting lifecycle_reasons: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-lifecycle_reasons").GetDiag() + } + if err = d.Set("lifecycle_state", clusterNetworkSubnetReservedIP.LifecycleState); err != nil { + err = fmt.Errorf("Error setting lifecycle_state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-lifecycle_state").GetDiag() + } + if err = d.Set("owner", clusterNetworkSubnetReservedIP.Owner); err != nil { + err = fmt.Errorf("Error setting owner: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-owner").GetDiag() + } + if err = d.Set("resource_type", clusterNetworkSubnetReservedIP.ResourceType); err != nil { + err = fmt.Errorf("Error setting resource_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-resource_type").GetDiag() + } + targetMap := make(map[string]interface{}) + if !core.IsNil(clusterNetworkSubnetReservedIP.Target) { + targetMap, err = ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(clusterNetworkSubnetReservedIP.Target) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "target-to-map").GetDiag() + } + } + if err = d.Set("target", []map[string]interface{}{targetMap}); err != nil { + err = fmt.Errorf("Error setting target: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-target").GetDiag() + } + if err = d.Set("cluster_network_subnet_reserved_ip_id", clusterNetworkSubnetReservedIP.ID); err != nil { + err = fmt.Errorf("Error setting cluster_network_subnet_reserved_ip_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-cluster_network_subnet_reserved_ip_id").GetDiag() + } + if err = d.Set("etag", response.Headers.Get("Etag")); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting etag: %s", err), "ibm_is_cluster_network_subnet_reserved_ip", "read", "set-etag").GetDiag() + } + + return nil +} + +func resourceIBMIsClusterNetworkSubnetReservedIPUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateClusterNetworkSubnetReservedIPOptions := &vpcv1.UpdateClusterNetworkSubnetReservedIPOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "update", "sep-id-parts").GetDiag() + } + + updateClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(parts[0]) + updateClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(parts[1]) + updateClusterNetworkSubnetReservedIPOptions.SetID(parts[2]) + + hasChange := false + + patchVals := &vpcv1.ClusterNetworkSubnetReservedIPPatch{} + if d.HasChange("cluster_network_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "cluster_network_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_is_cluster_network_subnet_reserved_ip", "update", "cluster_network_id-forces-new").GetDiag() + } + if d.HasChange("cluster_network_subnet_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "cluster_network_subnet_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_is_cluster_network_subnet_reserved_ip", "update", "cluster_network_subnet_id-forces-new").GetDiag() + } + if d.HasChange("auto_delete") { + newAutoDelete := d.Get("auto_delete").(bool) + patchVals.AutoDelete = &newAutoDelete + hasChange = true + } + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + // updateClusterNetworkSubnetReservedIPOptions.SetIfMatch(d.Get("etag").(string)) + + if hasChange { + updateClusterNetworkSubnetReservedIPOptions.ClusterNetworkSubnetReservedIPPatch = ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPPatchAsPatch(patchVals, d) + + _, _, err = vpcClient.UpdateClusterNetworkSubnetReservedIPWithContext(context, updateClusterNetworkSubnetReservedIPOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateClusterNetworkSubnetReservedIPWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet_reserved_ip", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIBMIsClusterNetworkSubnetReservedIPRead(context, d, meta) +} + +func resourceIBMIsClusterNetworkSubnetReservedIPDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteClusterNetworkSubnetReservedIPOptions := &vpcv1.DeleteClusterNetworkSubnetReservedIPOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_cluster_network_subnet_reserved_ip", "delete", "sep-id-parts").GetDiag() + } + + deleteClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(parts[0]) + deleteClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(parts[1]) + deleteClusterNetworkSubnetReservedIPOptions.SetID(parts[2]) + + _, _, err = vpcClient.DeleteClusterNetworkSubnetReservedIPWithContext(context, deleteClusterNetworkSubnetReservedIPOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteClusterNetworkSubnetReservedIPWithContext failed: %s", err.Error()), "ibm_is_cluster_network_subnet_reserved_ip", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPLifecycleReasonToMap(model *vpcv1.ClusterNetworkSubnetReservedIPLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetToMap(model vpcv1.ClusterNetworkSubnetReservedIPTargetIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext); ok { + return ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model.(*vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetReservedIPTarget) + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(model.Deleted) + if err != nil { + return modelMap, err + } + modelMap["deleted"] = []map[string]interface{}{deletedMap} + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.ResourceType != nil { + modelMap["resource_type"] = *model.ResourceType + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetReservedIPTargetIntf subtype encountered") + } +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContextToMap(model *vpcv1.ClusterNetworkSubnetReservedIPTargetClusterNetworkInterfaceReferenceClusterNetworkSubnetReservedIPTargetContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsClusterNetworkSubnetReservedIPDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsClusterNetworkSubnetReservedIPClusterNetworkSubnetReservedIPPatchAsPatch(patchVals *vpcv1.ClusterNetworkSubnetReservedIPPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "auto_delete" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["auto_delete"] = nil + } + path = "name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + + return patch +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip_test.go b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip_test.go new file mode 100644 index 0000000000..b5a58b1640 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_reserved_ip_test.go @@ -0,0 +1,152 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func TestAccIBMIsClusterNetworkSubnetReservedIPBasic(t *testing.T) { + var conf vpcv1.ClusterNetworkSubnetReservedIP + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + clustersubnetname := fmt.Sprintf("tf-clustersubnet-%d", acctest.RandIntRange(10, 100)) + clustersubnetreservedipname := fmt.Sprintf("tf-clustersubnet-reservedip-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkSubnetReservedIPDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetReservedIPConfigBasic(vpcname, clustersubnetname, clustersubnetreservedipname), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkSubnetReservedIPExists("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name", clustersubnetname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "name", clustersubnetreservedipname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "address"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "auto_delete"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "cluster_network_subnet_reserved_ip_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_state"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "resource_type"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "resource_type", "cluster_network_subnet_reserved_ip"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "owner"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIPConfigBasic(vpcname, clustersubnetname, clustersubnetreservedipname string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + total_ipv4_address_count = 64 + } + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + address = "${replace(ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.ipv4_cidr_block, "0/26", "11")}" + name = "%s" + } + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, clustersubnetname, clustersubnetreservedipname) +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIPExists(n string, obj vpcv1.ClusterNetworkSubnetReservedIP) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + + getClusterNetworkSubnetReservedIPOptions := &vpcv1.GetClusterNetworkSubnetReservedIPOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(parts[1]) + getClusterNetworkSubnetReservedIPOptions.SetID(parts[2]) + + clusterNetworkSubnetReservedIP, _, err := vpcClient.GetClusterNetworkSubnetReservedIP(getClusterNetworkSubnetReservedIPOptions) + if err != nil { + return err + } + + obj = *clusterNetworkSubnetReservedIP + return nil + } +} + +func testAccCheckIBMIsClusterNetworkSubnetReservedIPDestroy(s *terraform.State) error { + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_cluster_network_subnet_reserved_ip" { + continue + } + + getClusterNetworkSubnetReservedIPOptions := &vpcv1.GetClusterNetworkSubnetReservedIPOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetReservedIPOptions.SetClusterNetworkSubnetID(parts[1]) + getClusterNetworkSubnetReservedIPOptions.SetID(parts[2]) + + // Try to find the key + _, response, err := vpcClient.GetClusterNetworkSubnetReservedIP(getClusterNetworkSubnetReservedIPOptions) + + if err == nil { + return fmt.Errorf("ClusterNetworkSubnetReservedIP still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for ClusterNetworkSubnetReservedIP (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_test.go b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_test.go new file mode 100644 index 0000000000..aca9b5b5b3 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_subnet_test.go @@ -0,0 +1,251 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func TestAccIBMIsClusterNetworkSubnetBasic(t *testing.T) { + var conf vpcv1.ClusterNetworkSubnet + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + totalipv4addresscount := int64(64) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkSubnetDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetConfigBasic(vpcname, totalipv4addresscount), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkSubnetExists("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ip_version"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count", "64"), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkSubnetBasicAllArgs(t *testing.T) { + var conf vpcv1.ClusterNetworkSubnet + vpcname := fmt.Sprintf("tf-vpcname-%d", acctest.RandIntRange(10, 100)) + name1 := fmt.Sprintf("tf-cluster-subnet1-%d", acctest.RandIntRange(10, 100)) + name1Updated := fmt.Sprintf("tf-cluster-subnet1-updated%d", acctest.RandIntRange(10, 100)) + name2 := fmt.Sprintf("tf-cluster-subnet2-%d", acctest.RandIntRange(10, 100)) + name2Updated := fmt.Sprintf("tf-cluster-subnet2-%d", acctest.RandIntRange(10, 100)) + totalIpv4AddressCount := int64(64) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkSubnetDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetConfig(vpcname, name1, name2, totalIpv4AddressCount), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkSubnetExists("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name", name1), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count", "64"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "name", name2), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ipv4_cidr_block", acc.ISCIDR), + + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ip_version"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ip_version"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "name"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "total_ipv4_address_count"), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkSubnetConfig(vpcname, name1Updated, name2Updated, totalIpv4AddressCount), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name", name1Updated), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count", "64"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "name", name2Updated), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ipv4_cidr_block", acc.ISCIDR), + + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ip_version"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "total_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "available_ipv4_address_count"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "cluster_network_subnet_id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ip_version"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "ipv4_cidr_block"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "name"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "resource_type"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance_cidr", "total_ipv4_address_count"), + ), + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkSubnetConfigBasic(vpcname string, totalipv4addresscount int64) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + total_ipv4_address_count = %d + } + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, totalipv4addresscount) +} + +func testAccCheckIBMIsClusterNetworkSubnetConfig(vpcname, subnetname1, subnetname2 string, totalIpv4AddressCount int64) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + total_ipv4_address_count = %d + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance_cidr" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + ipv4_cidr_block = "%s" + } + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, subnetname1, totalIpv4AddressCount, subnetname2, acc.ISCIDR) +} + +func testAccCheckIBMIsClusterNetworkSubnetExists(n string, obj vpcv1.ClusterNetworkSubnet) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + + getClusterNetworkSubnetOptions := &vpcv1.GetClusterNetworkSubnetOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkSubnetOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetOptions.SetID(parts[1]) + + clusterNetworkSubnet, _, err := vpcClient.GetClusterNetworkSubnet(getClusterNetworkSubnetOptions) + if err != nil { + return err + } + + obj = *clusterNetworkSubnet + return nil + } +} + +func testAccCheckIBMIsClusterNetworkSubnetDestroy(s *terraform.State) error { + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_cluster_network_subnet" { + continue + } + + getClusterNetworkSubnetOptions := &vpcv1.GetClusterNetworkSubnetOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getClusterNetworkSubnetOptions.SetClusterNetworkID(parts[0]) + getClusterNetworkSubnetOptions.SetID(parts[1]) + + // Try to find the key + _, response, err := vpcClient.GetClusterNetworkSubnet(getClusterNetworkSubnetOptions) + + if err == nil { + return fmt.Errorf("ClusterNetworkSubnet still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for ClusterNetworkSubnet (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_cluster_network_test.go b/ibm/service/vpc/resource_ibm_is_cluster_network_test.go new file mode 100644 index 0000000000..9828fa4470 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_cluster_network_test.go @@ -0,0 +1,205 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func TestAccIBMIsClusterNetworkBasic(t *testing.T) { + var conf vpcv1.ClusterNetwork + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkConfigBasic(vpcname), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkExists("ibm_is_cluster_network.is_cluster_network_instance", conf), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "crn"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "zone"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.name", vpcname), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "profile", acc.ISClusterNetworkProfileName), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "resource_type", "cluster_network"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "zone", acc.ISZoneName), + ), + }, + }, + }) +} + +func TestAccIBMIsClusterNetworkBasicAllArgs(t *testing.T) { + var conf vpcv1.ClusterNetwork + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + subnetPrefixesCidr := acc.ISClusterNetworkSubnetPrefixesCidr + name := fmt.Sprintf("tf-clusternetwork-%d", acctest.RandIntRange(10, 100)) + nameUpdate := fmt.Sprintf("tf-clusternetwork-updated-%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsClusterNetworkDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkConfig(vpcname, name, subnetPrefixesCidr), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsClusterNetworkExists("ibm_is_cluster_network.is_cluster_network_instance", conf), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "name", name), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "crn"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "zone"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.name", vpcname), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "profile", acc.ISClusterNetworkProfileName), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "resource_type", "cluster_network"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.cidr", acc.ISClusterNetworkSubnetPrefixesCidr), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "zone", acc.ISZoneName), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMIsClusterNetworkConfig(vpcname, nameUpdate, subnetPrefixesCidr), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "name", nameUpdate), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "created_at"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "crn"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "href"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "vpc.#"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "zone"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "vpc.0.name", vpcname), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "profile", acc.ISClusterNetworkProfileName), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "lifecycle_state", "stable"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "subnet_prefixes.0.cidr", acc.ISClusterNetworkSubnetPrefixesCidr), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "resource_type", "cluster_network"), + resource.TestCheckResourceAttr("ibm_is_cluster_network.is_cluster_network_instance", "zone", acc.ISZoneName), + ), + }, + resource.TestStep{ + ResourceName: "ibm_is_cluster_network.is_cluster_network_instance", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckIBMIsClusterNetworkConfigBasic(vpcname string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName) +} + +func testAccCheckIBMIsClusterNetworkConfig(vpcname, clusterNetworkName, subnetPrefixesCidr string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + name = "%s" + profile = "%s" + subnet_prefixes { + cidr = "%s" + } + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + `, vpcname, clusterNetworkName, acc.ISClusterNetworkProfileName, subnetPrefixesCidr, acc.ISZoneName) +} + +func testAccCheckIBMIsClusterNetworkExists(n string, obj vpcv1.ClusterNetwork) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + + getClusterNetworkOptions := &vpcv1.GetClusterNetworkOptions{} + + getClusterNetworkOptions.SetID(rs.Primary.ID) + + clusterNetwork, _, err := vpcClient.GetClusterNetwork(getClusterNetworkOptions) + if err != nil { + return err + } + + obj = *clusterNetwork + return nil + } +} + +func testAccCheckIBMIsClusterNetworkDestroy(s *terraform.State) error { + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_cluster_network" { + continue + } + + getClusterNetworkOptions := &vpcv1.GetClusterNetworkOptions{} + + getClusterNetworkOptions.SetID(rs.Primary.ID) + + // Try to find the key + _, response, err := vpcClient.GetClusterNetwork(getClusterNetworkOptions) + + if err == nil { + return fmt.Errorf("ClusterNetwork still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for ClusterNetwork (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index 1f1d6bb628..1d9776d3db 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -215,6 +215,186 @@ func ResourceIBMISInstance() *schema.Resource { Description: "Crn for this Instance", }, + // cluster changes + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: "A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + DiffSuppressOnRefresh: true, + DiffSuppressFunc: flex.ApplyOnce, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + DiffSuppressFunc: flex.ApplyOnce, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + }, + }, + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The URL for this cluster network subnet.", + }, + }, + }, + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this cluster network interface.", + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "If present, the cluster network that this virtual server instance resides in.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "crn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The CRN for this cluster network.", + }, + "deleted": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + 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 cluster network.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network. The name must not be used by another cluster network in the region.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -1816,6 +1996,23 @@ func instanceCreateByImage(d *schema.ResourceData, meta interface{}, profile, na ID: &vpcID, }, } + + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + if len(clusterNetworkAttachmentList) > 0 { + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } + } + if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -2252,6 +2449,21 @@ func instanceCreateByCatalogOffering(d *schema.ResourceData, meta interface{}, p ID: &vpcID, }, } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + if len(clusterNetworkAttachmentList) > 0 { + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -2694,6 +2906,21 @@ func instanceCreateByTemplate(d *schema.ResourceData, meta interface{}, profile, }, Name: &name, } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + if len(clusterNetworkAttachmentList) > 0 { + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -3142,6 +3369,21 @@ func instanceCreateBySnapshot(d *schema.ResourceData, meta interface{}, profile, ID: &vpcID, }, } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + if len(clusterNetworkAttachmentList) > 0 { + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -3588,6 +3830,21 @@ func instanceCreateByVolume(d *schema.ResourceData, meta interface{}, profile, n ID: &vpcID, }, } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + if len(clusterNetworkAttachmentList) > 0 { + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -4163,6 +4420,31 @@ func instanceGet(d *schema.ResourceData, meta interface{}, id string) error { } return fmt.Errorf("[ERROR] Error getting Instance: %s\n%s", err, response) } + // cluster changes + if !core.IsNil(instance.ClusterNetworkAttachments) { + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := ResourceIBMIsInstanceInstanceClusterNetworkAttachmentReferenceToMap(instanceC, &clusterNetworkAttachmentsItem, *instance.ID) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "cluster_network_attachments-to-map") + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + if err = d.Set("cluster_network_attachments", clusterNetworkAttachments); err != nil { + err = fmt.Errorf("Error setting cluster_network_attachments: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "set-cluster_network_attachments") + } + } + if !core.IsNil(instance.ClusterNetwork) { + clusterNetworkMap, err := ResourceIBMIsInstanceClusterNetworkReferenceToMap(instance.ClusterNetwork) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "cluster_network-to-map") + } + if err = d.Set("cluster_network", []map[string]interface{}{clusterNetworkMap}); err != nil { + err = fmt.Errorf("Error setting cluster_network: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance", "read", "set-cluster_network") + } + } if !core.IsNil(instance.ConfidentialComputeMode) { if err = d.Set("confidential_compute_mode", instance.ConfidentialComputeMode); err != nil { return fmt.Errorf("Error setting confidential_compute_mode: %s", err) @@ -6689,3 +6971,167 @@ func containsNacId(s []string, e string) bool { } return false } + +func ResourceIBMIsInstanceInstanceClusterNetworkAttachmentReferenceToMap(instanceC *vpcv1.VpcV1, model *vpcv1.InstanceClusterNetworkAttachmentReference, id string) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + getInstanceClusterNetworkAttachment := &vpcv1.GetInstanceClusterNetworkAttachmentOptions{ + InstanceID: &id, + ID: model.ID, + } + clusterNetworkAttachment, _, err := instanceC.GetInstanceClusterNetworkAttachment(getInstanceClusterNetworkAttachment) + if err != nil { + return modelMap, err + } + if clusterNetworkAttachment.ClusterNetworkInterface != nil { + clusterMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentToMap(clusterNetworkAttachment) + if err != nil { + return modelMap, err + } + modelMap["cluster_network_interface"] = []map[string]interface{}{clusterMap} + } + + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentToMap(cnamodel *vpcv1.InstanceClusterNetworkAttachment) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + model := cnamodel.ClusterNetworkInterface + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsInstanceDeletedToMap(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.Subnet != nil { + subnetMap, err := ResourceIBMIsInstanceClusterNetworkInterfaceSubnetToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + if model.PrimaryIP != nil { + primaryipMap, err := ResourceIBMIsInstanceClusterNetworkInterfacePrimaryIPToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryipMap} + } + return modelMap, nil +} +func ResourceIBMIsInstanceClusterNetworkInterfacePrimaryIPToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + return modelMap, nil +} +func ResourceIBMIsInstanceClusterNetworkInterfaceSubnetToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + return modelMap, nil +} +func ResourceIBMIsInstanceClusterNetworkReferenceToMap(model *vpcv1.ClusterNetworkReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["crn"] = *model.CRN + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsInstanceDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsInstanceDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + ClusterNetworkInterfaceModel, err := ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(modelMap["cluster_network_interface"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ClusterNetworkInterface = ClusterNetworkInterfaceModel + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface{} + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["primary_ip"] != nil && len(modelMap["primary_ip"].([]interface{})) > 0 { + PrimaryIPModel, err := ResourceIBMIsInstanceMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap["primary_ip"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PrimaryIP = PrimaryIPModel + } + if modelMap["subnet"] != nil && len(modelMap["subnet"].([]interface{})) > 0 { + SubnetModel, err := ResourceIBMIsInstanceMapToClusterNetworkSubnetIdentity(modelMap["subnet"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Subnet = SubnetModel + } + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototype{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} +func ResourceIBMIsInstanceMapToClusterNetworkSubnetIdentity(modelMap map[string]interface{}) (vpcv1.ClusterNetworkSubnetIdentityIntf, error) { + model := &vpcv1.ClusterNetworkSubnetIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment.go b/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment.go new file mode 100644 index 0000000000..9920f41371 --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment.go @@ -0,0 +1,766 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc + +import ( + "context" + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func ResourceIBMIsInstanceClusterNetworkAttachment() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceIBMIsInstanceClusterNetworkAttachmentCreate, + ReadContext: resourceIBMIsInstanceClusterNetworkAttachmentRead, + UpdateContext: resourceIBMIsInstanceClusterNetworkAttachmentUpdate, + DeleteContext: resourceIBMIsInstanceClusterNetworkAttachmentDelete, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "instance_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.InvokeValidator("ibm_is_instance_cluster_network_attachment", "instance_id"), + Description: "The virtual server instance identifier.", + }, + "before": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: "The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: "The cluster network interface for this instance cluster network attachment.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network interface.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this cluster network interface.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name for this cluster network interface. The name is unique across all interfaces in the cluster network.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The primary IP for this cluster network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "address": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future.", + }, + "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, + Required: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "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 cluster network subnet.", + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + }, + }, + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.InvokeValidator("ibm_is_instance_cluster_network_attachment", "name"), + Description: "The name for this instance cluster network attachment. The name is unique across all network attachments for the instance.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this instance cluster network attachment.", + }, + "lifecycle_reasons": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The reasons for the current `lifecycle_state` (if any).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "code": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "message": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "An explanation of the reason for this lifecycle state.", + }, + "more_info": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Link to documentation about the reason for this lifecycle state.", + }, + }, + }, + }, + "lifecycle_state": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The lifecycle state of the instance cluster network attachment.", + }, + "resource_type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The resource type.", + }, + "instance_cluster_network_attachment_id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The unique identifier for this instance cluster network attachment.", + }, + }, + } +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentValidator() *validate.ResourceValidator { + validateSchema := make([]validate.ValidateSchema, 0) + validateSchema = append(validateSchema, + validate.ValidateSchema{ + Identifier: "instance_id", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Required: true, + Regexp: `^[-0-9a-z_]+$`, + MinValueLength: 1, + MaxValueLength: 64, + }, + validate.ValidateSchema{ + Identifier: "name", + ValidateFunctionIdentifier: validate.ValidateRegexpLen, + Type: validate.TypeString, + Optional: true, + Regexp: `^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$`, + MinValueLength: 1, + MaxValueLength: 63, + }, + ) + + resourceValidator := validate.ResourceValidator{ResourceName: "ibm_is_instance_cluster_network_attachment", Schema: validateSchema} + return &resourceValidator +} + +func resourceIBMIsInstanceClusterNetworkAttachmentCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "create", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + createClusterNetworkAttachmentOptions := &vpcv1.CreateClusterNetworkAttachmentOptions{} + + createClusterNetworkAttachmentOptions.SetInstanceID(d.Get("instance_id").(string)) + clusterNetworkInterfaceModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(d.Get("cluster_network_interface.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "create", "parse-cluster_network_interface").GetDiag() + } + createClusterNetworkAttachmentOptions.SetClusterNetworkInterface(clusterNetworkInterfaceModel) + if _, ok := d.GetOk("before"); ok { + beforeModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentBeforePrototype(d.Get("before.0").(map[string]interface{})) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "create", "parse-before").GetDiag() + } + createClusterNetworkAttachmentOptions.SetBefore(beforeModel) + } + if _, ok := d.GetOk("name"); ok { + createClusterNetworkAttachmentOptions.SetName(d.Get("name").(string)) + } + + instanceClusterNetworkAttachment, _, err := vpcClient.CreateClusterNetworkAttachmentWithContext(context, createClusterNetworkAttachmentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("CreateClusterNetworkAttachmentWithContext failed: %s", err.Error()), "ibm_is_instance_cluster_network_attachment", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId(fmt.Sprintf("%s/%s", *createClusterNetworkAttachmentOptions.InstanceID, *instanceClusterNetworkAttachment.ID)) + + return resourceIBMIsInstanceClusterNetworkAttachmentRead(context, d, meta) +} + +func resourceIBMIsInstanceClusterNetworkAttachmentRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + getInstanceClusterNetworkAttachmentOptions := &vpcv1.GetInstanceClusterNetworkAttachmentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "sep-id-parts").GetDiag() + } + + getInstanceClusterNetworkAttachmentOptions.SetInstanceID(parts[0]) + getInstanceClusterNetworkAttachmentOptions.SetID(parts[1]) + + instanceClusterNetworkAttachment, response, err := vpcClient.GetInstanceClusterNetworkAttachmentWithContext(context, getInstanceClusterNetworkAttachmentOptions) + if err != nil { + if response != nil && response.StatusCode == 404 { + d.SetId("") + return nil + } + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetInstanceClusterNetworkAttachmentWithContext failed: %s", err.Error()), "ibm_is_instance_cluster_network_attachment", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + if !core.IsNil(instanceClusterNetworkAttachment.Before) { + beforeMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentBeforeToMap(instanceClusterNetworkAttachment.Before) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "before-to-map").GetDiag() + } + if err = d.Set("before", []map[string]interface{}{beforeMap}); err != nil { + err = fmt.Errorf("Error setting before: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-before").GetDiag() + } + } + clusterNetworkInterfaceMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkInterfaceReferenceToMap(instanceClusterNetworkAttachment.ClusterNetworkInterface) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "cluster_network_interface-to-map").GetDiag() + } + if err = d.Set("cluster_network_interface", []map[string]interface{}{clusterNetworkInterfaceMap}); err != nil { + err = fmt.Errorf("Error setting cluster_network_interface: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-cluster_network_interface").GetDiag() + } + if !core.IsNil(instanceClusterNetworkAttachment.Name) { + if err = d.Set("name", instanceClusterNetworkAttachment.Name); err != nil { + err = fmt.Errorf("Error setting name: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-name").GetDiag() + } + } + if err = d.Set("href", instanceClusterNetworkAttachment.Href); err != nil { + err = fmt.Errorf("Error setting href: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-href").GetDiag() + } + lifecycleReasons := []map[string]interface{}{} + for _, lifecycleReasonsItem := range instanceClusterNetworkAttachment.LifecycleReasons { + lifecycleReasonsItemMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentLifecycleReasonToMap(&lifecycleReasonsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "lifecycle_reasons-to-map").GetDiag() + } + lifecycleReasons = append(lifecycleReasons, lifecycleReasonsItemMap) + } + if err = d.Set("lifecycle_reasons", lifecycleReasons); err != nil { + err = fmt.Errorf("Error setting lifecycle_reasons: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-lifecycle_reasons").GetDiag() + } + if err = d.Set("lifecycle_state", instanceClusterNetworkAttachment.LifecycleState); err != nil { + err = fmt.Errorf("Error setting lifecycle_state: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-lifecycle_state").GetDiag() + } + if err = d.Set("resource_type", instanceClusterNetworkAttachment.ResourceType); err != nil { + err = fmt.Errorf("Error setting resource_type: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-resource_type").GetDiag() + } + if err = d.Set("instance_cluster_network_attachment_id", instanceClusterNetworkAttachment.ID); err != nil { + err = fmt.Errorf("Error setting instance_cluster_network_attachment_id: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "read", "set-instance_cluster_network_attachment_id").GetDiag() + } + + return nil +} + +func resourceIBMIsInstanceClusterNetworkAttachmentUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "update", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + updateInstanceClusterNetworkAttachmentOptions := &vpcv1.UpdateInstanceClusterNetworkAttachmentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "update", "sep-id-parts").GetDiag() + } + + updateInstanceClusterNetworkAttachmentOptions.SetInstanceID(parts[0]) + updateInstanceClusterNetworkAttachmentOptions.SetID(parts[1]) + + hasChange := false + + patchVals := &vpcv1.InstanceClusterNetworkAttachmentPatch{} + if d.HasChange("instance_id") { + errMsg := fmt.Sprintf("Cannot update resource property \"%s\" with the ForceNew annotation."+ + " The resource must be re-created to update this property.", "instance_id") + return flex.DiscriminatedTerraformErrorf(nil, errMsg, "ibm_is_instance_cluster_network_attachment", "update", "instance_id-forces-new").GetDiag() + } + if d.HasChange("name") { + newName := d.Get("name").(string) + patchVals.Name = &newName + hasChange = true + } + + if hasChange { + // Fields with `nil` values are omitted from the generic map, + // so we need to re-add them to support removing arguments + // in merge-patch operations sent to the service. + updateInstanceClusterNetworkAttachmentOptions.InstanceClusterNetworkAttachmentPatch = ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentPatchAsPatch(patchVals, d) + + _, _, err = vpcClient.UpdateInstanceClusterNetworkAttachmentWithContext(context, updateInstanceClusterNetworkAttachmentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("UpdateInstanceClusterNetworkAttachmentWithContext failed: %s", err.Error()), "ibm_is_instance_cluster_network_attachment", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + } + + return resourceIBMIsInstanceClusterNetworkAttachmentRead(context, d, meta) +} + +func resourceIBMIsInstanceClusterNetworkAttachmentDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vpcClient, err := meta.(conns.ClientSession).VpcV1API() + if err != nil { + tfErr := flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "delete", "initialize-client") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + deleteInstanceClusterNetworkAttachmentOptions := &vpcv1.DeleteInstanceClusterNetworkAttachmentOptions{} + + parts, err := flex.SepIdParts(d.Id(), "/") + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_cluster_network_attachment", "delete", "sep-id-parts").GetDiag() + } + + deleteInstanceClusterNetworkAttachmentOptions.SetInstanceID(parts[0]) + deleteInstanceClusterNetworkAttachmentOptions.SetID(parts[1]) + + _, _, err = vpcClient.DeleteInstanceClusterNetworkAttachmentWithContext(context, deleteInstanceClusterNetworkAttachmentOptions) + if err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("DeleteInstanceClusterNetworkAttachmentWithContext failed: %s", err.Error()), "ibm_is_instance_cluster_network_attachment", "delete") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() + } + + d.SetId("") + + return nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface{} + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["primary_ip"] != nil && len(modelMap["primary_ip"].([]interface{})) > 0 { + PrimaryIPModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap["primary_ip"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PrimaryIP = PrimaryIPModel + } + if modelMap["subnet"] != nil && len(modelMap["subnet"].([]interface{})) > 0 { + SubnetModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkSubnetIdentity(modelMap["subnet"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Subnet = SubnetModel + } + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototype{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext{} + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkSubnetIdentity(modelMap map[string]interface{}) (vpcv1.ClusterNetworkSubnetIdentityIntf, error) { + model := &vpcv1.ClusterNetworkSubnetIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkSubnetIdentityByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByID, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkSubnetIdentityByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByHref, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment{} + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["primary_ip"] != nil && len(modelMap["primary_ip"].([]interface{})) > 0 { + PrimaryIPModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap["primary_ip"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PrimaryIP = PrimaryIPModel + } + if modelMap["subnet"] != nil && len(modelMap["subnet"].([]interface{})) > 0 { + SubnetModel, err := ResourceIBMIsInstanceClusterNetworkAttachmentMapToClusterNetworkSubnetIdentity(modelMap["subnet"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Subnet = SubnetModel + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentBeforePrototype(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentBeforePrototypeIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentBeforePrototype{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByID(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByID, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentMapToInstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByHref(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByHref, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentBeforePrototypeInstanceClusterNetworkAttachmentIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentBeforeToMap(model *vpcv1.InstanceClusterNetworkAttachmentBefore) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + modelMap["id"] = *model.ID + modelMap["name"] = *model.Name + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkInterfaceReferenceToMap(model *vpcv1.ClusterNetworkInterfaceReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + primaryIPMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReservedIPReferenceToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + modelMap["resource_type"] = *model.ResourceType + subnetMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReferenceToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(model *vpcv1.Deleted) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["more_info"] = *model.MoreInfo + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReservedIPReferenceToMap(model *vpcv1.ClusterNetworkSubnetReservedIPReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["address"] = *model.Address + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentClusterNetworkSubnetReferenceToMap(model *vpcv1.ClusterNetworkSubnetReference) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Deleted != nil { + deletedMap, err := ResourceIBMIsInstanceClusterNetworkAttachmentDeletedToMap(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 + modelMap["resource_type"] = *model.ResourceType + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentLifecycleReasonToMap(model *vpcv1.InstanceClusterNetworkAttachmentLifecycleReason) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["code"] = *model.Code + modelMap["message"] = *model.Message + if model.MoreInfo != nil { + modelMap["more_info"] = *model.MoreInfo + } + return modelMap, nil +} + +func ResourceIBMIsInstanceClusterNetworkAttachmentInstanceClusterNetworkAttachmentPatchAsPatch(patchVals *vpcv1.InstanceClusterNetworkAttachmentPatch, d *schema.ResourceData) map[string]interface{} { + patch, _ := patchVals.AsPatch() + var path string + + path = "name" + if _, exists := d.GetOk(path); d.HasChange(path) && !exists { + patch["name"] = nil + } + + return patch +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment_test.go b/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment_test.go new file mode 100644 index 0000000000..289c5e6a9e --- /dev/null +++ b/ibm/service/vpc/resource_ibm_is_instance_cluster_network_attachment_test.go @@ -0,0 +1,209 @@ +// Copyright IBM Corp. 2024 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package vpc_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" + "github.com/IBM/vpc-go-sdk/vpcv1" +) + +func TestAccIBMIsInstanceClusterNetworkAttachmentBasic(t *testing.T) { + var conf vpcv1.InstanceClusterNetworkAttachment + instanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsInstanceClusterNetworkAttachmentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentConfigBasic(instanceID), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsInstanceClusterNetworkAttachmentExists("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", conf), + resource.TestCheckResourceAttr("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_id", instanceID), + ), + }, + }, + }) +} + +func TestAccIBMIsInstanceClusterNetworkAttachmentAllArgs(t *testing.T) { + var conf vpcv1.InstanceClusterNetworkAttachment + instanceID := fmt.Sprintf("tf_instance_id_%d", acctest.RandIntRange(10, 100)) + name := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + nameUpdate := fmt.Sprintf("tf_name_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMIsInstanceClusterNetworkAttachmentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentConfig(instanceID, name), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckIBMIsInstanceClusterNetworkAttachmentExists("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", conf), + resource.TestCheckResourceAttr("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_id", instanceID), + resource.TestCheckResourceAttr("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "name", name), + ), + }, + resource.TestStep{ + Config: testAccCheckIBMIsInstanceClusterNetworkAttachmentConfig(instanceID, nameUpdate), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "instance_id", instanceID), + resource.TestCheckResourceAttr("ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance", "name", nameUpdate), + ), + }, + resource.TestStep{ + ResourceName: "ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentConfigBasic(instanceID string) string { + return fmt.Sprintf(` + resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = "%s" + cluster_network_interface { + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + id = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + name = "my-cluster-network-interface" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + } + `, instanceID) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentConfig(instanceID string, name string) string { + return fmt.Sprintf(` + + resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + instance_id = "%s" + before { + href = "https://us-south.iaas.cloud.ibm.com/v1/instances/0717_e21b7391-2ca2-4ab5-84a8-b92157a633b0/cluster_network_attachments/0717-fb880975-db45-4459-8548-64e3995ac213" + id = "0717-fb880975-db45-4459-8548-64e3995ac213" + } + cluster_network_interface { + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/interfaces/0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + id = "0717-ffc092f7-5d02-4b93-ab69-26860529b9fb" + name = "my-cluster-network-interface" + primary_ip { + address = "10.1.0.6" + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930/reserved_ips/6d353a0f-aeb1-4ae1-832e-1110d10981bb" + id = "6d353a0f-aeb1-4ae1-832e-1110d10981bb" + name = "my-cluster-network-subnet-reserved-ip" + resource_type = "cluster_network_subnet_reserved_ip" + } + subnet { + deleted { + more_info = "https://cloud.ibm.com/apidocs/vpc#deleted-resources" + } + href = "https://us-south.iaas.cloud.ibm.com/v1/cluster_networks/0717-da0df18c-7598-4633-a648-fdaac28a5573/subnets/0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + name = "my-cluster-network-subnet" + resource_type = "cluster_network_subnet" + } + } + name = "%s" + } + `, instanceID, name) +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentExists(n string, obj vpcv1.InstanceClusterNetworkAttachment) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + + getInstanceClusterNetworkAttachmentOptions := &vpcv1.GetInstanceClusterNetworkAttachmentOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getInstanceClusterNetworkAttachmentOptions.SetInstanceID(parts[0]) + getInstanceClusterNetworkAttachmentOptions.SetID(parts[1]) + + instanceClusterNetworkAttachment, _, err := vpcClient.GetInstanceClusterNetworkAttachment(getInstanceClusterNetworkAttachmentOptions) + if err != nil { + return err + } + + obj = *instanceClusterNetworkAttachment + return nil + } +} + +func testAccCheckIBMIsInstanceClusterNetworkAttachmentDestroy(s *terraform.State) error { + vpcClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).VpcV1API() + if err != nil { + return err + } + for _, rs := range s.RootModule().Resources { + if rs.Type != "ibm_is_instance_cluster_network_attachment" { + continue + } + + getInstanceClusterNetworkAttachmentOptions := &vpcv1.GetInstanceClusterNetworkAttachmentOptions{} + + parts, err := flex.SepIdParts(rs.Primary.ID, "/") + if err != nil { + return err + } + + getInstanceClusterNetworkAttachmentOptions.SetInstanceID(parts[0]) + getInstanceClusterNetworkAttachmentOptions.SetID(parts[1]) + + // Try to find the key + _, response, err := vpcClient.GetInstanceClusterNetworkAttachment(getInstanceClusterNetworkAttachmentOptions) + + if err == nil { + return fmt.Errorf("InstanceClusterNetworkAttachment still exists: %s", rs.Primary.ID) + } else if response.StatusCode != 404 { + return fmt.Errorf("Error checking for InstanceClusterNetworkAttachment (%s) has been destroyed: %s", rs.Primary.ID, err) + } + } + + return nil +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_template.go b/ibm/service/vpc/resource_ibm_is_instance_template.go index 4fd13aab33..f3240f3169 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_template.go +++ b/ibm/service/vpc/resource_ibm_is_instance_template.go @@ -110,6 +110,115 @@ func ResourceIBMISInstanceTemplate() *schema.Resource { Description: "Instance Template name", }, + // cluster changes + "cluster_network_attachments": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: "The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_network_interface": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: "A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Indicates whether this cluster network interface will be automatically deleted when `target` is deleted.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + "primary_ip": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unique identifier for this cluster network subnet reserved IP.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for this cluster network subnet reserved IP.", + }, + "address": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected.", + }, + "auto_delete": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound.", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words.", + }, + }, + }, + }, + "subnet": &schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unique identifier for this cluster network subnet.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for this cluster network subnet.", + }, + }, + }, + }, + "id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The unique identifier for this cluster network interface.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The URL for this cluster network interface.", + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed.", + }, + }, + }, + }, + "confidential_compute_mode": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -1278,6 +1387,19 @@ func instanceTemplateCreateByCatalogOffering(d *schema.ResourceData, meta interf ID: &vpcID, }, } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -1767,6 +1889,19 @@ func instanceTemplateCreate(d *schema.ResourceData, meta interface{}, profile, n if name != "" { instanceproto.Name = &name } + // cluster changes + if clusterNetworkAttachmentOk, ok := d.GetOk("cluster_network_attachments"); ok { + clusterNetworkAttachmentList := clusterNetworkAttachmentOk.([]interface{}) + clusterNetworkAttachments := []vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + for _, clusterNetworkAttachmentsItem := range clusterNetworkAttachmentList { + clusterNetworkAttachmentsItemModel, err := ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(clusterNetworkAttachmentsItem.(map[string]interface{})) + if err != nil { + return err + } + clusterNetworkAttachments = append(clusterNetworkAttachments, *clusterNetworkAttachmentsItemModel) + } + instanceproto.ClusterNetworkAttachments = clusterNetworkAttachments + } if _, ok := d.GetOk("confidential_compute_mode"); ok { instanceproto.ConfidentialComputeMode = core.StringPtr(d.Get("confidential_compute_mode").(string)) } @@ -2244,6 +2379,19 @@ func instanceTemplateGet(d *schema.ResourceData, meta interface{}, ID string) er if instance.AvailabilityPolicy != nil && instance.AvailabilityPolicy.HostFailure != nil { d.Set(isInstanceTemplateAvailablePolicyHostFailure, instance.AvailabilityPolicy.HostFailure) } + // cluster changes + clusterNetworkAttachments := []map[string]interface{}{} + for _, clusterNetworkAttachmentsItem := range instance.ClusterNetworkAttachments { + clusterNetworkAttachmentsItemMap, err := ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(&clusterNetworkAttachmentsItem) // #nosec G601 + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "cluster_network_attachments-to-map") + } + clusterNetworkAttachments = append(clusterNetworkAttachments, clusterNetworkAttachmentsItemMap) + } + if err = d.Set("cluster_network_attachments", clusterNetworkAttachments); err != nil { + err = fmt.Errorf("Error setting cluster_network_attachments: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_instance_template", "read", "set-cluster_network_attachments") + } if !core.IsNil(instance.ConfidentialComputeMode) { if err = d.Set("confidential_compute_mode", instance.ConfidentialComputeMode); err != nil { return fmt.Errorf("Error setting confidential_compute_mode: %s", err) @@ -2896,3 +3044,392 @@ func hashIpsListForInstanceTemplate(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-", a["address"].(string))) return conns.String(buf.String()) } + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeInstanceContextToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + clusterNetworkInterfaceMap, err := ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model.ClusterNetworkInterface) + if err != nil { + return modelMap, err + } + modelMap["cluster_network_interface"] = []map[string]interface{}{clusterNetworkInterfaceMap} + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment); ok { + return ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + return ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf subtype encountered") + } +} + +func ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototype) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf subtype encountered") + } +} + +func ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextToMap(model vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf subtype encountered") + } +} + +func ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByIDToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHrefToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContextToMap(model *vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.Address != nil { + modelMap["address"] = *model.Address + } + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model vpcv1.ClusterNetworkSubnetIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByID); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByIDToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByID)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentityByHref); ok { + return ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByHrefToMap(model.(*vpcv1.ClusterNetworkSubnetIdentityByHref)) + } else if _, ok := model.(*vpcv1.ClusterNetworkSubnetIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.ClusterNetworkSubnetIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.ClusterNetworkSubnetIdentityIntf subtype encountered") + } +} + +func ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByIDToMap(model *vpcv1.ClusterNetworkSubnetIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityByHrefToMap(model *vpcv1.ClusterNetworkSubnetIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachmentToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.AutoDelete != nil { + modelMap["auto_delete"] = *model.AutoDelete + } + if model.Name != nil { + modelMap["name"] = *model.Name + } + if model.PrimaryIP != nil { + primaryIPMap, err := ResourceIBMIsInstanceTemplateClusterNetworkInterfacePrimaryIPPrototypeToMap(model.PrimaryIP) + if err != nil { + return modelMap, err + } + modelMap["primary_ip"] = []map[string]interface{}{primaryIPMap} + } + if model.Subnet != nil { + subnetMap, err := ResourceIBMIsInstanceTemplateClusterNetworkSubnetIdentityToMap(model.Subnet) + if err != nil { + return modelMap, err + } + modelMap["subnet"] = []map[string]interface{}{subnetMap} + } + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityToMap(model vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID); ok { + return ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref); ok { + return ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref)) + } else if _, ok := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity) + if model.ID != nil { + modelMap["id"] = *model.ID + } + if model.Href != nil { + modelMap["href"] = *model.Href + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf subtype encountered") + } +} + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByIDToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["id"] = *model.ID + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHrefToMap(model *vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["href"] = *model.Href + return modelMap, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeInstanceContext(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeInstanceContext{} + ClusterNetworkInterfaceModel, err := ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(modelMap["cluster_network_interface"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.ClusterNetworkInterface = ClusterNetworkInterfaceModel + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterface{} + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["primary_ip"] != nil && len(modelMap["primary_ip"].([]interface{})) > 0 { + PrimaryIPModel, err := ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap["primary_ip"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PrimaryIP = PrimaryIPModel + } + if modelMap["subnet"] != nil && len(modelMap["subnet"].([]interface{})) > 0 { + SubnetModel, err := ResourceIBMIsInstanceTemplateMapToClusterNetworkSubnetIdentity(modelMap["subnet"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Subnet = SubnetModel + } + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototype{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextIntf, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContext{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPIdentityClusterNetworkInterfacePrimaryIPContextByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext, error) { + model := &vpcv1.ClusterNetworkInterfacePrimaryIPPrototypeClusterNetworkSubnetReservedIPPrototypeClusterNetworkInterfacePrimaryIPContext{} + if modelMap["address"] != nil && modelMap["address"].(string) != "" { + model.Address = core.StringPtr(modelMap["address"].(string)) + } + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkSubnetIdentity(modelMap map[string]interface{}) (vpcv1.ClusterNetworkSubnetIdentityIntf, error) { + model := &vpcv1.ClusterNetworkSubnetIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkSubnetIdentityByID(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByID, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToClusterNetworkSubnetIdentityByHref(modelMap map[string]interface{}) (*vpcv1.ClusterNetworkSubnetIdentityByHref, error) { + model := &vpcv1.ClusterNetworkSubnetIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceInstanceClusterNetworkInterfacePrototypeInstanceClusterNetworkAttachment{} + if modelMap["auto_delete"] != nil { + model.AutoDelete = core.BoolPtr(modelMap["auto_delete"].(bool)) + } + if modelMap["name"] != nil && modelMap["name"].(string) != "" { + model.Name = core.StringPtr(modelMap["name"].(string)) + } + if modelMap["primary_ip"] != nil && len(modelMap["primary_ip"].([]interface{})) > 0 { + PrimaryIPModel, err := ResourceIBMIsInstanceTemplateMapToClusterNetworkInterfacePrimaryIPPrototype(modelMap["primary_ip"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.PrimaryIP = PrimaryIPModel + } + if modelMap["subnet"] != nil && len(modelMap["subnet"].([]interface{})) > 0 { + SubnetModel, err := ResourceIBMIsInstanceTemplateMapToClusterNetworkSubnetIdentity(modelMap["subnet"].([]interface{})[0].(map[string]interface{})) + if err != nil { + return model, err + } + model.Subnet = SubnetModel + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity(modelMap map[string]interface{}) (vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityIntf, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentity{} + if modelMap["id"] != nil && modelMap["id"].(string) != "" { + model.ID = core.StringPtr(modelMap["id"].(string)) + } + if modelMap["href"] != nil && modelMap["href"].(string) != "" { + model.Href = core.StringPtr(modelMap["href"].(string)) + } + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByID{} + model.ID = core.StringPtr(modelMap["id"].(string)) + return model, nil +} + +func ResourceIBMIsInstanceTemplateMapToInstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref(modelMap map[string]interface{}) (*vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref, error) { + model := &vpcv1.InstanceClusterNetworkAttachmentPrototypeClusterNetworkInterfaceClusterNetworkInterfaceIdentityClusterNetworkInterfaceIdentityByHref{} + model.Href = core.StringPtr(modelMap["href"].(string)) + return model, nil +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_template_test.go b/ibm/service/vpc/resource_ibm_is_instance_template_test.go index 4d819dc180..0bbefa10a2 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_template_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_template_test.go @@ -939,3 +939,160 @@ func testAccCheckIBMISInstanceTemplateConfigAvailablePolicyHostFailure_Updated(v `, vpcName, subnetName, sshKeyName, publicKey, templateName) } + +func TestAccIBMISInstanceTemplate_clusternetworkbasic(t *testing.T) { + randInt := acctest.RandIntRange(10, 100) + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + clustersubnetname := fmt.Sprintf("tf-clustersubnet-%d", acctest.RandIntRange(10, 100)) + clustersubnetreservedipname := fmt.Sprintf("tf-clustersubnet-reservedip-%d", acctest.RandIntRange(10, 100)) + clusterinterfacename := fmt.Sprintf("tf-clusterinterface-%d", acctest.RandIntRange(10, 100)) + + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVtuCfWKVGKaRmaRG6JQZY8YdxnDgGzVOK93IrV9R5Hl0JP1oiLLWlZQS2reAKb8lBqyDVEREpaoRUDjqDqXG8J/kR42FKN51su914pjSBc86wJ02VtT1Wm1zRbSg67kT+g8/T1jCgB5XBODqbcICHVP8Z1lXkgbiHLwlUrbz6OZkGJHo/M/kD1Eme8lctceIYNz/Ilm7ewMXZA4fsidpto9AjyarrJLufrOBl4MRVcZTDSJ7rLP982aHpu9pi5eJAjOZc7Og7n4ns3NFppiCwgVMCVUQbN5GBlWhZ1OsT84ZiTf+Zy8ew+Yg5T7Il8HuC7loWnz+esQPf0s3xhC/kTsGgZreIDoh/rxJfD67wKXetNSh5RH/n5BqjaOuXPFeNXmMhKlhj9nJ8scayx/wsvOGuocEIkbyJSLj3sLUU403OafgatEdnJOwbqg6rUNNF5RIjpJpL7eEWlKIi1j9LyhmPJ+fEO7TmOES82VpCMHpLbe4gf/MhhJ/Xy8DKh9s= root@ffd8363b1226 + `) + subnetName := fmt.Sprintf("tf-testsubnet%d", randInt) + templateName := fmt.Sprintf("tf-testtemplate%d", randInt) + sshKeyName := fmt.Sprintf("tf-testsshkey%d", randInt) + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceTemplateClusterNetworkConfig(vpcname, clustersubnetname, clustersubnetreservedipname, clusterinterfacename, subnetName, sshKeyName, publicKey, templateName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name", clustersubnetname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "name", clustersubnetreservedipname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name", clusterinterfacename), + resource.TestCheckResourceAttrSet("ibm_is_subnet.is_subnet", "id"), + resource.TestCheckResourceAttr("ibm_is_subnet.is_subnet", "name", subnetName), + resource.TestCheckResourceAttrSet("ibm_is_ssh_key.is_sshkey", "id"), + resource.TestCheckResourceAttr("ibm_is_ssh_key.is_sshkey", "name", sshKeyName), + resource.TestCheckResourceAttr( + "ibm_is_instance_template.is_instance_template", "name", templateName), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "profile"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "crn"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "image"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "keys.#"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "name"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "resource_group"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "vpc"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "zone"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "boot_volume.#"), + resource.TestCheckResourceAttrSet("ibm_is_instance_template.is_instance_template", "cluster_network_attachments.#"), + resource.TestCheckResourceAttr("ibm_is_instance_template.is_instance_template", "cluster_network_attachments.#", "8"), + ), + }, + }, + }) +} + +func testAccCheckIBMISInstanceTemplateClusterNetworkConfig(vpcname, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename, subnetName, sshKeyName, publicKey, templateName string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + total_ipv4_address_count = 64 + } + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + address = "${replace(ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.ipv4_cidr_block, "0/26", "11")}" + name = "%s" + } + resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + primary_ip { + id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + } + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + + resource "ibm_is_subnet" "is_subnet" { + name = "%s" + vpc = ibm_is_vpc.is_vpc.id + zone = "%s" + total_ipv4_address_count = 64 + } + + resource "ibm_is_ssh_key" "is_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_instance_template" "is_instance_template" { + name = "%s" + image = "%s" + profile = "%s" + + primary_network_interface { + subnet = ibm_is_subnet.is_subnet.id + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id + } + } + vpc = ibm_is_vpc.is_vpc.id + zone = "%s" + keys = [ibm_is_ssh_key.is_sshkey.id] + } + + + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename, subnetName, acc.ISZoneName, sshKeyName, publicKey, templateName, acc.IsImage, acc.ISInstanceGPUProfileName, acc.ISZoneName) + +} diff --git a/ibm/service/vpc/resource_ibm_is_instance_test.go b/ibm/service/vpc/resource_ibm_is_instance_test.go index f11dcbc6d4..339a49da48 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_test.go +++ b/ibm/service/vpc/resource_ibm_is_instance_test.go @@ -3014,3 +3014,226 @@ func testAccCheckIBMISInstanceCatalogImagePNAConfig(vpcname, subnetname, sshname } }`, vpcname, subnetname, acc.ISZoneName, acc.ISCIDR, sshname, publicKey, name, acc.InstanceProfileName, userData, acc.ISZoneName) } + +func TestAccIBMISInstanceclusternetworkattachment_basic(t *testing.T) { + var instance string + randInt := acctest.RandIntRange(10, 100) + vpcname := fmt.Sprintf("tf-vpc-%d", acctest.RandIntRange(10, 100)) + clustersubnetname := fmt.Sprintf("tf-clustersubnet-%d", acctest.RandIntRange(10, 100)) + clustersubnetreservedipname := fmt.Sprintf("tf-clustersubnet-reservedip-%d", acctest.RandIntRange(10, 100)) + clusterinterfacename := fmt.Sprintf("tf-clusterinterface-%d", acctest.RandIntRange(10, 100)) + + publicKey := strings.TrimSpace(` + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVtuCfWKVGKaRmaRG6JQZY8YdxnDgGzVOK93IrV9R5Hl0JP1oiLLWlZQS2reAKb8lBqyDVEREpaoRUDjqDqXG8J/kR42FKN51su914pjSBc86wJ02VtT1Wm1zRbSg67kT+g8/T1jCgB5XBODqbcICHVP8Z1lXkgbiHLwlUrbz6OZkGJHo/M/kD1Eme8lctceIYNz/Ilm7ewMXZA4fsidpto9AjyarrJLufrOBl4MRVcZTDSJ7rLP982aHpu9pi5eJAjOZc7Og7n4ns3NFppiCwgVMCVUQbN5GBlWhZ1OsT84ZiTf+Zy8ew+Yg5T7Il8HuC7loWnz+esQPf0s3xhC/kTsGgZreIDoh/rxJfD67wKXetNSh5RH/n5BqjaOuXPFeNXmMhKlhj9nJ8scayx/wsvOGuocEIkbyJSLj3sLUU403OafgatEdnJOwbqg6rUNNF5RIjpJpL7eEWlKIi1j9LyhmPJ+fEO7TmOES82VpCMHpLbe4gf/MhhJ/Xy8DKh9s= root@ffd8363b1226 + `) + subnetName := fmt.Sprintf("tf-testsubnet-%d", randInt) + name := fmt.Sprintf("tf-testinstance-%d", randInt) + updatedname := fmt.Sprintf("tf-testinstance-%d", randInt) + sshKeyName := fmt.Sprintf("tf-testsshkey-%d", randInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckIBMISInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckIBMISInstanceClusterNetworkAttachmentConfig(vpcname, clustersubnetname, clustersubnetreservedipname, clusterinterfacename, subnetName, sshKeyName, publicKey, name), + Check: resource.ComposeTestCheckFunc( + testAccCheckIBMISInstanceExists("ibm_is_instance.is_instance", instance), + resource.TestCheckResourceAttr( + "ibm_is_instance.is_instance", "name", name), + resource.TestCheckResourceAttr( + "ibm_is_instance.is_instance", "zone", acc.ISZoneName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.is_instance", "vcpu.#"), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.is_instance", "vcpu.0.manufacturer"), + resource.TestCheckResourceAttr("ibm_is_vpc.is_vpc", "name", vpcname), + resource.TestCheckResourceAttrSet("ibm_is_vpc.is_vpc", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network.is_cluster_network_instance", "id"), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance", "name", clustersubnetname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance", "name", clustersubnetreservedipname), + resource.TestCheckResourceAttrSet("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "id"), + resource.TestCheckResourceAttr("ibm_is_cluster_network_interface.is_cluster_network_interface_instance", "name", clusterinterfacename), + resource.TestCheckResourceAttrSet("ibm_is_subnet.is_subnet", "id"), + resource.TestCheckResourceAttr("ibm_is_subnet.is_subnet", "name", subnetName), + resource.TestCheckResourceAttrSet("ibm_is_ssh_key.is_sshkey", "id"), + resource.TestCheckResourceAttr("ibm_is_ssh_key.is_sshkey", "name", sshKeyName), + resource.TestCheckResourceAttr( + "ibm_is_instance.is_instance", "name", name), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "profile"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "crn"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "image"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "keys.#"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "name"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "resource_group"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "vpc"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "zone"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "boot_volume.#"), + resource.TestCheckResourceAttrSet("ibm_is_instance.is_instance", "cluster_network_attachments.#"), + resource.TestCheckResourceAttr("ibm_is_instance.is_instance", "cluster_network_attachments.#", "8"), + ), + }, + { + Config: testAccCheckIBMISInstanceClusterNetworkAttachmentConfig(vpcname, clustersubnetname, clustersubnetreservedipname, clusterinterfacename, subnetName, sshKeyName, publicKey, updatedname), + 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", "zone", acc.ISZoneName), + resource.TestCheckResourceAttrSet( + "ibm_is_instance.testacc_instance", "primary_network_interface.0.port_speed"), + 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", "numa_count"), + ), + }, + }, + }) +} + +func testAccCheckIBMISInstanceClusterNetworkAttachmentConfig(vpcname, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename, subnetName, sshKeyName, publicKey, instanceName string) string { + return fmt.Sprintf(` + resource "ibm_is_vpc" "is_vpc" { + name = "%s" + } + resource "ibm_is_cluster_network" "is_cluster_network_instance" { + profile = "%s" + vpc { + id = ibm_is_vpc.is_vpc.id + } + zone = "%s" + } + resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + total_ipv4_address_count = 64 + } + resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + address = "${replace(ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.ipv4_cidr_block, "0/26", "11")}" + name = "%s" + } + resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + name = "%s" + primary_ip { + id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id + } + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + + resource "ibm_is_subnet" "is_subnet" { + name = "%s" + vpc = ibm_is_vpc.is_vpc.id + zone = "%s" + total_ipv4_address_count = 64 + } + + resource "ibm_is_ssh_key" "is_sshkey" { + name = "%s" + public_key = "%s" + } + + resource "ibm_is_instance" "is_instance" { + name = "%s" + image = "%s" + profile = "%s" + timeouts { + create = "60m" + } + primary_network_attachment { + name = "my-pna" + virtual_network_interface { + auto_delete = true + subnet = ibm_is_subnet.is_subnet.id + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-1" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-2" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-3" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-4" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-5" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-6" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-7" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-8" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + vpc = ibm_is_vpc.is_vpc.id + zone = ibm_is_subnet.is_subnet.zone + keys = [ibm_is_ssh_key.is_sshkey.id] + } + + `, vpcname, acc.ISClusterNetworkProfileName, acc.ISZoneName, clustersubnetname, clustersubnetreservedipname, clusternetworkinterfacename, subnetName, acc.ISZoneName, sshKeyName, publicKey, instanceName, acc.IsImage, acc.ISInstanceGPUProfileName) +} diff --git a/website/docs/d/is_cluster_network.html.markdown b/website/docs/d/is_cluster_network.html.markdown new file mode 100644 index 0000000000..99a5b0460d --- /dev/null +++ b/website/docs/d/is_cluster_network.html.markdown @@ -0,0 +1,74 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network" +description: |- + Get information about ClusterNetwork +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network + +Provides a read-only data source to retrieve information about a ClusterNetwork. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network" "is_cluster_network_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetwork. +- `created_at` - (String) The date and time that the cluster network was created. +- `crn` - (String) The CRN for this cluster network. +- `href` - (String) The URL for this cluster network. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network. +- `name` - (String) The name for this cluster network. The name must not be used by another cluster network in the region. +- `profile` - (List) The profile for this cluster network. +Nested schema for **profile**: + - `href` - (String) The URL for this cluster network profile. + - `name` - (String) The globally unique name for this cluster network profile. + - `resource_type` - (String) The resource type. +- `resource_group` - (List) The resource group for this cluster network. +Nested schema for **resource_group**: + - `href` - (String) The URL for this resource group. + - `id` - (String) The unique identifier for this resource group. + - `name` - (String) The name for this resource group. +- `resource_type` - (String) The resource type. +- `subnet_prefixes` - (List) The IP address ranges available for subnets for this cluster network. + + Nested schema for **subnet_prefixes**: + - `allocation_policy` - (String) The allocation policy for this subnet prefix:- `auto`: Subnets created by total count in this cluster network can use this prefix. + - `cidr` - (String) The CIDR block for this prefix. +- `vpc` - (List) The VPC this cluster network resides in. + + Nested schema for **vpc**: + - `crn` - (String) The CRN for this VPC. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this VPC. + - `id` - (String) The unique identifier for this VPC. + - `name` - (String) The name for this VPC. The name is unique across all VPCs in the region. + - `resource_type` - (String) The resource type. +- `zone` - (List) The zone this cluster network resides in. + Nested schema for **zone**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_cluster_network_interface.html.markdown b/website/docs/d/is_cluster_network_interface.html.markdown new file mode 100644 index 0000000000..b3e417cf5f --- /dev/null +++ b/website/docs/d/is_cluster_network_interface.html.markdown @@ -0,0 +1,86 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_interface" +description: |- + Get information about ClusterNetworkInterface +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_interface + +Provides a read-only data source to retrieve information about a ClusterNetworkInterface. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_interface_id = ibm_is_cluster_network_interface.is_cluster_network_interface_instance.cluster_network_interface_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `cluster_network_interface_id` - (Required, Forces new resource, String) The cluster network interface identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkInterface. +- `allow_ip_spoofing` - (Boolean) Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface. +- `auto_delete` - (Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. +- `created_at` - (String) The date and time that the cluster network interface was created. +- `enable_infrastructure_nat` - (Boolean) If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations. +- `href` - (String) The URL for this cluster network interface. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network interface. +- `mac_address` - (String) The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`. +- `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. +- `primary_ip` - (List) The cluster network subnet reserved IP for this cluster network interface. + Nested schema for **primary_ip**: + - `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (String) The resource type. +- `subnet` - (List) + Nested schema for **subnet**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (String) The resource type. +- `target` - (List) The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + Nested schema for **target**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. +- `vpc` - (List) The VPC this cluster network interface resides in. + Nested schema for **vpc**: + - `crn` - (String) The CRN for this VPC. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this VPC. + - `id` - (String) The unique identifier for this VPC. + - `name` - (String) The name for this VPC. The name is unique across all VPCs in the region. + - `resource_type` - (String) The resource type. +- `zone` - (List) The zone this cluster network interface resides in. + Nested schema for **zone**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_cluster_network_interfaces.html.markdown b/website/docs/d/is_cluster_network_interfaces.html.markdown new file mode 100644 index 0000000000..b8f8b6ffcf --- /dev/null +++ b/website/docs/d/is_cluster_network_interfaces.html.markdown @@ -0,0 +1,90 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_interfaces" +description: |- + Get information about ClusterNetworkInterfaceCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_interfaces + +Provides a read-only data source to retrieve information about a ClusterNetworkInterfaceCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_interfaces" "is_cluster_network_interfaces_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `name` - (Optional, String) Filters the collection to resources with a `name` property matching the exact specified name. +- `sort` - (Optional, String) Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkInterfaceCollection. +- `interfaces` - (List) A page of cluster network interfaces. + Nested schema for **interfaces**: + - `allow_ip_spoofing` - (Boolean) Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface. + - `auto_delete` - (Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. + - `created_at` - (String) The date and time that the cluster network interface was created. + - `enable_infrastructure_nat` - (Boolean) If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + - `lifecycle_state` - (String) The lifecycle state of the cluster network interface. + - `mac_address` - (String) The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `primary_ip` - (List) The cluster network subnet reserved IP for this cluster network interface. + Nested schema for **primary_ip**: + - `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (String) The resource type. + - `resource_type` - (String) The resource type. + - `subnet` - (List) + Nested schema for **subnet**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (String) The resource type. + - `target` - (List) The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + Nested schema for **target**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. + - `vpc` - (List) The VPC this cluster network interface resides in. + Nested schema for **vpc**: + - `crn` - (String) The CRN for this VPC. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this VPC. + - `id` - (String) The unique identifier for this VPC. + - `name` - (String) The name for this VPC. The name is unique across all VPCs in the region. + - `resource_type` - (String) The resource type. + - `zone` - (List) The zone this cluster network interface resides in. + Nested schema for **zone**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_cluster_network_profile.html.markdown b/website/docs/d/is_cluster_network_profile.html.markdown new file mode 100644 index 0000000000..0c38c33bf0 --- /dev/null +++ b/website/docs/d/is_cluster_network_profile.html.markdown @@ -0,0 +1,44 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_profile" +description: |- + Get information about ClusterNetworkProfile +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_profile + +Provides a read-only data source to retrieve information about a ClusterNetworkProfile. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_profile" "is_cluster_network_profile" { + name = "h100" +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `name` - (Required, Forces new resource, String) The cluster network profile name. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkProfile.(same as `name`) +- `family` - (String) The product family this cluster network profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. +- `href` - (String) The URL for this cluster network profile. +- `resource_type` - (String) The resource type. +- `supported_instance_profiles` - (List) The instance profiles that support this cluster network profile. + Nested schema for **supported_instance_profiles**: + - `href` - (String) The URL for this virtual server instance profile. + - `name` - (String) The globally unique name for this virtual server instance profile. + - `resource_type` - (String) The resource type. +- `zones` - (List) Zones in this region that support this cluster network profile. + Nested schema for **zones**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_cluster_network_profiles.html.markdown b/website/docs/d/is_cluster_network_profiles.html.markdown new file mode 100644 index 0000000000..4eefaeb19f --- /dev/null +++ b/website/docs/d/is_cluster_network_profiles.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_profiles" +description: |- + Get information about ClusterNetworkProfileCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_profiles + +Provides a read-only data source to retrieve information about a ClusterNetworkProfileCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_profiles" "is_cluster_network_profiles" { +} +``` + + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkProfileCollection. +- `profiles` - (List) A page of cluster network profiles. + + Nested schema for **profiles**: + - `family` - (String) The product family this cluster network profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `href` - (String) The URL for this cluster network profile. + - `name` - (String) The globally unique name for this cluster network profile. + - `resource_type` - (String) The resource type. + - `supported_instance_profiles` - (List) The instance profiles that support this cluster network profile. + Nested schema for **supported_instance_profiles**: + - `href` - (String) The URL for this virtual server instance profile. + - `name` - (String) The globally unique name for this virtual server instance profile. + - `resource_type` - (String) The resource type. + - `zones` - (List) Zones in this region that support this cluster network profile. + + Nested schema for **zones**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_cluster_network_subnet.html.markdown b/website/docs/d/is_cluster_network_subnet.html.markdown new file mode 100644 index 0000000000..ee5de289b0 --- /dev/null +++ b/website/docs/d/is_cluster_network_subnet.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnet" +description: |- + Get information about ClusterNetworkSubnet +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnet + +Provides a read-only data source to retrieve information about a ClusterNetworkSubnet. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `cluster_network_subnet_id` - (Required, Forces new resource, String) The cluster network subnet identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnet. +- `available_ipv4_address_count` - (Integer) The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider. +- `created_at` - (String) The date and time that the cluster network subnet was created. +- `href` - (String) The URL for this cluster network subnet. +- `ip_version` - (String) The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. +- `ipv4_cidr_block` - (String) The IPv4 range of this cluster network subnet, expressed in CIDR format. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network subnet. +- `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. +- `resource_type` - (String) The resource type. +- `total_ipv4_address_count` - (Integer) The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses. + diff --git a/website/docs/d/is_cluster_network_subnet_reserved_ip.html.markdown b/website/docs/d/is_cluster_network_subnet_reserved_ip.html.markdown new file mode 100644 index 0000000000..56186b6b1f --- /dev/null +++ b/website/docs/d/is_cluster_network_subnet_reserved_ip.html.markdown @@ -0,0 +1,58 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnet_reserved_ip" +description: |- + Get information about ClusterNetworkSubnetReservedIP +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnet_reserved_ip + +Provides a read-only data source to retrieve information about a ClusterNetworkSubnetReservedIP. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id =ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + cluster_network_subnet_reserved_ip_id = ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip_instance.cluster_network_subnet_reserved_ip_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `cluster_network_subnet_id` - (Required, Forces new resource, String) The cluster network subnet identifier. +- `cluster_network_subnet_reserved_ip_id` - (Required, Forces new resource, String) The cluster network subnet reserved IP identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnetReservedIP. +- `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. +- `auto_delete` - (Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. +- `created_at` - (String) The date and time that the cluster network subnet reserved IP was created. +- `href` - (String) The URL for this cluster network subnet reserved IP. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network subnet reserved IP. +- `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. +- `owner` - (String) The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. +- `resource_type` - (String) The resource type. +- `target` - (List) The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound. + Nested schema for **target**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `resource_type` - (String) The resource type. + diff --git a/website/docs/d/is_cluster_network_subnet_reserved_ips.html.markdown b/website/docs/d/is_cluster_network_subnet_reserved_ips.html.markdown new file mode 100644 index 0000000000..b8726a99ce --- /dev/null +++ b/website/docs/d/is_cluster_network_subnet_reserved_ips.html.markdown @@ -0,0 +1,61 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnet_reserved_ips" +description: |- + Get information about ClusterNetworkSubnetReservedIPCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnet_reserved_ips + +Provides a read-only data source to retrieve information about a ClusterNetworkSubnetReservedIPCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_subnet_reserved_ips" "is_cluster_network_subnet_reserved_ips_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id + cluster_network_subnet_id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `cluster_network_subnet_id` - (Required, Forces new resource, String) The cluster network subnet identifier. +- `name` - (Optional, String) Filters the collection to resources with a `name` property matching the exact specified name. +- `sort` - (Optional, String) Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnetReservedIPCollection. +- `reserved_ips` - (List) A page of reserved IPs for the cluster network subnet. + Nested schema for **reserved_ips**: + - `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `auto_delete` - (Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. + - `created_at` - (String) The date and time that the cluster network subnet reserved IP was created. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + - `lifecycle_state` - (String) The lifecycle state of the cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `owner` - (String) The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `resource_type` - (String) The resource type. + - `target` - (List) The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound. + Nested schema for **target**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `resource_type` - (String) The resource type. + diff --git a/website/docs/d/is_cluster_network_subnets.html.markdown b/website/docs/d/is_cluster_network_subnets.html.markdown new file mode 100644 index 0000000000..78a5c442bc --- /dev/null +++ b/website/docs/d/is_cluster_network_subnets.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnets" +description: |- + Get information about ClusterNetworkSubnetCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnets + +Provides a read-only data source to retrieve information about a ClusterNetworkSubnetCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_network_subnets" "is_cluster_network_subnets_instance" { + cluster_network_id = ibm_is_cluster_network.is_cluster_network_instance.id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `name` - (Optional, String) Filters the collection to resources with a `name` property matching the exact specified name. +- `sort` - (Optional, String) Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnetCollection. +- `subnets` - (List) A page of subnets for the cluster network. + + Nested schema for **subnets**: + - `available_ipv4_address_count` - (Integer) The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider. + - `created_at` - (String) The date and time that the cluster network subnet was created. + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `ip_version` - (String) The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `ipv4_cidr_block` - (String) The IPv4 range of this cluster network subnet, expressed in CIDR format. + - `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + - `lifecycle_state` - (String) The lifecycle state of the cluster network subnet. + - `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (String) The resource type. + - `total_ipv4_address_count` - (Integer) The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses. + diff --git a/website/docs/d/is_cluster_networks.html.markdown b/website/docs/d/is_cluster_networks.html.markdown new file mode 100644 index 0000000000..5200b1998e --- /dev/null +++ b/website/docs/d/is_cluster_networks.html.markdown @@ -0,0 +1,79 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_networks" +description: |- + Get information about ClusterNetworkCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_networks + +Provides a read-only data source to retrieve information about a ClusterNetworkCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_cluster_networks" "is_cluster_networks_instance" { +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `name` - (Optional, String) Filters the collection to resources with a `name` property matching the exact specified name. +- `resource_group_id` - (Optional, String) Filters the collection to resources with a `resource_group.id` property matching the specified identifier. +- `sort` - (Optional, String) Sorts the returned collection by the specified property name in ascending order. A `-` may be prepended to the name to sort in descending order. For example, the value `-created_at` sorts the collection by the `created_at` property in descending order, and the value `name` sorts it by the `name` property in ascending order. +- `vpc_crn` - (Optional, String) Filters the collection to cluster networks with a `vpc.crn` property matching the specified CRN. +- `vpc_id` - (Optional, String) Filters the collection to cluster networks with a `vpc.id` property matching the specified id. +- `vpc_name` - (Optional, String) Filters the collection to cluster networks with a `vpc.name` property matching the specified name. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the ClusterNetworkCollection. +- `cluster_networks` - (List) A page of cluster networks. + + Nested schema for **cluster_networks**: + - `created_at` - (String) The date and time that the cluster network was created. + - `crn` - (String) The CRN for this cluster network. + - `href` - (String) The URL for this cluster network. + - `id` - (String) The unique identifier for this cluster network. + - `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + - `lifecycle_state` - (String) The lifecycle state of the cluster network. + - `name` - (String) The name for this cluster network. The name must not be used by another cluster network in the region. + - `profile` - (List) The profile for this cluster network. + Nested schema for **profile**: + - `href` - (String) The URL for this cluster network profile. + - `name` - (String) The globally unique name for this cluster network profile. + - `resource_type` - (String) The resource type. + - `resource_group` - (List) The resource group for this cluster network. + Nested schema for **resource_group**: + - `href` - (String) The URL for this resource group. + - `id` - (String) The unique identifier for this resource group. + - `name` - (String) The name for this resource group. + - `resource_type` - (String) The resource type. + - `subnet_prefixes` - (List) The IP address ranges available for subnets for this cluster network. + Nested schema for **subnet_prefixes**: + - `allocation_policy` - (String) The allocation policy for this subnet prefix:- `auto`: Subnets created by total count in this cluster network can use this prefix. + - `cidr` - (String) The CIDR block for this prefix. + - `vpc` - (List) The VPC this cluster network resides in. + Nested schema for **vpc**: + - `crn` - (String) The CRN for this VPC. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this VPC. + - `id` - (String) The unique identifier for this VPC. + - `name` - (String) The name for this VPC. The name is unique across all VPCs in the region. + - `resource_type` - (String) The resource type. + - `zone` - (List) The zone this cluster network resides in. + Nested schema for **zone**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + diff --git a/website/docs/d/is_instance.html.markdown b/website/docs/d/is_instance.html.markdown index 8cacbc87cb..18b9c10a9b 100644 --- a/website/docs/d/is_instance.html.markdown +++ b/website/docs/d/is_instance.html.markdown @@ -127,7 +127,24 @@ In addition to all argument reference list, you can access the following attribu - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and provides some supplementary information. Nested schema for `deleted`: - `more_info` - (String) Link to documentation about deleted resources. - + +- `cluster_network` - (List) If present, the cluster network that this virtual server instance resides in. + Nested schema for **cluster_network**: + - `crn` - (String) The CRN for this cluster network. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network. + - `id` - (String) The unique identifier for this cluster network. + - `name` - (String) The name for this cluster network. The name must not be used by another cluster network in the region. + - `resource_type` - (String) The resource type. +- `cluster_network_attachments` - (List) The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration. + Nested schema for **cluster_network_attachments**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. + - `confidential_compute_mode` - (String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. - `crn` - (String) The CRN of the instance. - `disks` - (List) Collection of the instance's disks. Nested `disks` blocks has the following structure: diff --git a/website/docs/d/is_instance_cluster_network_attachment.html.markdown b/website/docs/d/is_instance_cluster_network_attachment.html.markdown new file mode 100644 index 0000000000..7fa28f4624 --- /dev/null +++ b/website/docs/d/is_instance_cluster_network_attachment.html.markdown @@ -0,0 +1,78 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_instance_cluster_network_attachment" +description: |- + Get information about InstanceClusterNetworkAttachment +subcategory: "VPC infrastructure" +--- + +# ibm_is_instance_cluster_network_attachment + +Provides a read-only data source to retrieve information about an InstanceClusterNetworkAttachment. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment" { + instance_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_id + instance_cluster_network_attachment_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_cluster_network_attachment_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `instance_id` - (Required, Forces new resource, String) The virtual server instance identifier. +- `instance_cluster_network_attachment_id` - (Required, Forces new resource, String) The instance cluster network attachment identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the InstanceClusterNetworkAttachment. +- `before` - (List) The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment. + Nested schema for **before**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. +- `cluster_network_interface` - (List) The cluster network interface for this instance cluster network attachment. + Nested schema for **cluster_network_interface**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `primary_ip` - (List) The primary IP for this cluster network interface. + Nested schema for **primary_ip**: + - `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (String) The resource type. + - `resource_type` - (String) The resource type. + - `subnet` - (List) + Nested schema for **subnet**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (String) The resource type. +- `href` - (String) The URL for this instance cluster network attachment. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the instance cluster network attachment. +- `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. +- `resource_type` - (String) The resource type. + diff --git a/website/docs/d/is_instance_cluster_network_attachments.html.markdown b/website/docs/d/is_instance_cluster_network_attachments.html.markdown new file mode 100644 index 0000000000..390221683a --- /dev/null +++ b/website/docs/d/is_instance_cluster_network_attachments.html.markdown @@ -0,0 +1,83 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_instance_cluster_network_attachments" +description: |- + Get information about InstanceClusterNetworkAttachmentCollection +subcategory: "VPC infrastructure" +--- + +# ibm_is_instance_cluster_network_attachments + +Provides a read-only data source to retrieve information about an InstanceClusterNetworkAttachmentCollection. You can then reference the fields of the data source in other resources within the same configuration by using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_is_instance_cluster_network_attachments" "is_instance_cluster_network_attachments" { + instance_id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_id +} +``` + +## Argument Reference + +You can specify the following arguments for this data source. + +- `instance_id` - (Required, Forces new resource, String) The virtual server instance identifier. + +## Attribute Reference + +After your data source is created, you can read values from the following attributes. + +- `id` - The unique identifier of the InstanceClusterNetworkAttachmentCollection. +- `cluster_network_attachments` - (List) A page of ordered cluster network attachments (sorted based on the `before` property) for the instance. A cluster network attachment represents a device to which a cluster network interface is attached. + Nested schema for **cluster_network_attachments**: + - `before` - (List) The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment. + + Nested schema for **before**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. + - `cluster_network_interface` - (List) The cluster network interface for this instance cluster network attachment. + Nested schema for **cluster_network_interface**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `primary_ip` - (List) The primary IP for this cluster network interface. + Nested schema for **primary_ip**: + - `address` - (String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (String) The resource type. + - `resource_type` - (String) The resource type. + - `subnet` - (List) + + Nested schema for **subnet**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (String) The resource type. + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + - `lifecycle_state` - (String) The lifecycle state of the instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. + diff --git a/website/docs/d/is_instance_profile.html.markdown b/website/docs/d/is_instance_profile.html.markdown index 33240b04b0..7d9c593aba 100644 --- a/website/docs/d/is_instance_profile.html.markdown +++ b/website/docs/d/is_instance_profile.html.markdown @@ -53,6 +53,16 @@ In addition to the argument reference list, you can access the following attribu - `value` - (String) The value for this profile field. - `values` - (String) The permitted values for this profile field. +- `cluster_network_attachment_count` - (List) Nested `cluster_network_attachment_count` blocks have the following structure: + + Nested schema for **cluster_network_attachment_count**: + - `default` - (Integer) + - `max` - (Integer) The maximum value for this profile field. + - `min` - (Integer) The minimum value for this profile field. + - `step` - (Integer) + - `type` - (String) The type for this profile field. + - `values` - (List) The permitted values for this profile field. + - `confidential_compute_modes` - (List) Nested schema for **confidential_compute_modes**: @@ -167,6 +177,13 @@ In addition to the argument reference list, you can access the following attribu - `type` - (String) The type for this profile field. - `values` - (List) The supported `enable_secure_boot` values for an instance using this profile. +- `supported_cluster_network_profiles` - (List) The cluster network profiles that support this instance profile. + + Nested schema for **supported_cluster_network_profiles**: + - `href` - (String) The URL for this cluster network profile. + - `name` - (String) The globally unique name for this cluster network profile. + - `resource_type` - (String) The resource type. + - `vcpu_architecture` - (List) Nested `vcpu_architecture` blocks have the following structure: Nested scheme for `vcpu_architecture`: diff --git a/website/docs/d/is_instance_profiles.html.markdown b/website/docs/d/is_instance_profiles.html.markdown index f5519db608..5bbc7a3b17 100644 --- a/website/docs/d/is_instance_profiles.html.markdown +++ b/website/docs/d/is_instance_profiles.html.markdown @@ -50,6 +50,17 @@ You can access the following attribute references after your data source is crea - `type` - (String) The type for this profile field. - `value` - (String) The value for this profile field. - `values` - (String) The permitted values for this profile field. + + - `cluster_network_attachment_count` - (List) Nested `cluster_network_attachment_count` blocks have the following structure: + + Nested schema for **cluster_network_attachment_count**: + - `default` - (Integer) + - `max` - (Integer) The maximum value for this profile field. + - `min` - (Integer) The minimum value for this profile field. + - `step` - (Integer) + - `type` - (String) The type for this profile field. + - `values` - (List) The permitted values for this profile field. + - `confidential_compute_modes` - (List) Nested schema for **confidential_compute_modes**: @@ -160,13 +171,21 @@ You can access the following attribute references after your data source is crea Nested scheme for `port_speed`: - `type` - (String) The type for this profile field. - `value` - (String) The value for this profile field. - - `secure_boot_modes` - (List) + - `secure_boot_modes` - (List) Nested schema for **secure_boot_modes**: - `default` - (Boolean) The default secure boot mode for this profile. - `type` - (String) The type for this profile field. - `values` - (List) The supported `enable_secure_boot` values for an instance using this profile. - + + - `supported_cluster_network_profiles` - (List) The cluster network profiles that support this instance profile. + + Nested schema for **supported_cluster_network_profiles**: + - `href` - (String) The URL for this cluster network profile. + - `name` - (String) The globally unique name for this cluster network profile. + - `resource_type` - (String) The resource type. + + - `vcpu_architecture` - (List) Nested `vcpu_architecture` blocks have the following structure: Nested scheme for `vcpu_architecture`: diff --git a/website/docs/d/is_instance_template.html.markdown b/website/docs/d/is_instance_template.html.markdown index ac4b54dfec..3e3ca26037 100644 --- a/website/docs/d/is_instance_template.html.markdown +++ b/website/docs/d/is_instance_template.html.markdown @@ -57,6 +57,27 @@ You can access the following attribute references after your data source is crea - `profile` - (String) The profile for the boot volume configuration. - `size` - (String) The boot volume size to configure in giga bytes. - `tags` - (String) User Tags associated with the boot_volume. (https://cloud.ibm.com/apidocs/tagging#types-of-tags) +- `cluster_network_attachments` - (List) The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started. + Nested schema for **cluster_network_attachments**: + - `cluster_network_interface` - (List) A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance. + Nested schema for **cluster_network_interface**: + - `auto_delete` - (Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `primary_ip` - (List) The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved. + Nested schema for **primary_ip**: + - `address` - (String) The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected. + - `auto_delete` - (Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `subnet` - (List) The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity. + Nested schema for **subnet**: + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. + - `confidential_compute_mode` - (String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. - `catalog_offering` - (List) The [catalog](https://cloud.ibm.com/docs/account?topic=account-restrict-by-user&interface=ui) offering or offering version to use when provisioning this virtual server instance. If an offering is specified, the latest version of that offering will be used. The specified offering or offering version may be in a different account in the same [enterprise](https://cloud.ibm.com/docs/account?topic=account-what-is-enterprise), subject to IAM policies. diff --git a/website/docs/d/is_instance_templates.html.markdown b/website/docs/d/is_instance_templates.html.markdown index 9a746a15c7..4e99bad094 100644 --- a/website/docs/d/is_instance_templates.html.markdown +++ b/website/docs/d/is_instance_templates.html.markdown @@ -44,6 +44,28 @@ You can access the following attribute references after your data source is crea - `profile` - (String) The profile for the boot volume configuration. - `size` - (String) The boot volume size to configure in giga bytes. - `tags` - (String) User Tags associated with the volume. (https://cloud.ibm.com/apidocs/tagging#types-of-tags). + + - `cluster_network_attachments` - (List) The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started. + Nested schema for **cluster_network_attachments**: + - `cluster_network_interface` - (List) A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance. + Nested schema for **cluster_network_interface**: + - `auto_delete` - (Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `primary_ip` - (List) The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved. + Nested schema for **primary_ip**: + - `address` - (String) The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected. + - `auto_delete` - (Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. + - `href` - (String) The URL for this cluster network subnet reserved IP. + - `id` - (String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (String) The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `subnet` - (List) The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity. + Nested schema for **subnet**: + - `href` - (String) The URL for this cluster network subnet. + - `id` - (String) The unique identifier for this cluster network subnet. + - `name` - (String) The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. + - `confidential_compute_mode` - (String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. - `catalog_offering` - (List) The [catalog](https://cloud.ibm.com/docs/account?topic=account-restrict-by-user&interface=ui) offering or offering version to use when provisioning this virtual server instance. If an offering is specified, the latest version of that offering will be used. The specified offering or offering version may be in a different account in the same [enterprise](https://cloud.ibm.com/docs/account?topic=account-what-is-enterprise), subject to IAM policies. diff --git a/website/docs/d/is_instances.html.markdown b/website/docs/d/is_instances.html.markdown index 7c3ca0f75f..32fd8110be 100644 --- a/website/docs/d/is_instances.html.markdown +++ b/website/docs/d/is_instances.html.markdown @@ -77,7 +77,26 @@ In addition to all argument reference list, you can access the following attribu - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and provides some supplementary information. Nested schema for `deleted`: - `more_info` - (String) Link to documentation about deleted resources. - + + - `cluster_network` - (List) If present, the cluster network that this virtual server instance resides in. + Nested schema for **cluster_network**: + - `crn` - (String) The CRN for this cluster network. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network. + - `id` - (String) The unique identifier for this cluster network. + - `name` - (String) The name for this cluster network. The name must not be used by another cluster network in the region. + - `resource_type` - (String) The resource type. + - `cluster_network_attachments` - (List) The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration. + + Nested schema for **cluster_network_attachments**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. + + - `confidential_compute_mode` - (String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. - `crn` - (String) The CRN of the instance. - `disks` - (List) Collection of the instance's disks. Nested `disks` blocks has the following structure: diff --git a/website/docs/r/is_cluster_network.html.markdown b/website/docs/r/is_cluster_network.html.markdown new file mode 100644 index 0000000000..abac3a7333 --- /dev/null +++ b/website/docs/r/is_cluster_network.html.markdown @@ -0,0 +1,75 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network" +description: |- + Manages ClusterNetwork. +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network + +Create, update, and delete ClusterNetworks with this resource. + +## Example Usage + +```hcl +resource "ibm_is_cluster_network" "example" { + name = "my-cluster-network" + profile = "h100" + resource_group = "fee82deba12e4c0fb69c3b09d1f12345" + subnet_prefixes { + cidr = "10.0.0.0/24" + } + vpc { + id = "r006-4727d842-f94f-4a2d-824a-9bc9b02c523b" + } + zone = "us-east-3" +} + +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +- `name` - (Optional, String) The name for this cluster network. The name must not be used by another cluster network in the region. +- `profile` - (Required, String) The profile (globally unique name for the cluster network profile) for this cluster network. +- `resource_group` - (Optional, String) The resource group (unique identifier for the resource group) for this cluster network. +- `subnet_prefixes` - (Optional, List) The IP address ranges available for subnets for this cluster network.(The maximum length is `1` item. The minimum length is `1` item.) + Nested schema for **subnet_prefixes**: + - `cidr` - (Required, String) The CIDR block for this prefix. +- `vpc` - (Required, List) The VPC this cluster network resides in. + Nested schema for **vpc**: + - `id` - (Required, String) The unique identifier for this VPC. +- `zone` - (Required, List) The zone (globally unique name for this zone) this cluster network resides in. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +- `id` - The unique identifier of the ClusterNetwork. +- `created_at` - (String) The date and time that the cluster network was created. +- `crn` - (String) The CRN for this cluster network. +- `href` - (String) The URL for this cluster network. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `internal_error`, `resource_suspended_by_provider`. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network. Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. +- `resource_type` - (String) The resource type. Allowable values are: `cluster_network`. +- `etag` - ETag identifier for ClusterNetwork. + +## Import + +You can import the `ibm_is_cluster_network` resource by using `id`. The unique identifier for this cluster network. + +# Syntax +
+$ terraform import ibm_is_cluster_network.is_cluster_network <id>
+
+ +# Example +``` +$ terraform import ibm_is_cluster_network.is_cluster_network 0717-da0df18c-7598-4633-a648-fdaac28a5573 +``` diff --git a/website/docs/r/is_cluster_network_interface.html.markdown b/website/docs/r/is_cluster_network_interface.html.markdown new file mode 100644 index 0000000000..e59b4a85f3 --- /dev/null +++ b/website/docs/r/is_cluster_network_interface.html.markdown @@ -0,0 +1,106 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_interface" +description: |- + Manages ClusterNetworkInterface. +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_interface + +Create, update, and delete ClusterNetworkInterfaces with this resource. + +## Example Usage + +```hcl +resource "ibm_is_cluster_network_interface" "is_cluster_network_interface_instance" { + cluster_network_id = "cluster_network_id" + name = "my-cluster-network-interface" + primary_ip { + address = "10.1.0.6" + name = "my-cluster-network-subnet-reserved-ip" + } + subnet { + id = "0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930" + } +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `name` - (Optional, String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. +- `primary_ip` - (Optional, List) The cluster network subnet reserved IP for this cluster network interface. + + Nested schema for **primary_ip**: + - `address` - (Required, String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `href` - (Required, String) The URL for this cluster network subnet reserved IP. + - `id` - (Required, String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (Required, String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (Computed, String) The resource type. Allowable values are: `cluster_network_subnet_reserved_ip`. +- `subnet` - (Optional, List) The associated cluster network subnet. Required if `primary_ip` does not specify a clusternetwork subnet reserved IP identity. + + Nested schema for **subnet**: + - `href` - (Required, String) The URL for this cluster network subnet. + - `id` - (Required, String) The unique identifier for this cluster network subnet. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +- `id` - The unique identifier of the ClusterNetworkInterface. +- `allow_ip_spoofing` - (Boolean) Indicates whether source IP spoofing is allowed on this cluster network interface. If `false`, source IP spoofing is prevented on this cluster network interface. If `true`, source IP spoofing is allowed on this cluster network interface. +- `auto_delete` - (Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. +- `created_at` - (String) The date and time that the cluster network interface was created. +- `enable_infrastructure_nat` - (Boolean) If `true`:- The VPC infrastructure performs any needed NAT operations.- `floating_ips` must not have more than one floating IP.If `false`:- Packets are passed unchanged to/from the virtual network interface, allowing the workload to perform any needed NAT operations. +- `href` - (String) The URL for this cluster network interface. +- `cluster_network_interface_id` - (String) The unique identifier for this cluster network interface. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `internal_error`, `resource_suspended_by_provider`. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network interface. Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. +- `mac_address` - (String) The MAC address of the cluster network interface. May be absent if`lifecycle_state` is `pending`. +- `protocol_state_filtering_mode` - (String) The protocol state filtering mode used for this cluster network interface.Protocol state filtering monitors each network connection flowing over this cluster network interface, and drops any packets that are invalid based on the current connection state and protocol. See [Protocol state filtering mode](https://cloud.ibm.com/docs/vpc?topic=vpc-vni-about#protocol-state-filtering) for more information.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. The default value is `enabled`. Allowable values are: `disabled`, `enabled`. The maximum length is `128` characters. +- `resource_type` - (String) The resource type. llowable values are: `cluster_network_interface`. +- `target` - (List) The target of this cluster network interface.If absent, this cluster network interface is not attached to a target.The resources supported by this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + Nested schema for **target**: + - `href` - (String) The URL for this instance cluster network attachment. + - `id` - (String) The unique identifier for this instance cluster network attachment. + - `name` - (String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (String) The resource type. Allowable values are: `instance_cluster_network_attachment`. +- `vpc` - (List) The VPC this cluster network interface resides in. + Nested schema for **vpc**: + - `crn` - (String) The CRN for this VPC. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this VPC. + - `id` - (String) The unique identifier for this VPC. + - `name` - (String) The name for this VPC. The name is unique across all VPCs in the region. + - `resource_type` - (String) The resource type. Allowable values are: `vpc`. +- `zone` - (List) The zone this cluster network interface resides in. + Nested schema for **zone**: + - `href` - (String) The URL for this zone. + - `name` - (String) The globally unique name for this zone. + +- `etag` - ETag identifier for ClusterNetworkInterface. + +## Import + +You can import the `ibm_is_cluster_network_interface` resource by using `id`. +The `id` property can be formed from `cluster_network_id`, and `cluster_network_interface_id` in the following format: + +
+<cluster_network_id>/<cluster_network_interface_id>
+
+- `cluster_network_id`: A string. The cluster network identifier. +- `cluster_network_interface_id`: A string in the format `0717-ffc092f7-5d02-4b93-ab69-26860529b9fb`. The unique identifier for this cluster network interface. + +# Syntax +
+$ terraform import ibm_is_cluster_network_interface.is_cluster_network_interface <cluster_network_id>/<cluster_network_interface_id>
+
diff --git a/website/docs/r/is_cluster_network_subnet.html.markdown b/website/docs/r/is_cluster_network_subnet.html.markdown new file mode 100644 index 0000000000..fa09a28695 --- /dev/null +++ b/website/docs/r/is_cluster_network_subnet.html.markdown @@ -0,0 +1,73 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnet" +description: |- + Manages ClusterNetworkSubnet. +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnet + +Create, update, and delete ClusterNetworkSubnets with this resource. + +## Example Usage + +```hcl +resource "ibm_is_cluster_network_subnet" "is_cluster_network_subnet_instance" { + cluster_network_id = "cluster_network_id" + ip_version = "ipv4" + ipv4_cidr_block = "10.0.0.0/24" + name = "my-cluster-network-subnet" + # total_ipv4_address_count = 256 // either ipv4_cidr_block or total_ipv4_address_count +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `ip_version` - (Optional, String) The IP version for this cluster network subnet.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `ipv4`. +- `ipv4_cidr_block` - (Optional, String) The IPv4 range of this cluster network subnet, expressed in CIDR format. +- `name` - (Optional, String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. +- `total_ipv4_address_count` - (Optional, Integer) The total number of IPv4 addresses in this cluster network subnet.Note: This is calculated as 2(32 - prefix length). For example, the prefix length `/24` gives:
2(32 - 24) = 28 = 256 addresses. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnet. +- `available_ipv4_address_count` - (Integer) The number of IPv4 addresses in this cluster network subnet that are not in use, and have not been reserved by the user or the provider. +- `created_at` - (String) The date and time that the cluster network subnet was created. +- `href` - (String) The URL for this cluster network subnet. +- `cluster_network_subnet_id` - (String) The unique identifier for this cluster network subnet. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. + * Constraints: Allowable values are: `internal_error`, `resource_suspended_by_provider`. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. + * Constraints: The maximum length is `8000` characters. The minimum length is `10` characters. The value must match regular expression `/^http(s)?:\/\/([^\/?#]*)([^?#]*)(\\?([^#]*))?(#(.*))?$/`. +- `lifecycle_state` - (String) The lifecycle state of the cluster network subnet. + * Constraints: Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. +- `resource_type` - (String) The resource type. + * Constraints: Allowable values are: `cluster_network_subnet`. + +- `etag` - ETag identifier for ClusterNetworkSubnet. + +## Import + +You can import the `ibm_is_cluster_network_subnet` resource by using `id`. +The `id` property can be formed from `cluster_network_id`, and `cluster_network_subnet_id` in the following format: + +
+<cluster_network_id>/<cluster_network_subnet_id>
+
+- `cluster_network_id`: A string. The cluster network identifier. +- `cluster_network_subnet_id`: A string in the format `0717-7931845c-65c4-4b0a-80cd-7d9c1a6d7930`. The unique identifier for this cluster network subnet. + +# Syntax +
+$ terraform import ibm_is_cluster_network_subnet.is_cluster_network_subnet <cluster_network_id>/<cluster_network_subnet_id>
+
diff --git a/website/docs/r/is_cluster_network_subnet_reserved_ip.html.markdown b/website/docs/r/is_cluster_network_subnet_reserved_ip.html.markdown new file mode 100644 index 0000000000..cf0e0be579 --- /dev/null +++ b/website/docs/r/is_cluster_network_subnet_reserved_ip.html.markdown @@ -0,0 +1,76 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_cluster_network_subnet_reserved_ip" +description: |- + Manages ClusterNetworkSubnetReservedIP. +subcategory: "VPC infrastructure" +--- + +# ibm_is_cluster_network_subnet_reserved_ip + +Create, update, and delete ClusterNetworkSubnetReservedIPs with this resource. + +## Example Usage + +```hcl +resource "ibm_is_cluster_network_subnet_reserved_ip" "is_cluster_network_subnet_reserved_ip_instance" { + address = "192.168.3.4" + cluster_network_id = "cluster_network_id" + cluster_network_subnet_id = "cluster_network_subnet_id" + name = "my-cluster-network-subnet-reserved-ip" +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +- `address` - (Optional, String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. +- `cluster_network_id` - (Required, Forces new resource, String) The cluster network identifier. +- `cluster_network_subnet_id` - (Required, Forces new resource, String) The cluster network subnet identifier. +- `name` - (Optional, String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +- `id` - The unique identifier of the ClusterNetworkSubnetReservedIP. +- `auto_delete` - (Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. +- `created_at` - (String) The date and time that the cluster network subnet reserved IP was created. +- `href` - (String) The URL for this cluster network subnet reserved IP. +- `cluster_network_subnet_reserved_ip_id` - (String) The unique identifier for this cluster network subnet reserved IP. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `internal_error`, `resource_suspended_by_provider`. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the cluster network subnet reserved IP. Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. +- `owner` - (String) The owner of the cluster network subnet reserved IPThe enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `provider`, `user`. +- `resource_type` - (String) The resource type. Allowable values are: `cluster_network_subnet_reserved_ip`. +- `target` - (List) The target this cluster network subnet reserved IP is bound to.If absent, this cluster network subnet reserved IP is provider-owned or unbound. + Nested schema for **target**: + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network interface. + - `id` - (String) The unique identifier for this cluster network interface. + - `name` - (String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `resource_type` - (String) The resource type. Allowable values are: `cluster_network_interface`. +- `etag` - ETag identifier for ClusterNetworkSubnetReservedIP. + +## Import + +You can import the `ibm_is_cluster_network_subnet_reserved_ip` resource by using `id`. +The `id` property can be formed from `cluster_network_id`, `cluster_network_subnet_id`, and `cluster_network_subnet_reserved_ip_id` in the following format: + +
+<cluster_network_id>/<cluster_network_subnet_id>/<cluster_network_subnet_reserved_ip_id>
+
+- `cluster_network_id`: A string. The cluster network identifier. +- `cluster_network_subnet_id`: A string. The cluster network subnet identifier. +- `cluster_network_subnet_reserved_ip_id`: A string in the format `6d353a0f-aeb1-4ae1-832e-1110d10981bb`. The unique identifier for this cluster network subnet reserved IP. + +# Syntax +
+$ terraform import ibm_is_cluster_network_subnet_reserved_ip.is_cluster_network_subnet_reserved_ip <cluster_network_id>/<cluster_network_subnet_id>/<cluster_network_subnet_reserved_ip_id>
+
diff --git a/website/docs/r/is_instance.html.markdown b/website/docs/r/is_instance.html.markdown index eee5980d05..329a8e839c 100644 --- a/website/docs/r/is_instance.html.markdown +++ b/website/docs/r/is_instance.html.markdown @@ -486,6 +486,94 @@ resource "ibm_is_instance" "example" { } } ``` +### Example to create an instance with cluster network attachments ### + +```terraform + +resource "ibm_is_instance" "is_instance" { + name = "example-instance" + image = data.ibm_is_image.example.id + profile = "gx3d-160x1792x8h100" + primary_network_interface { + subnet = ibm_is_subnet.example.id + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-1" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-2" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-3" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-4" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-5" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-6" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-7" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + cluster_network_attachments { + cluster_network_interface{ + auto_delete = true + name = "cna-8" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + } + vpc = ibm_is_vpc.example.id + zone = ibm_is_subnet.example.zone + keys = [ibm_is_ssh_key.example.id] +} +``` ## Timeouts The `ibm_is_instance` resource provides the following [[Timeouts](https://www.terraform.io/docs/language/resources/syntax.html) configuration options: @@ -544,6 +632,15 @@ Review the argument references that you can specify for your resource. ~> **Note:** `offering_crn` conflicts with `version_crn`, both are mutually exclusive. `catalog_offering` and `image` id are mutually exclusive. `snapshot` conflicts with `image` id and `instance_template` + +- `cluster_network_attachments` - (Optional, List) The cluster network attachments for this virtual server instance.The cluster network attachments are ordered for consistent instance configuration. + + Nested schema for **cluster_network_attachments**: + - `href` - (Required, String) The URL for this instance cluster network attachment. + - `id` - (Required, String) The unique identifier for this instance cluster network attachment. + - `name` - (Required, String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (Required, String) The resource type. + - `confidential_compute_mode` - (Optional, String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. **Constraints: Allowable values are: `disabled`, `sgx`** {Select Availability} ~>**Note:** The confidential_compute_mode is `Select Availability` feature. Confidential computing with Intel SGX for VPC is available only in the US-South (Dallas) region. @@ -760,6 +857,18 @@ In addition to all argument reference list, you can access the following attribu - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and provides some supplementary information. Nested schema for `deleted`: - `more_info` - (String) Link to documentation about deleted resources. + +- `cluster_network` - (List) If present, the cluster network that this virtual server instance resides in. + Nested schema for **cluster_network**: + - `crn` - (String) The CRN for this cluster network. + - `deleted` - (List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (String) Link to documentation about deleted resources. + - `href` - (String) The URL for this cluster network. + - `id` - (String) The unique identifier for this cluster network. + - `name` - (String) The name for this cluster network. The name must not be used by another cluster network in the region. + - `resource_type` - (String) The resource type. + - `crn` - (String) The CRN of the instance. - `disks` - (List of Strings) The collection of the instance's disks. Nested `disks` blocks have the following structure: diff --git a/website/docs/r/is_instance_cluster_network_attachment.html.markdown b/website/docs/r/is_instance_cluster_network_attachment.html.markdown new file mode 100644 index 0000000000..cf48bd5263 --- /dev/null +++ b/website/docs/r/is_instance_cluster_network_attachment.html.markdown @@ -0,0 +1,218 @@ +--- +layout: "ibm" +page_title: "IBM : ibm_is_instance_cluster_network_attachment" +description: |- + Manages InstanceClusterNetworkAttachment. +subcategory: "VPC infrastructure" +--- + +# ibm_is_instance_cluster_network_attachment + +Create, update, and delete InstanceClusterNetworkAttachments with this resource. + +## Example Usage + +```hcl + +resource "ibm_is_instance_action" "is_instance_stop_before" { + action = "stop" + instance = ibm_is_instance.is_instance.id +} + +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance.is_instance.cluster_network_attachments.0.id + } + cluster_network_interface { + name = "my-cluster-network-interface" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-9" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance10" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface-10" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-10" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance11" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance10.instance_cluster_network_attachment_id +} + cluster_network_interface { + name = "my-cluster-network-interface-11" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-11" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance12" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance11.instance_cluster_network_attachment_id +} + cluster_network_interface { + name = "my-cluster-network-interface12" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-12" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance13" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance12.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface13" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-13" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance14" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance13.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface14" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-149" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance15" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance14.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface15" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-15" +} +resource "ibm_is_instance_cluster_network_attachment" "is_instance_cluster_network_attachment_instance16" { + depends_on = [ibm_is_instance_action.is_instance_stop_before] + instance_id = ibm_is_instance.is_instance.id + before { + id = ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance15.instance_cluster_network_attachment_id + } + cluster_network_interface { + name = "my-cluster-network-interface16" + subnet { + id = ibm_is_cluster_network_subnet.is_cluster_network_subnet_instance.cluster_network_subnet_id + } + } + name = "cna-16" +} +resource "ibm_is_instance_action" "is_instance_start_after" { + # depends_on = [ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment_instance16] + action = "start" + instance = ibm_is_instance.is_instance.id +} +``` + +## Argument Reference + +You can specify the following arguments for this resource. + +- `before` - (Optional, List) The instance cluster network attachment that is immediately before. If absent, this is thelast instance cluster network attachment. + Nested schema for **before**: + - `href` - (Required, String) The URL for this instance cluster network attachment. + - `id` - (Required, String) The unique identifier for this instance cluster network attachment. + - `name` - (Computed, String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + - `resource_type` - (Computed, String) The resource type. +- `cluster_network_interface` - (Required, List) The cluster network interface for this instance cluster network attachment. + + Nested schema for **cluster_network_interface**: + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Required, String) The URL for this cluster network interface. + - `id` - (Required, String) The unique identifier for this cluster network interface. + - `name` - (Required, String) The name for this cluster network interface. The name is unique across all interfaces in the cluster network. + - `primary_ip` - (Required, List) The primary IP for this cluster network interface. + + Nested schema for **primary_ip**: + - `address` - (Required, String) The IP address.If the address is pending allocation, the value will be `0.0.0.0`.This property may [expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) to support IPv6 addresses in the future. + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Required, String) The URL for this cluster network subnet reserved IP. + - `id` - (Required, String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (Required, String) The name for this cluster network subnet reserved IP. The name is unique across all reserved IPs in a cluster network subnet. + - `resource_type` - (Computed, String) The resource type. + - `resource_type` - (Computed, String) The resource type. + - `subnet` - (Required, List) + + Nested schema for **subnet**: + - `deleted` - (Optional, List) If present, this property indicates the referenced resource has been deleted, and providessome supplementary information. + + Nested schema for **deleted**: + - `more_info` - (Computed, String) Link to documentation about deleted resources. + - `href` - (Required, String) The URL for this cluster network subnet. + - `id` - (Required, String) The unique identifier for this cluster network subnet. + - `name` - (Computed, String) The name for this cluster network subnet. The name is unique across all cluster network subnets in the cluster network. + - `resource_type` - (Computed, String) The resource type. +- `instance_id` - (Required, Forces new resource, String) The virtual server instance identifier. +- `name` - (Optional, String) The name for this instance cluster network attachment. The name is unique across all network attachments for the instance. + +## Attribute Reference + +After your resource is created, you can read values from the listed arguments and the following attributes. + +- `id` - The unique identifier of the InstanceClusterNetworkAttachment. +- `href` - (String) The URL for this instance cluster network attachment. +- `instance_cluster_network_attachment_id` - (String) The unique identifier for this instance cluster network attachment. +- `lifecycle_reasons` - (List) The reasons for the current `lifecycle_state` (if any). + + Nested schema for **lifecycle_reasons**: + - `code` - (String) A reason code for this lifecycle state:- `internal_error`: internal error (contact IBM support)- `resource_suspended_by_provider`: The resource has been suspended (contact IBM support)The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future. Allowable values are: `internal_error`, `resource_suspended_by_provider`. + - `message` - (String) An explanation of the reason for this lifecycle state. + - `more_info` - (String) Link to documentation about the reason for this lifecycle state. +- `lifecycle_state` - (String) The lifecycle state of the instance cluster network attachment. Allowable values are: `deleting`, `failed`, `pending`, `stable`, `suspended`, `updating`, `waiting`. +- `resource_type` - (String) The resource type. Allowable values are: `instance_cluster_network_attachment`. + + +## Import + +You can import the `ibm_is_instance_cluster_network_attachment` resource by using `id`. +The `id` property can be formed from `instance_id`, and `instance_cluster_network_attachment_id` in the following format: + +
+<instance_id>/<instance_cluster_network_attachment_id>
+
+- `instance_id`: A string. The virtual server instance identifier. +- `instance_cluster_network_attachment_id`: A string in the format `0717-fb880975-db45-4459-8548-64e3995ac213`. The unique identifier for this instance cluster network attachment. + +# Syntax +
+$ terraform import ibm_is_instance_cluster_network_attachment.is_instance_cluster_network_attachment <instance_id>/<instance_cluster_network_attachment_id>
+
diff --git a/website/docs/r/is_instance_template.html.markdown b/website/docs/r/is_instance_template.html.markdown index bf0f679468..84ea67daeb 100644 --- a/website/docs/r/is_instance_template.html.markdown +++ b/website/docs/r/is_instance_template.html.markdown @@ -197,6 +197,64 @@ resource "ibm_is_instance_template" "example4" { delete_volume_on_instance_delete = true } } + +// cluster_network_attachments example + +resource "ibm_is_instance_template" "is_instance_template" { + name = "example-template" + image = data.ibm_is_image.example.id + profile = "gx3d-160x1792x8h100" + primary_network_attachment { + name = ""example-template-pna" + virtual_network_interface { + auto_delete = true + subnet = ibm_is_subnet.example.id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = ibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + cluster_network_attachments { + cluster_network_interface{ + id = VPCibm_is_cluster_network_interface.example.cluster_network_interface_id + } + } + vpc = ibm_is_vpc.example.id + zone = ibm_is_subnet.example.zone + keys = [ibm_is_ssh_key.example.id] +} ``` ## Argument reference Review the argument references that you can specify for your resource. @@ -220,6 +278,30 @@ Review the argument references that you can specify for your resource. - `version_crn` - (Optional, Force new resource, String) The CRN for this version of a catalog offering. Identifies a version of a catalog offering by this unique property. Conflicts with `catalog_offering.0.offering_crn` - `plan_crn` - (Optional, String) The CRN for this catalog offering version's billing plan. If unspecified, no billing plan will be used (free). Must be specified for catalog offering versions that require a billing plan to be used. +- `cluster_network_attachments` - (Optional, List) The cluster network attachments to create for this virtual server instance. A cluster network attachment represents a device that is connected to a cluster network. The number of network attachments must match one of the values from the instance profile's `cluster_network_attachment_count` before the instance can be started. + + Nested schema for **cluster_network_attachments**: + - `cluster_network_interface` - (Required, List) A cluster network interface for the instance cluster network attachment. This can bespecified using an existing cluster network interface that does not already have a `target`,or a prototype object for a new cluster network interface.This instance must reside in the same VPC as the specified cluster network interface. Thecluster network interface must reside in the same cluster network as the`cluster_network_interface` of any other `cluster_network_attachments` for this instance. + Nested schema for **cluster_network_interface**: + - `auto_delete` - (Optional, Boolean) Indicates whether this cluster network interface will be automatically deleted when `target` is deleted. + - `href` - (Optional, String) The URL for this cluster network interface. + - `id` - (Optional, String) The unique identifier for this cluster network interface. + - `name` - (Optional, String) The name for this cluster network interface. The name must not be used by another interface in the cluster network. Names beginning with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `primary_ip` - (Optional, List) The primary IP address to bind to the cluster network interface. May be eithera cluster network subnet reserved IP identity, or a cluster network subnet reserved IPprototype object which will be used to create a new cluster network subnet reserved IP.If a cluster network subnet reserved IP identity is provided, the specified clusternetwork subnet reserved IP must be unbound.If a cluster network subnet reserved IP prototype object with an address is provided,the address must be available on the cluster network interface's cluster networksubnet. If no address is specified, an available address on the cluster network subnetwill be automatically selected and reserved. + + Nested schema for **primary_ip**: + - `address` - (Optional, String) The IP address to reserve, which must not already be reserved on the subnet.If unspecified, an available address on the subnet will automatically be selected. + - `auto_delete` - (Optional, Boolean) Indicates whether this cluster network subnet reserved IP member will be automatically deleted when either `target` is deleted, or the cluster network subnet reserved IP is unbound. + - `href` - (Optional, String) The URL for this cluster network subnet reserved IP. + - `id` - (Optional, String) The unique identifier for this cluster network subnet reserved IP. + - `name` - (Optional, String) The name for this cluster network subnet reserved IP. The name must not be used by another reserved IP in the cluster network subnet. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. If unspecified, the name will be a hyphenated list of randomly-selected words. + - `subnet` - (Optional, List) The associated cluster network subnet. Required if `primary_ip` does not specify acluster network subnet reserved IP identity. + + Nested schema for **subnet**: + - `href` - (Optional, String) The URL for this cluster network subnet. + - `id` - (Optional, String) The unique identifier for this cluster network subnet. + - `name` - (Optional, String) The name for this cluster network attachment. Names must be unique within the instance the cluster network attachment resides in. If unspecified, the name will be a hyphenated list of randomly-selected words. Names starting with `ibm-` are reserved for provider-owned resources, and are not allowed. + - `confidential_compute_mode` - (Optional, String) The confidential compute mode to use for this virtual server instance.If unspecified, the default confidential compute mode from the profile will be used. **Constraints: Allowable values are: `disabled`, `sgx`** {Select Availability} ~>**Note:** The confidential_compute_mode is `Select Availability` feature. Confidential computing with Intel SGX for VPC is available only in the US-South (Dallas) region.