Appendix
All Exercises

All Exercises

Module 3: Providers

New File

Create a file named provider.tf in your local clone of your GitHub repository. Populate it as the example above.

Update

Update the Akamai required version to use the ~> operator, and specify only the Major and Minor versions, e.g. 1.1, rather than 1.1.0. This means that Terraform will install any minor updates when running init, but not the next major version. Make sure Terraform uses the most recent version.

Run

Run terraform init. Which version was installed?

Commit

Commit your change and push it to GitHub.

Module 4: Data Sources

New File

Create a Terraform file named main.tf which contains 3 data sources:

  • akamai_group, referencing a single group.
ℹ️

Hint: In techdocs check the Base IDs (opens in a new tab) section.

  • akamai_appsec_configuration, referencing a single config
  • akamai_property, referencing a single Akamai property

Run

Run a terraform apply

Q&A

What happens?

Commit

Commit your changes and push them to GitHub.

Module 5: Resources

Exercise #1

New File

Create a terraform file named security.tf with an akamai_appsec_configuration resource and an akamai_appsec_security_policy resource

Configure

Configure the akamai_appsec_security_policy resource to get its config_id from the data.akamai_appsec_configuration.

Apply

Run a terraform apply

Reconfigure

Duplicate the policy resouce and make the necessary modifications to create a new policy.

Apply

Run another terraform apply

Destroy

Run a terraform destroy. What happens?

Re-Apply

Re-apply your terraform code to recreate your resources as we may need them later on.

Commit

Commit your changes and push them to GitHub.

Exercise #2

New File

Create a terraform file named property.tf with the following resources:

  • CP Code: use the resource akamai_cp_code to create a new CP code with the name, contract_id, group_id, product_id arguments
  • Edge Hostname: use the resource akamai_edge_hostname to create a new Edge Hostname using the required arguments according to the Akamai provider documentation.
  • Property: use the resource akamai_property to create a new property using the required arguments according to the Akamai provider documentation.

Configure

Observe you'll need to configure hostnames, rules and rule_format for the akamai_property too.

ℹ️

Hint: check the data.akamai_property_rules_builder data source in Techdocs.

Apply

Run another terraform apply

Commit

Commit your changes and push them to GitHub.

Module 6: Outputs

New File

Create a terraform file called outputs.tf

Configure

Create outputs with the IDs for all 3 data sources created in the Exercises section in module 4. Data Sources

Plan

Run terraform plan. What's different in Terraforms output in the terminal?

Commit

Commit your changes and push them to GitHub.

Module 7: Variables

Terraform Variables

New File

Create a variables.tf file which declares the variables edgerc_path and config_section, both of type string. Configure these with descriptions and default values.

Update

Update your provider.tf file to use these variables in the provider "akamai" block.

Init

Run terraform init and confirm the provider is installed correctly.

Plan

Run terraform plan, providing new values for the 2 variables using the -var syntax. You could run terraform apply too, but because we are not modifying any resources no changes will be applied anyway.

New File

Create a terraform.tfvars file and use it to set new values for both variables.

Plan

Re-run terraform plan using this file instead. You could run terraform apply too, but because we are not modifying any resources no changes will be applied anyway.

Commit

Commit your changes and push them to GitHub.

ℹ️

Hint: If you use terraform.tfvars you don't need to tell Terraform the variable file's name. If you use anything else (.tfvars) you must use -var-file

Locals

Configure

In your main.tf create a local named notes which could be referenced in different resources later on (e.g. akamai_appsec_activations, akamai_property).

Update

The notes local is a joined string containing a ficticious ticket ID (e.g. TF-3001) and the group ID.

Validate

Run terraform validate to confirm you don't have any sytax errors or missing statements in the code. You could run terraform plan or terraform apply too, but because we are not modifying any resources no changes will be detected/applied anyway.

Commit

Commit your change and push it to GitHub.

Environment Variables

Update

Switch to environment variables for the Akamai API Credentials instead of referring to the .edgerc file.

Module 8: Expressions

Conditionals

Configure

Define a new variable named ab_test and give it a default value of "A".

Update

In your property created in the Exercise #2 in module 5. Resources create a condition for the origin name based on the variable ab_test. That is if ab_test="A" go to Origin A (e.g. origin-a.example.com), else go to Origin B (e.g. origin-b.example.com).

Plan/Apply

Run terraform a few times and modify the value of ab_test each time.

Commit

  1. Commit your change and push it to GitHub.

for Expressions

Configure

Create the following variable in your variables.tf:

variables.tf
variable "apps" {
  default = [ "www", "api", "blog", "shop", "cdn"]
}

Update

In your main.tf and with the use of the for expression, convert each app name above into a hostname by appending the example.com domain. The new local variable containing the new hostnames list can be named app_hostnames and we will use it in later exercises.

Output

Output the app_hostnames local to confirm the logic is applied.

Plan

Run terraform plan. You could run terraform apply too, but because we are not modifying any resources no changes will be applied anyway.

Commit

Commit your change and push it to GitHub.

Dynamic Blocks

  • At this point you should have a property.tf file that creates a property with a single hostname. If not review the Exercise #2 in module 5. Resources.

  • You should also have a list of hostnames in a local variable named apps_hostnames from the previous exercise in module For Expressions.

Configure

Add a dynamic block in the akamai_property resource to add all the hostnames in the apps_hostnames list to the property. The hostnames can share the same edge hostname and other required parameters.

Plan/Apply

Run terraform plan to confirm your changes. Run terraform apply if all looks in order.

Commit

Commit your change and push it to GitHub.

Module 9: Meta-Arguments

depends_on

Update

Add 2 akamai_property_activation resources to your property.tf. One for the staging network and the other one for the production network.

ℹ️

Hint: You can use the local.notes defined in the Exercises section in module 7. Terraform Locals

Configure

Add a depends_on to the production activation resource so that the production activation doesn't start until the staging activation has completed.

Plan/Apply

Run terraform plan to confirm your changes. Run terraform apply if all looks in order.

Commit

Commit your change and push it to GitHub.

Although this is not a real use case it shows how the order of the resources updates/creations can be somewhat controlled.

count

  • You need an existing EdgeDNS zone where you can make changes. If you don't have an EdgeDNS zone, then create one outside of Terraform (we'll explain why in a bit). Chose any domain of your preference for the new EdgeDNS zone.

  • You should have a list of hostnames in a local variable named apps_hostnames from the previous exercise in module For Expressions.

New File

Create a new dns.tf file and add the akamai_dns_record resource. Remember that the DNZ zone name must match your already deployed zone name.

Configure

Using count configure akamai_dns_record to create as many CNAME records as entries in apps_hostnames.

Plan/Apply

Run terraform plan to confirm your changes. Run terraform apply if all looks in order.

ℹ️

As you can notice, Terraform will create the DNS records in the zone even if the zone is not managed by Terraform. The DNS records and zone are independent resources. This allows to manage only specific resources as code.

Commit

Commit your change and push to GitHub.

for_each

Update

Create the following variable in your variables.tf:

variables.tf
variable "dns_records" {
  default = {
    "orgigin1" = {
      zone       = "example.com"
      recordType = "A"
      ttl        = 60
      target     = "172.233.190.92"
      name       = "origin-www.example.com"
    },
    "origin2" = {
      zone       = "example.com"
      recordType = "A"
      ttl        = 100
      target     = "173.233.190.93"
      name       = "origin-api.example.com"
    },
    "origin3" = {
      zone       = "example.com"
      recordType = "A"
      ttl        = 600
      target     = "174.233.190.94"
      name       = "origin-blog.example.com"
    }
  }
}

Configure

In your dns.tf with the use of the for_each meta-argument and a single akamai_dns_record resource block create all 3 DNS records from the dns_records variable above. The values for all the arguments must be Terraform expressions.

Plan/Apply

Run terraform

Commit

Commit your change and push it to GitHub.

lifecycle

Configure

Add lifecyle ignore_changes to both of the 2 akamai_property_activation resources in your property.tf to prevent changes to the notes to trigger activations.

Plan/Apply

Run terraform

Update

Make a change to the note argument.

Plan/Apply

Run Terraform again. What happens?

Commit

Commit your change and push it to GitHub.

Module 10: Built-In Functions

Configure

In your main.tf create 3 local variables.

Update

Use at least one built-in function on each variable to change its value.

Outputs

Create outputs for the values. Although not necessary, but for standardization remember to add your outputs to your outputs.tf file.

Plan/Apply

Run terraform plan to show the outputs in the terminal. You can also run terraform apply and that will save the outputs to the Terraform state file.

Module 11: Terraform Modules

Exercise #1

New Directory

Create a new directory named modules, and inside it a sub-directory named edgeworkers. So you end up with ./modules/edgeworkers.

New Module

In your ./modules/edgeworkers create all the necessary *.tf files to create a new EdgeWorker ID. Make sure that the name, group_id and resource_tier_id are parameters that can be set by the root module.

New File

Back in your root directory create a new edgeworkers.tf file and add the necessary Terraform code to call the EdgeWorkers module.

Plan

Run a terraform plan. Why do you need to run a terraform init?

Init

After running the terraform init try to run the terrform plan again. What happened?

ℹ️

Hint: remember to define the akamai provider in the child modules.

Plan/Apply

After defining the provider in your child module run terraform plan and terraform apply.

Commit

Commit your changes and push them to GitHub.

Exercise #2

Configure

In your property.tf you should have the rule tree defined in a data.akamai_property_rules_builder. Convert this data source to a Terraform module instead.

  • Create a new directory inside the modules directory and name it rules. So ./modules/rules
  • Add all the necessary child module *.tf files inside this directory.
ℹ️

Hint: remember to create the variables.tf with any of the parameters needed for your rule tree. If you've been following along you should have 2 parameters in the rule tree: ab_test for the origin selection and the akamai_cp_code.my_cp_code.id. These 2 values will be arguments when you call the module.

Update

Use your new child module in you property.tf to build the rule tree and update the akamai_property accordingly.

ℹ️

Hint: remember that the akamai_property resource requires the rule_format and rules argument which should be updated with the expression to reference the newly created module. Also keep in mind that you need to define these values as outputs in the child module.

Plan/Apply

Run Terraform.

Commit

Commit your changes and push them to GitHub.

Module 12: State File

This is an optional but highly encourage exercise. If you don't have access to Linode Object Storage you can configure any other compatible remote backend.

New S3 Bucket

In Linode setup an Object Storage (S3) bucket to store the state file.

API Access

If you don't have the necessary access credentials follow the instructions in the Linode API Requirements section.

Configure

Configure Terraform to store the state file in the remote backend.

Init

Run terraform init --reconfigure to apply the new backend configuration.

Commit

Commit your changes and push them to GitHub.

Module 13: Terraform Imports

New File

Create a new gtm.tf file and add the akamai_gtm_domain resource with all the necessary parameters for the domain you want to import.

Plan

Run a terraform plan. Is Terraform going to add a new GTM domain or reuse the existing one at this point?

State

Run a terraform state list and look for the akamai_gtm_domain resource. Did you find it? Why not?

Import

Import the GTM domain into Terraform's state file.

ℹ️

Hint: refer to the akamai_gtm_domain resource documentation in Techdocs (opens in a new tab). You could also use the Akamai CLI to export a GTM domain.

Check the State

Run a terraform state list command to verify the new resource has been succeessfuly imported to the state file.

Plan

Run another terraform plan. What happens now?

Commit

Commit your changes and push them to GitHub.

Module 14: Troubleshooting

Configure

Enable logging for the Akamai API calls and review the output. Try to make sense of all the API calls happening based on your Terraform configuration.

ℹ️

Note: if you enabled logging to a log file be sure to add it to your .gitignore file to prevent from uploading it to your repository.

Project Structure

For reference only, if you followed along and completed all the exercises you will end up with a project structure similar to the following:

    • dns.tf
    • edgeworkers.tf
    • gtm.tf
    • main.tf
    • outputs.tf
    • property.tf
    • providers.tf
    • security.tf
    • terraform.tfstate
    • terraform.tfvars
    • variables.tf
        • edgeworkers.tf
        • providers.tf
        • variables.tf
        • outputs.tf
        • providers.tf
        • rules.tf
        • variables.tf