From 38f505a9fc6ccddd2a8b843cee86974d599c0f60 Mon Sep 17 00:00:00 2001 From: Tim Hogarty Date: Fri, 29 Sep 2023 14:55:00 -0700 Subject: [PATCH 1/4] Add redundant connection to Port2Azure and update variables+README.md for both single and redundant Port2Azure Examples --- .../azure/{ => singleConnection}/README.md | 57 +++++---- .../azure/{ => singleConnection}/main.tf | 31 +++-- .../azure/{ => singleConnection}/terraform.tf | 0 .../terraform.tfvars.example | 7 +- .../azure/{ => singleConnection}/variables.tf | 4 +- .../azure/twoRedundantConnections/README.md | 58 +++++++++ .../azure/twoRedundantConnections/main.tf | 115 ++++++++++++++++++ .../twoRedundantConnections/terraform.tf | 7 ++ .../terraform.tfvars.example | 21 ++++ .../twoRedundantConnections/variables.tf | 21 ++++ 10 files changed, 271 insertions(+), 50 deletions(-) rename examples/fabric/v4/portConnectivity/azure/{ => singleConnection}/README.md (50%) rename examples/fabric/v4/portConnectivity/azure/{ => singleConnection}/main.tf (52%) rename examples/fabric/v4/portConnectivity/azure/{ => singleConnection}/terraform.tf (100%) rename examples/fabric/v4/portConnectivity/azure/{ => singleConnection}/terraform.tfvars.example (68%) rename examples/fabric/v4/portConnectivity/azure/{ => singleConnection}/variables.tf (85%) create mode 100644 examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md create mode 100644 examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/main.tf create mode 100644 examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf create mode 100644 examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example create mode 100644 examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/variables.tf diff --git a/examples/fabric/v4/portConnectivity/azure/README.md b/examples/fabric/v4/portConnectivity/azure/singleConnection/README.md similarity index 50% rename from examples/fabric/v4/portConnectivity/azure/README.md rename to examples/fabric/v4/portConnectivity/azure/singleConnection/README.md index 688a19d09..10656fb86 100644 --- a/examples/fabric/v4/portConnectivity/azure/README.md +++ b/examples/fabric/v4/portConnectivity/azure/singleConnection/README.md @@ -1,43 +1,48 @@ # ECX Fabric Layer2 Connection to Azure -This example shows how to create layer 2 connection between ECX Fabric port and AZURE Cloud. -Example covers **provisioning of both sides** of the connection. +This example shows how to create layer 2 connection between ECX Fabric port +and AZURE 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 -- `fabric_sp_name` - Service profile name like i.e. AZURE -- `equinix_port_name` - Name of ECX Fabric port that should be connected to AZURE, i.e. ops-user100-CX-SV5-NL-Qinq-BO-10G-SEC-JP-199 -- `connection_name` - the name of the connection -- `connection_type` - connection type, please refer schema -- `notifications_type` - notification type -- `notifications_emails` - List of emails -- `bandwidth` - bandwidth in MBs -- `redundancy` - Port redundancy -- `aside_ap_type` - Access point type -- `peering_type` - Peering type -- `aside_port_uuid` - Port uuid, fetched based on port call using Port resource -- `aside_link_protocol_type` - link protocol type -- `aside_link_protocol_stag` - s tag number -- `aside_link_protocol_ctag` - c tag number -- `zside_ap_type` - Z side access point type -- `zside_ap_authentication_key` - AZURE authorization key, like c620477c-3f30-41e8-a0b9-cfdb4a12121d -- `zside_ap_profile_type` - Service profile type -- `zside_ap_profile_uuid` - Service profile uuid, fetched based on Service Profile get call using Service Profile search schema -- `zside_location` - Seller location + +* `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 PRIMARY or SECONDARY +`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_link_protocol_stag` - S-Tag number +`zside_ap_type` - Z side access point type +`zside_ap_authentication_key` - AZURE authorization key, like c620477c-3f30-41e8-a0b9-cf324a12121d +`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 that will be used for the Connection ## Azure login -Log in to Azure portal use account that has permission to create necessary resources. +Log in to Azure portal with an account that has permission to create necessary resources. + +Create an Azure ExpressRoute Circuit and use its Service Key as the Authentication Key in the examples. + +Bandwidth in Terraform must match the bandwidth of the ExpressRoute Circuit created in Azure. ## 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 port2azure connection can be found at examples/fabric/v4/portConnectivity/azure/. + In the given example, the folder to perform CRUD operations for port2azure connection can be found at examples/fabric/v4/portConnectivity/azure/singleConnection. -- Change directory into - `CD examples/fabric/v4/portConnectivity/azure/` +- Change directory into - `CD examples/fabric/v4/portConnectivity/azure/singleConnection` - Initialize Terraform plugins - `terraform init` ## Port to Azure connection : Create, Read, Update and Delete(CRUD) operations diff --git a/examples/fabric/v4/portConnectivity/azure/main.tf b/examples/fabric/v4/portConnectivity/azure/singleConnection/main.tf similarity index 52% rename from examples/fabric/v4/portConnectivity/azure/main.tf rename to examples/fabric/v4/portConnectivity/azure/singleConnection/main.tf index b935f0d3d..48c3439de 100644 --- a/examples/fabric/v4/portConnectivity/azure/main.tf +++ b/examples/fabric/v4/portConnectivity/azure/singleConnection/main.tf @@ -7,7 +7,7 @@ data "equinix_fabric_service_profiles" "azure" { filter { property = "/name" operator = "=" - values = [var.fabric_sp_name] + values = [var.fabric_sp_name] } } @@ -20,38 +20,37 @@ data "equinix_fabric_ports" "qinq-pri" { resource "equinix_fabric_connection" "azure-qinq" { name = var.connection_name type = var.connection_type - notifications{ - type=var.notifications_type - emails=var.notifications_emails + notifications { + type = var.notifications_type + emails = var.notifications_emails } bandwidth = var.bandwidth - redundancy {priority= var.redundancy} + redundancy { priority = var.redundancy } order { - purchase_order_number= var.purchase_order_number + purchase_order_number = var.purchase_order_number } a_side { access_point { - type= var.aside_ap_type + type = var.aside_ap_type port { - uuid= data.equinix_fabric_ports.qinq-pri.data.0.uuid + uuid = data.equinix_fabric_ports.qinq-pri.data.0.uuid } link_protocol { - type= var.aside_link_protocol_type - vlan_s_tag= var.aside_link_protocol_stag + type = var.aside_link_protocol_type + vlan_s_tag = var.aside_link_protocol_stag } } } z_side { access_point { - type= var.zside_ap_type - authentication_key= var.zside_ap_authentication_key - ///peering_type= var.peering_type + type = var.zside_ap_type + authentication_key = var.zside_ap_authentication_key profile { - type= var.zside_ap_profile_type - uuid= data.equinix_fabric_service_profiles.azure.data.0.uuid + type = var.zside_ap_profile_type + uuid = data.equinix_fabric_service_profiles.azure.data.0.uuid } location { - metro_code= var.zside_location + metro_code = var.zside_location } } } diff --git a/examples/fabric/v4/portConnectivity/azure/terraform.tf b/examples/fabric/v4/portConnectivity/azure/singleConnection/terraform.tf similarity index 100% rename from examples/fabric/v4/portConnectivity/azure/terraform.tf rename to examples/fabric/v4/portConnectivity/azure/singleConnection/terraform.tf diff --git a/examples/fabric/v4/portConnectivity/azure/terraform.tfvars.example b/examples/fabric/v4/portConnectivity/azure/singleConnection/terraform.tfvars.example similarity index 68% rename from examples/fabric/v4/portConnectivity/azure/terraform.tfvars.example rename to examples/fabric/v4/portConnectivity/azure/singleConnection/terraform.tfvars.example index 592154079..3d3d8e5ec 100644 --- a/examples/fabric/v4/portConnectivity/azure/terraform.tfvars.example +++ b/examples/fabric/v4/portConnectivity/azure/singleConnection/terraform.tfvars.example @@ -1,7 +1,7 @@ equinix_client_id = "MyEquinixClientId" equinix_client_secret = "MyEquinixSecret" -connection_name = "terra_e2e_azure" +connection_name = "Terra_Port2Azure" connection_type = "EVPL_VC" notifications_type = "ALL" notifications_emails = ["example@equinix.com"] @@ -9,14 +9,11 @@ bandwidth = 50 redundancy = "PRIMARY" purchase_order_number = "1-323292" aside_ap_type = "COLO" -peering_type="MICROSOFT" -aside_port_uuid = "c4d9350e-783c-83cd-1ce0-306a5c00a600" aside_link_protocol_type = "QINQ" aside_link_protocol_stag = "2019" zside_ap_type = "SP" -zside_ap_authentication_key = "c620477c-3f30-41e8-a0b9-cfdb4a31034b" +zside_ap_authentication_key = "Azure Express Route Service Key" zside_ap_profile_type = "L2_PROFILE" -zside_ap_profile_uuid = "bfb74121-7e2c-4f74-99b3-69cdafb03b41" zside_location = "SV" fabric_sp_name = "Azure ExpressRoute" equinix_port_name = "ops-user100-CX-SV1-NL-Qinq-STD-1G-PRI-NK-349" diff --git a/examples/fabric/v4/portConnectivity/azure/variables.tf b/examples/fabric/v4/portConnectivity/azure/singleConnection/variables.tf similarity index 85% rename from examples/fabric/v4/portConnectivity/azure/variables.tf rename to examples/fabric/v4/portConnectivity/azure/singleConnection/variables.tf index 7dc04e695..eb6680d71 100644 --- a/examples/fabric/v4/portConnectivity/azure/variables.tf +++ b/examples/fabric/v4/portConnectivity/azure/singleConnection/variables.tf @@ -9,14 +9,12 @@ variable "bandwidth" {} variable "redundancy" {} variable "purchase_order_number" {} variable "aside_ap_type" {} -variable "aside_port_uuid" {} variable "aside_link_protocol_type" {} variable "aside_link_protocol_stag" {} variable "zside_ap_type" {} variable "zside_ap_authentication_key" {} variable "peering_type" {} variable "zside_ap_profile_type" {} -variable "zside_ap_profile_uuid" {} variable "zside_location" {} variable "fabric_sp_name" {} -variable "equinix_port_name" {} \ No newline at end of file +variable "equinix_port_name" {} diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md new file mode 100644 index 000000000..3adc256f2 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md @@ -0,0 +1,58 @@ +# ECX Fabric Layer2 Redundant Connection to Azure + +This example shows how to create Layer 2 Connection between two ECX Fabric ports +and AZURE 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 + +`pri_connection_name` - The name of the PRIMARY connection +`sec_connection_name` - The name of the SECONDARY 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 +`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_stag` - S-Tag number for PRIMARY Connection +`aside_sec_link_protocol_stag` - S-Tag number for SECONDARY Connection +`zside_ap_type` - Z side access point type +`zside_ap_authentication_key` - AZURE authorization key, like c620477c-3f30-41e8-a0b9-cf324a12121d +`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_pri_port_name` - Name of ECX Fabric Port for the PRIMARY Connection +`equinix_sec_port_name` - Name of ECX Fabric Port for the SECONDARY Connection + +## Azure login + +Log in to Azure portal with an account that has permission to create necessary resources. + +Create an Azure ExpressRoute Circuit and use its Service Key as the Authentication Key in the examples. + +Bandwidth in Terraform must match the bandwidth of the ExpressRoute Circuit created in Azure. + +## 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 port2azure redundant connections can be found at examples/fabric/v4/portConnectivity/azure/twoRedundantConnection. + +- Change directory into - `CD examples/fabric/v4/portConnectivity/azure/twoRedundantConnection` +- Initialize Terraform plugins - `terraform init` + +## Port to Azure 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 port2azure redundant connection resources | +| READ | `terraform show` | Reads/Shows the current state of the port2azure 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 port2azure connection resources | + diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/main.tf b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/main.tf new file mode 100644 index 000000000..d1959c057 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/main.tf @@ -0,0 +1,115 @@ +provider "equinix" { + client_id = var.equinix_client_id + client_secret = var.equinix_client_secret +} + +data "equinix_fabric_service_profiles" "azure" { + filter { + property = "/name" + operator = "=" + values = [var.fabric_sp_name] + } +} + +data "equinix_fabric_ports" "qinq-pri" { + filters { + name = var.equinix_pri_port_name + } +} + +data "equinix_fabric_ports" "qinq-sec" { + filters { + name = var.equinix_sec_port_name + } +} + +resource "equinix_fabric_connection" "azure-qinq" { + name = var.pri_connection_name + type = var.connection_type + notifications { + type = var.notifications_type + emails = var.notifications_emails + } + bandwidth = var.bandwidth + redundancy { + priority = "PRIMARY" + } + order { + purchase_order_number = var.purchase_order_number + } + a_side { + access_point { + type = var.aside_ap_type + port { + uuid = data.equinix_fabric_ports.qinq-pri.data.0.uuid + } + link_protocol { + type = var.aside_link_protocol_type + vlan_s_tag = var.aside_pri_link_protocol_stag + } + } + } + z_side { + access_point { + type = var.zside_ap_type + authentication_key = var.zside_ap_authentication_key + profile { + type = var.zside_ap_profile_type + uuid = data.equinix_fabric_service_profiles.azure.data.0.uuid + } + location { + metro_code = var.zside_location + } + } + } +} + +resource "equinix_fabric_connection" "azure-qinq-second-connection" { + name = var.sec_connection_name + type = var.connection_type + notifications { + type = var.notifications_type + emails = var.notifications_emails + } + bandwidth = var.bandwidth + redundancy { + priority = "SECONDARY" + group = one(equinix_fabric_connection.azure-qinq.redundancy).group + } + order { + purchase_order_number = var.purchase_order_number + } + a_side { + access_point { + type = var.aside_ap_type + port { + uuid = data.equinix_fabric_ports.qinq-sec.data.0.uuid + } + link_protocol { + type = var.aside_link_protocol_type + vlan_s_tag = var.aside_sec_link_protocol_stag + } + } + } + z_side { + access_point { + type = var.zside_ap_type + authentication_key = var.zside_ap_authentication_key + profile { + type = var.zside_ap_profile_type + uuid = data.equinix_fabric_service_profiles.azure.data.0.uuid + } + location { + metro_code = var.zside_location + } + } + } +} + +output "connection_result" { + value = equinix_fabric_connection.azure-qinq.id +} + +output "second_connection_result" { + value = equinix_fabric_connection.azure-qinq-second-connection.id +} diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf new file mode 100644 index 000000000..2dc81d8b0 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + equinix = { + source = "equinix/equinix" + } + } +} \ No newline at end of file diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example new file mode 100644 index 000000000..7ea77ef18 --- /dev/null +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example @@ -0,0 +1,21 @@ +equinix_client_id = "MyEquinixClientId" +equinix_client_secret = "MyEquinixSecret" + +pri_connection_name = "terraform_port2azure_pri" +sec_connection_name = "terraform_port2azure_sec" +connection_type = "EVPL_VC" +notifications_type = "ALL" +notifications_emails = ["example@equinix.com"] +bandwidth = 50 +purchase_order_number = "1-323292" +aside_ap_type = "COLO" +aside_link_protocol_type = "QINQ" +aside_pri_link_protocol_stag = "2019" +aside_sec_link_protocol_stag = "2020" +zside_ap_type = "SP" +zside_ap_authentication_key = "Azure Express Route Service Key" +zside_ap_profile_type = "L2_PROFILE" +zside_location = "SV" +fabric_sp_name = "Azure ExpressRoute" +equinix_pri_port_name = "ops-user100-CX-SV1-NL-Qinq-STD-10G-PRI-JP-149" +equinix_sec_port_name = "ops-user100-CX-SV1-NL-Qinq-STD-10G-PRI-JP-150" diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/variables.tf b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/variables.tf new file mode 100644 index 000000000..4dec9bf6e --- /dev/null +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/variables.tf @@ -0,0 +1,21 @@ +variable "equinix_client_id" {} +variable "equinix_client_secret" {} + +variable "pri_connection_name" {} +variable "sec_connection_name" {} +variable "connection_type" {} +variable "notifications_type" {} +variable "notifications_emails" {} +variable "bandwidth" {} +variable "purchase_order_number" {} +variable "aside_ap_type" {} +variable "aside_link_protocol_type" {} +variable "aside_pri_link_protocol_stag" {} +variable "aside_sec_link_protocol_stag" {} +variable "zside_ap_type" {} +variable "zside_ap_authentication_key" {} +variable "zside_ap_profile_type" {} +variable "zside_location" {} +variable "fabric_sp_name" {} +variable "equinix_pri_port_name" {} +variable "equinix_sec_port_name" {} From 848f3c970be580ffc329518d02968d39bebea813 Mon Sep 17 00:00:00 2001 From: Tim Hogarty Date: Fri, 29 Sep 2023 15:12:23 -0700 Subject: [PATCH 2/4] Update connection names for redundant connections --- .../azure/twoRedundantConnections/terraform.tfvars.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example index 7ea77ef18..7c2e6b9cc 100644 --- a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tfvars.example @@ -1,8 +1,8 @@ equinix_client_id = "MyEquinixClientId" equinix_client_secret = "MyEquinixSecret" -pri_connection_name = "terraform_port2azure_pri" -sec_connection_name = "terraform_port2azure_sec" +pri_connection_name = "Terra_Port2Azure_Pri" +sec_connection_name = "Terra_Port2Azure_Sec" connection_type = "EVPL_VC" notifications_type = "ALL" notifications_emails = ["example@equinix.com"] From 636d0ce8d712552ea4a1eaf8b25823d8b73b26b8 Mon Sep 17 00:00:00 2001 From: Tim Hogarty Date: Fri, 29 Sep 2023 15:13:55 -0700 Subject: [PATCH 3/4] Fix typo in path for redundant connections --- .../portConnectivity/azure/twoRedundantConnections/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md index 3adc256f2..9cecf2c28 100644 --- a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/README.md @@ -41,9 +41,9 @@ Bandwidth in Terraform must match the bandwidth of the ExpressRoute Circuit crea ## 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 port2azure redundant connections can be found at examples/fabric/v4/portConnectivity/azure/twoRedundantConnection. + In the given example, the folder to perform CRUD operations for port2azure redundant connections can be found at examples/fabric/v4/portConnectivity/azure/twoRedundantConnections. -- Change directory into - `CD examples/fabric/v4/portConnectivity/azure/twoRedundantConnection` +- Change directory into - `CD examples/fabric/v4/portConnectivity/azure/twoRedundantConnections` - Initialize Terraform plugins - `terraform init` ## Port to Azure connection : Create, Read, Update and Delete(CRUD) operations From fb57be1acfde78e358fb42f3b66b85f984f9f86c Mon Sep 17 00:00:00 2001 From: Tim Hogarty Date: Fri, 13 Oct 2023 15:56:57 -0700 Subject: [PATCH 4/4] Add trailing newline to file --- .../portConnectivity/azure/twoRedundantConnections/terraform.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf index 2dc81d8b0..fd41df1c0 100644 --- a/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf +++ b/examples/fabric/v4/portConnectivity/azure/twoRedundantConnections/terraform.tf @@ -4,4 +4,4 @@ terraform { source = "equinix/equinix" } } -} \ No newline at end of file +}