diff --git a/equinix/fabric_mapping_helper.go b/equinix/fabric_mapping_helper.go index 8f40dbceb..0ea1551bb 100644 --- a/equinix/fabric_mapping_helper.go +++ b/equinix/fabric_mapping_helper.go @@ -24,12 +24,12 @@ func serviceTokenToFabric(serviceTokenRequest []interface{}) v4.ServiceToken { func additionalInfoToFabric(additionalInfoRequest []interface{}) []v4.ConnectionSideAdditionalInfo { var mappedaiArray []v4.ConnectionSideAdditionalInfo - for i, ai := range additionalInfoRequest { + for _, ai := range additionalInfoRequest { aiMap := ai.(map[string]interface{}) key := aiMap["key"].(string) value := aiMap["value"].(string) mappedai := v4.ConnectionSideAdditionalInfo{Key: key, Value: value} - mappedaiArray[i] = mappedai + mappedaiArray = append(mappedaiArray, mappedai) } return mappedaiArray } diff --git a/equinix/resource_fabric_connection.go b/equinix/resource_fabric_connection.go index 6583d27ef..2764fe9a5 100755 --- a/equinix/resource_fabric_connection.go +++ b/equinix/resource_fabric_connection.go @@ -48,6 +48,7 @@ func resourceFabricConnectionCreate(ctx context.Context, d *schema.ResourceData, projectReq := d.Get("project").(*schema.Set).List() project := projectToFabric(projectReq) additionalInfo := d.Get("additional_info").([]interface{}) + additionalinfo := additionalInfoToFabric(additionalInfo) connectionASide := v4.ConnectionSide{} for _, as := range aside { asideMap := as.(map[string]interface{}) @@ -91,15 +92,16 @@ func resourceFabricConnectionCreate(ctx context.Context, d *schema.ResourceData, } createRequest := v4.ConnectionPostRequest{ - Name: d.Get("name").(string), - Type_: &conType, - Order: &order, - Notifications: notifications, - Bandwidth: int32(d.Get("bandwidth").(int)), - Redundancy: &red, - ASide: &connectionASide, - ZSide: &connectionZSide, - Project: &project, + Name: d.Get("name").(string), + Type_: &conType, + Order: &order, + Notifications: notifications, + Bandwidth: int32(d.Get("bandwidth").(int)), + AdditionalInfo: additionalinfo, + Redundancy: &red, + ASide: &connectionASide, + ZSide: &connectionZSide, + Project: &project, } conn, _, err := client.ConnectionsApi.CreateConnection(ctx, createRequest) @@ -231,13 +233,15 @@ func resourceFabricConnectionUpdate(ctx context.Context, d *schema.ResourceData, waitFunction = waitForConnectionProviderStatusChange } - updatedConn, err = waitFunction(d.Id(), meta, ctx) + conn, err := waitFunction(d.Id(), meta, ctx) if err != nil { if !strings.Contains(err.Error(), "500") { d.SetId("") } diags = append(diags, diag.Diagnostic{Severity: 2, Summary: fmt.Sprintf("connection property update completion timeout error: %v [update payload: %v] (other updates will be successful if the payload is not shown)", err, update)}) + } else { + updatedConn = conn } } diff --git a/examples/fabric/v4/portConnectivity/ibm/ibm2/README.md b/examples/fabric/v4/portConnectivity/ibm/ibm2/README.md new file mode 100644 index 000000000..70e206964 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/ibm/ibm2/README.md @@ -0,0 +1,52 @@ +# ECX Fabric Layer2 Redundant Connection to IBM 2 + +This example shows how to create Layer 2 Connection between ECX Fabric ports and IBM2 Cloud. + +## Adjust variables + +At minimum, you must set below variables in `terraform.tfvars` file: + +* `equinix_client_id` - Equinix client ID (consumer key), obtained after + registering app in the developer platform +* `equinix_client_secret` - Equinix client secret ID (consumer secret), + obtained same way as above + +`connection_name` - The name of the connection +`connection_type` - Connection type, please refer to OAS schema for enum values. +`notifications_type` - Notification type +`notifications_emails` - List of emails +`bandwidth` - Bandwidth in MBs +`redundancy` - Port redundancy +`purchase_order_number` - Purchase order number applied to billing invoices for this connection. +`aside_ap_type` - Access point type +`aside_link_protocol_type` - Link protocol type +`aside_pri_link_protocol_tag` - Tag number +`zside_ap_type` - Z side access point type +`zside_ap_authentication_key` - IBM authorization key (Account Id), like 6if92b31d921499f903592cd816f6aw1 +`zside_ap_profile_type` - Service profile type +`zside_location` - Equinix Metro Code for the Z side access point +`fabric_sp_name` - Service profile name like i.e. AZURE +`equinix_port_name` - Name of ECX Fabric Port +`seller_asn` - Seller ASN Number +`seller_region` - Seller Region + +## IBM login + +Log in to IBM portal with an account that has permission to create necessary resources. + +## Initialize +- First step is to initialize the terraform directory/resource we are going to work on. + In the given example, the folder to perform CRUD operations for port2ibm2 redundant connections can be found at examples/fabric/v4/portConnectivity/ibm/ibm2. + +- Change directory into - `CD examples/fabric/v4/portConnectivity/ibm/ibm2` +- Initialize Terraform plugins - `terraform init` + +## Port to IBM2 connection : Create, Read, Update and Delete(CRUD) operations +Note: `–auto-approve` command does not prompt the user for validating the applying config. Remove it to get a prompt to confirm the operation. + +| Operation | Command | Description | +|:----------|:---------------------------------:|---------------------------------------------------------------------------:| +| CREATE | `terraform apply –auto-approve` | Creates a port2ibm2 connection resources | +| READ | `terraform show` | Reads/Shows the current state of the port2ibm2 connection resources | +| UPDATE | `terraform apply -refresh` | Updates the connections with values provided in the terraform.tfvars file | +| DELETE | `terraform destroy –auto-approve` | Deletes the created port2ibm2 connection resources | diff --git a/examples/fabric/v4/portConnectivity/ibm/ibm2/main.tf b/examples/fabric/v4/portConnectivity/ibm/ibm2/main.tf new file mode 100644 index 000000000..f55849e02 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/ibm/ibm2/main.tf @@ -0,0 +1,67 @@ +provider "equinix" { + client_id = var.equinix_client_id + client_secret = var.equinix_client_secret +} + +data "equinix_fabric_service_profiles" "ibm" { + filter { + property = "/name" + operator = "=" + values = [var.fabric_sp_name] + } +} + +data "equinix_fabric_ports" "port" { + filters { + name = var.equinix_port_name + } +} + +resource "equinix_fabric_connection" "ibm2" { + name = var.connection_name + type = var.connection_type + + notifications { + type = var.notifications_type + emails = var.notifications_emails + } + + bandwidth = var.bandwidth + + additional_info = [{key = "ASN", value = var.seller_asn }, {"key"= "Global","value" = "false"}, {"key" = "BGP_IBM_CIDR","value" = "172.16.0.18/30"},{"key" = "BGP_CER_CIDR","value" = "172.16.0.19/30"} ] + + redundancy { priority = var.redundancy } + order { + purchase_order_number = var.purchase_order_number + } + a_side { + access_point { + type = var.aside_ap_type + port { + uuid = data.equinix_fabric_ports.port.id + } + link_protocol { + type = var.aside_link_protocol_type + vlan_tag = var.aside_link_protocol_tag + } + } + } + z_side { + access_point { + type = var.zside_ap_type + authentication_key = var.zside_ap_authentication_key + seller_region = var.seller_region + profile { + type = var.zside_ap_profile_type + uuid = data.equinix_fabric_service_profiles.ibm.id + } + location { + metro_code = var.zside_location + } + } + } +} + +output "connection_result" { + value = equinix_fabric_connection.ibm2.id +} diff --git a/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tf b/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tf new file mode 100644 index 000000000..b5f55a7f4 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + equinix = { + source="equinix/equinix" + } + } +} diff --git a/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tfvars.example b/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tfvars.example new file mode 100644 index 000000000..5c5816f6a --- /dev/null +++ b/examples/fabric/v4/portConnectivity/ibm/ibm2/terraform.tfvars.example @@ -0,0 +1,21 @@ +equinix_client_id = "MyEquinixClientId" +equinix_client_secret = "MyEquinixClientSecret" + +connection_name = "Terra_Port2IBM2" +connection_type = "EVPL_VC" +notifications_type = "ALL" +notifications_emails = ["example@equinix.com"] +bandwidth = 50 +redundancy = "PRIMARY" +purchase_order_number = "1-323292" +aside_ap_type = "COLO" +aside_link_protocol_type = "DOT1Q" +aside_link_protocol_tag = "1302" +zside_ap_type = "SP" +zside_ap_authentication_key = "IBM Authentication Key" +zside_ap_profile_type = "L2_PROFILE" +zside_location = "SV" +fabric_sp_name = "IBM Cloud Direct Link 2" +equinix_port_name = "Equinix Port Name" +seller_asn = "2400" +seller_region = "San Jose 2" diff --git a/examples/fabric/v4/portConnectivity/ibm/ibm2/variables.tf b/examples/fabric/v4/portConnectivity/ibm/ibm2/variables.tf new file mode 100644 index 000000000..b8ddcb5a2 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/ibm/ibm2/variables.tf @@ -0,0 +1,20 @@ +variable "equinix_client_id" {} +variable "equinix_client_secret" {} +variable "connection_name" {} +variable "connection_type" {} +variable "notifications_type" {} +variable "notifications_emails" {} +variable "bandwidth" {} +variable "redundancy" {} +variable "purchase_order_number" {} +variable "aside_ap_type" {} +variable "aside_link_protocol_type" {} +variable "aside_link_protocol_tag" {} +variable "zside_ap_type" {} +variable "zside_ap_authentication_key" {} +variable "zside_ap_profile_type" {} +variable "zside_location" {} +variable "fabric_sp_name" {} +variable "equinix_port_name" {} +variable "seller_asn" {} +variable "seller_region" {} diff --git a/tests/connection_e2e_fcr_multicloud_connection_test.go b/tests/connection_e2e_fcr_multicloud_connection_test.go new file mode 100644 index 000000000..1159300a2 --- /dev/null +++ b/tests/connection_e2e_fcr_multicloud_connection_test.go @@ -0,0 +1,21 @@ +package tests + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +func TestFCRMultiCloudCreateConnection(t *testing.T) { + // retryable errors in terraform testing. + terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: "../examples/fabric/v4/cloudRouterConnectivity/multiCloudConnection", + }) + + defer terraform.Destroy(t, terraformOptions) + + terraform.InitAndApply(t, terraformOptions) + output := terraform.Output(t, terraformOptions, "connection_result") + assert.NotNil(t, output) +} diff --git a/tests/connection_e2e_ibm_test.go b/tests/connection_e2e_ibm2_test.go similarity index 88% rename from tests/connection_e2e_ibm_test.go rename to tests/connection_e2e_ibm2_test.go index 9b8332974..7cf580cde 100644 --- a/tests/connection_e2e_ibm_test.go +++ b/tests/connection_e2e_ibm2_test.go @@ -10,7 +10,7 @@ import ( func TestIBMCreateConnection(t *testing.T) { // retryable errors in terraform testing. terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ - TerraformDir: "../examples/fabric/v4/portConnectivity/ibm", + TerraformDir: "../examples/fabric/v4/portConnectivity/ibm/ibm2", }) defer terraform.Destroy(t, terraformOptions)