Technical Blog: Building a Scalable Multi-Cloud Network Infrastructure with Terraform

In today’s digital age, building a scalable and secure network infrastructure is crucial for any business. One of the tools that can help you do that is Terraform.

Terraform is an open-source Infrastructure as Code (IaC) tool that allows you to provision and manage infrastructure resources. It supports multiple cloud providers such as AWS, Google Cloud Platform (GCP), and Azure, and can also be used to manage on-premises resources.

In this blog post, we will explore how to use Terraform and PacketFabric to build a scalable network infrastructure. Specifically, we are going to discuss this example use case available on GitHub and how to build a PacketFabric Cloud Router between AWS and Google Cloud Platform using a custom Terraform module.

Terraform modules

One of the key features of Terraform is the ability to use modules, which allow you to package and reuse a set of Terraform resources. A module is a collection of Terraform configuration files that define reusable infrastructure resources. A module can be thought of as a blueprint for building a specific type of infrastructure, such as a web server or a database cluster. Modules allow you to organize your Terraform code and make it more reusable by encapsulating complex resource configurations and making them available to other parts of your infrastructure. Modules can also be shared and reused across different Terraform projects, making it easier to create and manage similar infrastructure in multiple environments.

In addition to modules, another best practice in Terraform is to use variables to manage input values. Instead of hardcoding values into your Terraform code, variables allow you to separate the configuration of your infrastructure from the implementation.

When working with multiple environments, such as dev and prod, it can be useful to define all the variables in different JSON files, which can be easily consumed by Terraform. This approach allows you to keep the environment-specific configuration separate from the Terraform code, making it easier to manage and maintain.

Defining BGP

When you’re setting up your connections, you will need to define how BGP should work between the clouds. 

Border Gateway Protocol (BGP) is a routing protocol used to direct data traffic between different networks. It ensures that data travels from one place to another quickly and reliably. A BGP session is an active connection between two BGP routers, such as those from AWS/GCP and PacketFabric.

An ASN is a unique identifier that is assigned to a network participating in BGP. It helps identify the network and its routing policies to other networks.

When setting up PacketFabric Cloud Router connections, BGP prefixes are divided into two types: allowed prefixes from the cloud and allowed prefixes to the cloud:

  • Allowed prefixes from the cloud is a list of IP addresses within the cloud environment that you want to advertise to other connections on the Cloud Router, including the VPC internal space and created routes.
  • Allowed prefixes to the cloud is a list of IP addresses you want to allow into the cloud VPC from other connections on the same Cloud Router.

Setting variables for the Cloud Router and its connections

In our example, the JSON blob provided in the sample code is a representation of the network infrastructure we want to compose and its desired state (a Cloud Router with an AWS and a GCP connection). 

The JSON files define the variables for different environments like dev-environment and prod-environment and contain the following information:

  • cloud_routers: The ASN, capacity, and regions for the Cloud Router.
  • aws_connections: The speed and POP (point of presence) for the AWS connection.
  • gcp_connections: The pairing key, VLAN attachment name, speed, and POP for the GCP connection.
  • aws_bgp_sessions: The remote ASN, remote address, L3 address, MD5, and disabled status for the AWS BGP session.
  • gcp_bgp_sessions: The remote ASN, remote address, L3 address, and disabled status for the GCP BGP session.
  • aws_outbound: The BGP prefixes for the AWS allowed prefixes to/from clouds. 
  • gcp_outbound: The BGP prefixes for the GCP allowed prefixes to/from clouds.
{
   "cloud_routers": {
       "dev-environment": {
           "asn": 4556,
           "capacity": "500Mbps",
           "regions": [
               "US"
           ]
       }
   },
   "aws_connections": {
       "dev-environment": {
           "speed": "50Mbps",
           "pop": "PDX2"
       }
   },
   "gcp_connections": {
       "dev-environment": {
           "pairing_key": "redacted",
           "vlan_attachment_name": "dev-env-interconnect",
           "speed": "50Mbps",
           "pop": "WDC1"
       }
   },
   "aws_bgp_sessions": {
       "dev-environment": {
           "remote_asn": 64512,
           "remote_address": "169.254.254.30/30",
           "l3_address": "169.254.254.29/30",
           "md5": "redacted",
           "disabled": false
       }
   },
   "gcp_bgp_sessions": {
       "dev-environment": {
           "remote_asn": 16550,
           "remote_address": "169.254.13.170/29",
           "l3_address": "169.254.13.169/29",
           "disabled": false
       }
   },
   "aws_outbound": {
       "dev-environment": [
           { "prefix": "198.168.1.0/24" },
           { "prefix": "198.168.2.0/24" }
       ]
   },
   "gcp_outbound": {
       "dev-environment": [
           { "prefix": "198.168.3.0/24" },
           { "prefix": "198.168.4.0/24" }
       ]
   }
}

Using the Terraform module as described above, we can easily manage different environments by changing the variables in the JSON file and re-running the Terraform code. This approach also makes it easy to share and collaborate on the infrastructure code, as the environment-specific configuration is clearly separated from the implementation.

The Terraform module takes in a number of inputs, such as the desired ASN, capacity, and regions for cloud routers, as well as the desired speed, POP, and BGP session details for AWS and GCP connections.

Here is an example of the code that defines the “cloud_router” module:

module "packetfabric-cloud-router" {
 source = "./modules/packetfabric"
 # This variable is used to iterate over multiple cloud routers
 for_each         = var.cloud_routers
 name             = each.key
 asn              = each.value.asn
 capacity         = each.value.capacity
 regions          = each.value.regions
 aws_connections  = var.aws_connections
 aws_bgp_sessions = var.aws_bgp_sessions
 aws_outbound     = var.aws_outbound
 gcp_connections  = var.gcp_connections
 gcp_bgp_sessions = var.gcp_bgp_sessions
 gcp_outbound     = var.gcp_outbound
 # This block sets the provider to use the "pf" alias created earlier
 providers = {
   packetfabric = packetfabric.pf
 }
}

The Terraform module is organized in a way that it is split into different sections, such as cloud routers, AWS connections, GCP connections, AWS BGP sessions, GCP BGP sessions, AWS outbound, and GCP outbound. The BGP sessions define the remote ASN, remote address, L3 address, and disabled status for the GCP BGP session. The aws_outbound and the gcp_outbound variables define the prefixes associated with the BGP session (see below for details). 

Each section is responsible for creating a specific aspect of the network infrastructure. This makes the code easy to understand and navigate.

Here is an example of the code that defines the “cloud_routers” resources within the module:

resource "packetfabric_cloud_router" "cr" {
 provider = packetfabric
 name     = var.name
 asn      = var.asn
 capacity = var.capacity
 regions  = var.regions
}

Here is an example of the code that defines the “cloud_router_connection” resources within the module:

resource "packetfabric_cloud_router_connection_google" "gcp" {
 for_each                    = var.gcp_connections
 provider                    = packetfabric
 circuit_id                  = packetfabric_cloud_router.cr.id
 description                 = "gcp-${each.key}-${lower(each.value.pop)}"
 google_pairing_key          = each.value.pairing_key
 google_vlan_attachment_name = "aws-${each.value.vlan_attachment_name}-${lower(each.value.pop)}"
 pop                         = each.value.pop
 speed                       = each.value.speed
}

In the next example, we define the “packetfabric_cloud_router_bgp_session” resources within the module:

The dynamic “prefixes” block is used to create one or more “prefix” resources within the “packetfabric_cloud_router_bgp_session” resource. The “for_each” argument is used to iterate over a specific list of values, in this case the “var.gcp_outbound” variable, and create a new prefix resource for each item in the list. The “content” block is where the actual creation of the resource is specified.

So, in simple words, this code is creating one or more “prefix” using the values defined in the “var.gcp_outbound” list and setting the properties “prefix”, “type” and “order” for each of them.

resource "packetfabric_cloud_router_bgp_session" "gcp" {
 for_each       = var.gcp_bgp_sessions
 provider       = packetfabric
 circuit_id     = packetfabric_cloud_router.cr.id
 connection_id  = packetfabric_cloud_router_connection_google.gcp[each.key].id
 address_family = "v4"
 remote_asn     = each.value.remote_asn
 remote_address = each.value.remote_address
 l3_address     = each.value.l3_address
 multihop_ttl   = 1
 disabled       = each.value.disabled


 # This block creates a dynamic block of in and out prefixes for the BGP session.
 dynamic "prefixes" {
   for_each = { for i, v in var.aws_outbound[each.key] : i => v }
   content {
     prefix     = prefixes.value.prefix
     type       = "in"
     order      = prefixes.key
   }
 }


 dynamic "prefixes" {
   for_each = { for i, v in var.gcp_outbound[each.key] : i => v }
   content {
     prefix     = prefixes.value.prefix
     type       = "out"
     med        = lookup(prefixes.value, "med", 0)
     order      = prefixes.key
   }
 }
}

Running Terraform 

Let’s go ahead and run the code example.

These commands are setting environment variables for use in the Terraform code.

Mac/Linux environment:

$ export PF_TOKEN="secret"
$ export PF_ACCOUNT_ID="123456789"
$ export PF_AWS_ACCOUNT_ID="987654321"

Windows Power-shell environment:

$ PS C:\> $Env:PF_TOKEN="secret"
$ PS C:\> $Env:PF_ACCOUNT_ID="123456789"
$ PS C:\> $Env:PF_AWS_ACCOUNT_ID="987654321"

The first command sets the environment variable PF_TOKEN. This variable will be used later in the Terraform code to authenticate with the PacketFabric API. 

The second command sets the environment variable PF_ACCOUNT_ID and will be used later to identify the PacketFabric billing account to be used. 

Finally, the third command, export PF_AWS_ACCOUNT_ID will be used later in the Terraform code to identify the AWS account to be used to create the AWS Direct Connect.

The terraform init command is used to initialize a working directory containing Terraform configuration files. This command is typically the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control.

$ terraform init

After running terraform init, Terraform will be ready to use, and you can run other Terraform commands such as terraform plan and terraform apply to create or update infrastructure.

$ terraform apply --var-file=tfvars_dev.json
module.packetfabric-cloud-router["dev-environment"].data.packetfabric_locations_pop_zones.locations_pop_zones_aws["dev-environment"]: Reading...
module.packetfabric-cloud-router["dev-environment"].data.packetfabric_locations_pop_zones.locations_pop_zones_aws["dev-environment"]: Read complete after 0s [id=26106af6-b6a9-4610-aa58-4bcb86c57fe6]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router.cr will be created
  + resource "packetfabric_cloud_router" "cr" {
      + account_uuid = "123456789"
      + asn          = 4556
      + capacity     = "500Mbps"
      + id           = (known after apply)
      + name         = "dev-environment"
      + regions      = [
          + "US",
        ]
    }

  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"] will be created
  + resource "packetfabric_cloud_router_bgp_session" "aws" {
      + address_family = "v4"
      + circuit_id     = (known after apply)
      + connection_id  = (known after apply)
      + disabled       = false
      + id             = (known after apply)
      + l3_address     = "169.254.254.29/30"
      + md5            = "5ebe2294ecd0e0f08eab7690d2a6ee69"
      + multihop_ttl   = 1
      + remote_address = "169.254.254.30/30"
      + remote_asn     = 64512

      + prefixes {
          + order      = 0
          + prefix     = "198.168.1.0/24"
          + type       = "out"
        }
      + prefixes {
          + order      = 0
          + prefix     = "198.168.3.0/24"
          + type       = "in"
        }
      + prefixes {
          + order      = 1
          + prefix     = "198.168.2.0/24"
          + type       = "out"
        }
      + prefixes {
          + order      = 1
          + prefix     = "198.168.4.0/24"
          + type       = "in"
        }
    }
  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"] will be created
  + resource "packetfabric_cloud_router_bgp_session" "gcp" {
      + address_family = "v4"
      + circuit_id     = (known after apply)
      + connection_id  = (known after apply)
      + disabled       = false
      + id             = (known after apply)
      + l3_address     = "169.254.13.169/29"
      + multihop_ttl   = 1
      + remote_address = "169.254.13.170/29"
      + remote_asn     = 16550

      + prefixes {
          + med        = 0
          + order      = 0
          + prefix     = "198.168.3.0/24"
          + type       = "out"
        }
      + prefixes {
          + med        = 0
          + order      = 1
          + prefix     = "198.168.4.0/24"
          + type       = "out"
        }
      + prefixes {
          + order      = 0
          + prefix     = "198.168.1.0/24"
          + type       = "in"
        }
      + prefixes {
          + order      = 1
          + prefix     = "198.168.2.0/24"
          + type       = "in"
        }
    }

  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"] will be created
  + resource "packetfabric_cloud_router_connection_aws" "aws" {
      + account_uuid   = "123456789"
      + aws_account_id = "987654321"
      + circuit_id     = (known after apply)
      + description    = "aws-dev-environment-pdx2"
      + id             = (known after apply)
      + is_public      = false
      + maybe_dnat     = false
      + maybe_nat      = false
      + pop            = "PDX2"
      + speed          = "50Mbps"
      + zone           = "A"
    }

  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"] will be created
  + resource "packetfabric_cloud_router_connection_google" "gcp" {
      + account_uuid                = "123456789"
      + circuit_id                  = (known after apply)
      + description                 = "gcp-dev-environment-wdc1"
      + google_pairing_key          = "secret/us-east1/any"
      + google_vlan_attachment_name = “dev-env-interconnect-wdc1"
      + id                          = (known after apply)
      + maybe_dnat                  = false
      + maybe_nat                   = false
      + pop                         = "WDC1"
      + speed                       = "50Mbps"
    }

Plan: 5 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router.cr: Creating...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router.cr: Creation complete after 1s [id=PF-L3-CUST-1757476]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Creating...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Creating...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Still creating... [10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Still creating... [20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Still creating... [30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Creation complete after 38s [id=PF-L3-CON-1757486]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Creating...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [40s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [50s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [1m0s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Still creating... [1m10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Creation complete after 1m12s [id=PF-L3-CON-1757480]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Creating...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [40s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still creating... [10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [50s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still creating... [20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [1m0s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still creating... [30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [1m10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still creating... [40s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Creation complete after 42s [id=c9ad4783-20a3-48b0-9777-997d61688934]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [1m20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [1m30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still creating... [1m40s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Creation complete after 1m47s [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Verifying your results

Once Terraform execution is completed, we can review the output and make sure there are no errors and then log into the PacketFabric portal to confirm the Cloud Router was successfully created and the BGP session is being established.

Once the AWS Direct Connect has been established through PacketFabric, it will usually appear on the AWS console within a minute. The connection is linked to a Virtual Interface (VIF), which serves as the location for the Border Gateway Protocol (BGP) configuration within AWS. You can also use Terraform to set up the AWS Direct Connect and VIF.

The process of establishing Google Interconnect is different from AWS Direct Connect. To get started, you must first create a Google Cloud Router and a VLAN attachment. Then, use the available service key to establish the Google connection on the PacketFabric Cloud Router. Like AWS, Terraform can also be used for this process.

Using Terraform for ongoing management tasks

Using Terraform to manage your network infrastructure allows for efficient automation of tasks, such as updating BGP prefixes. When a new subnet is added to your AWS or Google Virtual Network, the Cloud Router’s BGP prefixes need to be updated in order for systems in the new subnet to communicate with systems across both cloud providers.

If you’re already using Terraform to manage your cloud network resources, such as VPCs and subnets, you can automate the BGP prefix updates by updating a JSON file containing the list of prefixes when creating those new subnets. 

For example, in our initial list of prefixes that we advertise from GCP and allow in AWS, we had the following:

   "gcp_outbound": {
       "dev-environment": [
           { "prefix": "198.168.3.0/24" },
           { "prefix": "198.168.4.0/24" }
       ]
   }

If we add a new 198.168.5.0/24 subnet in the GCP dev environment, we can simply add the necessary prefix to the JSON file:

   "gcp_outbound": {
       "dev-environment": [
           { "prefix": "198.168.3.0/24" },
           { "prefix": "198.168.4.0/24" },
           { "prefix": "198.168.5.0/24" }
       ]
   }

By saving the updated JSON file and running the terraform apply command again, we can update our existing infrastructure to include the new subnet prefix.

$ terraform apply --var-file=tfvars_dev.json
module.packetfabric-cloud-router["dev-environment"].data.packetfabric_locations_pop_zones.locations_pop_zones_aws["dev-environment"]: Reading...
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router.cr: Refreshing state... [id=PF-L3-CUST-1757476]
module.packetfabric-cloud-router["dev-environment"].data.packetfabric_locations_pop_zones.locations_pop_zones_aws["dev-environment"]: Read complete after 1s [id=154fd979-a229-429f-aafc-e5cc361ed6d5]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_aws.aws["dev-environment"]: Refreshing state... [id=PF-L3-CON-1757486]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_connection_google.gcp["dev-environment"]: Refreshing state... [id=PF-L3-CON-1757480]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Refreshing state... [id=c9ad4783-20a3-48b0-9777-997d61688934]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Refreshing state... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  ~ update in-place

Terraform will perform the following actions:
  # module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"] will be updated in-place
  ~ resource "packetfabric_cloud_router_bgp_session" "aws" {
        id             = "2d7d38a9-93d2-42dd-9a8d-9fdb515d3325"
        # (9 unchanged attributes hidden)

      - prefixes {
          - order            = 0 -> null
          - prefix           = "198.168.1.0/24" -> null
          - type             = "out" -> null
        }
      - prefixes {
          - order            = 0 -> null
          - prefix           = "198.168.3.0/24" -> null
          - type             = "in" -> null
        }
      - prefixes {
          - order            = 1 -> null
          - prefix           = "198.168.2.0/24" -> null
          - type             = "out" -> null
        }
      - prefixes {
          - order            = 1 -> null
          - prefix           = "198.168.4.0/24" -> null
          - type             = "in" -> null
        }
      + prefixes {
          + order      = 0
          + prefix     = "198.168.1.0/24"
          + type       = "out"
        }
      + prefixes {
          + order      = 0
          + prefix     = "198.168.3.0/24"
          + type       = "in"
        }
      + prefixes {
          + order      = 1
          + prefix     = "198.168.2.0/24"
          + type       = "out"
        }
      + prefixes {
          + order      = 1
          + prefix     = "198.168.4.0/24"
          + type       = "in"
        }
      + prefixes {
          + order      = 2
          + prefix     = "198.168.5.0/24"
          + type       = "in"
        }
    }

Plan: 0 to add, 2 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Modifying... [id=c9ad4783-20a3-48b0-9777-997d61688934]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still modifying... [id=c9ad4783-20a3-48b0-9777-997d61688934, 10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Still modifying... [id=c9ad4783-20a3-48b0-9777-997d61688934, 20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.gcp["dev-environment"]: Modifications complete after 27s [id=7a07d3f0-aff3-46fa-821f-ca8b003bd8a8]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 40s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 50s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 1m0s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 1m10s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 1m20s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Still modifying... [id=2d7d38a9-93d2-42dd-9a8d-9fdb515d3325, 1m30s elapsed]
module.packetfabric-cloud-router["dev-environment"].packetfabric_cloud_router_bgp_session.aws["dev-environment"]: Modifications complete after 1m32s [id=eaced31b-cbb3-4d39-a1a6-682d20584ae4]

Apply complete! Resources: 0 added, 2 changed, 0 destroyed.

Back in the PacketFabric portal, we can verify the new prefix 198.168.5.0/24 has been added to the “Allowed prefixes to cloud” list for the AWS connection and also added to the “Allowed prefixes from cloud” list for the GCP connection.

AWS BGP settingsGCP BGP settings

Using Terraform in a CI/CD pipeline

It is worth noting that the Terraform code and JSON files can be stored on a source code repository such as GitHub or GitLab. When changes are made to these files and committed to the repository, they can be automatically detected by a continuous integration/continuous delivery (CI/CD) pipeline. The pipeline can then trigger a Terraform run, using the newly committed code and JSON files.

In this scenario, the pipeline would first run a Terraform initialization command to download any necessary providers and modules.

Next, the pipeline would run the terraform plan command, which generates an execution plan based on the current state of the infrastructure and the new Terraform code. This step allows the pipeline to show what changes will be made to the infrastructure before they are applied.

Finally, the pipeline would run the terraform apply command, which applies the changes to the infrastructure as per the execution plan generated.

It’s important to keep in mind that this approach requires a secure and automated way to provide the credentials to the Terraform; usually this is done via environment variables or a secrets manager.

By integrating Terraform into a CI/CD pipeline, you can ensure that your infrastructure is always in the desired state, and that changes are made in a controlled and predictable manner.

Find the Quick Start code here.

New to PacketFabric’s Terraform Provider?

Here are a few resource links to help you get started:

Learn More

Watch our recent webinar, Simplify Multi-Cloud Infrastructure Automation using Terraform and PacketFabric.


Already familiar with Terraform and want to see how you can add network infrastructure to the mix? Check out our services, request a demo, or register an account to get started today.