Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active September 25, 2024 02:05
Show Gist options
  • Save Integralist/2b4298d4d287376b8a939c4e9eadd693 to your computer and use it in GitHub Desktop.
Save Integralist/2b4298d4d287376b8a939c4e9eadd693 to your computer and use it in GitHub Desktop.
[Fastly Terraform Import] #fastly #terraform #go #import

NOTE: these instructions have been genericised from a real example, and so your mileage may vary.

I first create a provider.tf file.

terraform {
  required_providers {
    fastly = {
      source  = "fastly/fastly"
      version = "0.28.2"
    }
  }
}
provider "fastly" {
  api_key = "<API_KEY>"
}

Next I create a main.tf placeholder file (I name the resource import_testing but you will likely want to name it something different).

resource "fastly_service_v1" "import_testing" {}

I use a program called tfswitch (https://github.com/warrensbox/terraform-switcher) to manage multiple terraform versions, but you can just download the latest version direct from HashiCorp if you don't have multiple projects (e.g. each project using a different Terraform version).

I use tfswitch to install the latest version of Terraform (currently v0.15.1).

I run terraform init which displays a bunch of information, but the relevant section is in green and says "Terraform has been successfully initialized!"

I then import the service using:

terraform import fastly_service_v1.import_testing <SERVICE_ID>

Notice the use of import_testing as the name I assigned to the fastly_service_v1 resource. If you decide to change the name as I suggested earlier, you will want to be sure to update this command to reflect that change. Also <SERVICE_ID> should be replaced with your actual Service ID.

Running this command will display some information, but the relevant section is in green and says "Import successful!".

I don't need to run the next command, but I like to have a look at the local state straight after an initial import:

terraform show

The show subcommand pretty prints the internal Terraform state (i.e. what's in the terraform.tfstate that has been created in the local directory where the other Terraform files, provider.tf/main.tf are located).

The next crucial command is to run:

terraform show -no-color > main.tf

This will overwrite the 'placeholder' content that was in the main.tf file with a bunch of Terraform HCL code.

This code is a HCL version of the Terraform internal state, which will include a bunch of things that shouldn't be present in a typical Terraform file you would normally write manually by hand.

This means I need to manually edit the updated main.tf content so it doesn't include internal state attributes that would cause a terraform plan to get confused. I start by first executing terraform validate to be sure that otherwise Terraform is happy.

This should print the message "Success! The configuration is valid."

At this point I also run a terraform plan to see if Terraform thinks any changes are needed (I know from experience that Terraform will be confused and so I typically run this just out of interest).

I can see in the output (I've shortened it for brevity):

~ resource "fastly_service_v1" "import_testing" {
    + comment  = "Managed by Terraform"
    + vcl {
        + content = <<-EOT
    - vcl {
        - content = <<-EOT
        - main    = true -> null
        - name    = "customvcl" -> null

So we can see from this that it is seeing comment as a new attribute and the vcl attribute is being deleted and recreated.

So here's where I open up main.tf and manually remove attributes I know should be deleted (and add/modify certain attributes)...

Attributes to delete:

  • active_version
  • id

Attributes to add:

  • comment = "" (I just added it under the name = "<...>" attribute).

Attributes to modify:

  • content (inside the vcl block) should no longer use <<-EOT inlined VCL and should now become content = file("vcl/main.vcl")

That last point will require you to download your main VCL file and stick it inside a vcl directory next to your other Terraform files provider.tf and main.tf.

One other change I need to make is to the terraform.state file itself. I modify this file so that "activate": null becomes "activate": true. The activate field is specific to the Fastly Terraform Provider and is not returned by the Fastly API and so that's why we need to tweak it when doing an import of a service.

Although not used in this example, I've historically had to delete fields such as dictionary_id.

NOTE: If you see any (sensitive value) values, then replace them with actual secrets (although it might be best to use file() for multi-line keys). You should have a read through Fastly's "Orchestration using Terraform and the Fastly Terraform Provider" which has a best practices section that covers how to handle sensitive data.

Now if I run a terraform plan I'll see:

No changes. Infrastructure is up-to-date.
#!/usr/bin/env bash
#
# Explanation:
# I use this to help me identify when newlines are causing diff conflicts.
# Get plan
terraform plan -out=tfplan > /dev/null 2>&1
# Convert plan to json
CHANGES=$(terraform show -json tfplan | jq '.resource_changes[].change')
# Diff before and after with newlines expanded
diff -u \
<(echo "$CHANGES" | jq '.before' | sed 's/\\n/\//g') \
<(echo "$CHANGES" | jq '.after' | sed 's/\\n/\//g')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment