Skip to content

Terraform Basics

← Back to all decks

142 cards β€” 🟒 27 easy | 🟑 72 medium | πŸ”΄ 28 hard

🟒 Easy (27)

1. What is the purpose of output in Terraform?

Show answer Outputs in Terraform allow you to expose selected values or computed results from your infrastructure configuration. These values can be useful for understanding the outcome of a Terraform run or for sharing specific information with other Terraform configurations. Outputs are declared using the output block, and their values can be referenced in other Terraform configurations or scripts. For example, you might define an output to expose the public IP address of a provisioned resource for external use.

2. What are locals in Terraform and how do they simplify configurations?

Show answer Similarly to variables they serve as placeholders for data and values. Differently from variables, users can't override them by passing different values.

Remember: "HCL = HashiCorp Configuration Language." It's declarative β€” you describe the end state, Terraform figures out how to get there.

3. What is the Terraform Registry?

Show answer The Terraform Registry provides a centralized location for official and community-managed providers and modules.

Ref: https://registry.terraform.io/ β€” hosts 3,000+ providers and 15,000+ modules. Verified modules have a blue checkmark from HashiCorp.

Remember: "Variables go in variables.tf, outputs go in outputs.tf, main resources go in main.tf." This is convention, not requirement.

4. What are meta-arguments in Terraform?

Show answer Arguments that affect the lifecycle of a resources (its creation, modification, ...) and supported by Terraform regardless to the type of resource in which they are used.

Some examples:

- count: how many resources to create out of one definition of a resource
- lifecycle: how to treat resource creation or removal

5. What is the Terraform plan command used for?

Show answer The terraform plan command is used to preview the changes that Terraform will make to the infrastructure based on the current configuration. It analyzes the configuration files, compares the desired state with the existing state, and generates an execution plan. The plan includes details such as which resources will be added, modified, or destroyed. Running terraform plan allows users to review potential changes before applying them, providing an opportunity to catch errors or unintended modifications.

6. What is a "data source" in Terraform?

Show answer Allows fetching information from external systems to use in code.

Example: data "aws_ami" "ubuntu" { filter { name = "name" values = ["ubuntu/images/*22.04*"] } } fetches the latest Ubuntu AMI without creating any resources.

7. How to list resources created with Terraform?

Show answer `terraform state list`

Under the hood: reads the state file and lists all resource addresses Terraform manages. Use terraform state show
for full details on a specific resource.

8. What's the default input variable type in Terraform?

Show answer `any`. When no type constraint is specified, Terraform accepts any value type. In practice, always declare explicit types (`string`, `number`, `list`, `map`, `bool`) for safety and documentation.

9. What is terraform init and when do you run it?

Show answer terraform init initializes a Terraform working directory – it downloads provider plugins, sets up the backend, and prepares the environment. You run it once per project (or whenever providers/modules change).

10. What are input variables good for in Terraform?

Show answer Variables allow you define piece of data in one location instead of repeating the hardcoded value of it in multiple different locations. Then when you need to modify the variable's value, you do it in one location instead of changing each one of the hardcoded values.

11. What does terraform init do?

Show answer Initializes the working directory and downloads provider plugins.

Under the hood: init downloads providers to .terraform/, initializes the backend (local or remote state), and installs module sources. Must run after any provider or backend change.

12. What is the primary language used by Terraform?

Show answer HCL (HashiCorp Configuration Language).

Fun fact: HCL (HashiCorp Configuration Language) was created specifically for infrastructure-as-code β€” human-readable like YAML but with first-class support for expressions and blocks.

13. How to create a number of resources based on the length of a list?

Show answer ```\nresource "some_resource" "some_name" {\n count = length(var.some_list)\n}\n```

Remember: "Backend config is in the terraform {} block." Backend determines where state is stored (local, S3, GCS, Consul, etc.).

14. What is the purpose of terraform validate?

Show answer Checks the syntax and consistency of configuration files.

Gotcha: validate checks syntax and type constraints but does NOT check that resource configurations are valid against the provider API. terraform plan catches those errors.

Remember: "Provider aliases allow multiple provider configurations." Useful for multi-region or multi-account setups.

15. What is the purpose of Terraform data sources?

Show answer Terraform data sources allow you to query and retrieve information from external sources during the Terraform execution. Data sources do not create or manage resources but provide read-only access to external data, such as existing infrastructure details or information from APIs. Examples of data sources include querying AWS AMIs, getting information from external databases, or fetching details from a configuration management database (CMDB).

16. What is a Terraform module?

Show answer A Terraform module is a set of Terraform configuration files in a directory, encapsulating a logical grouping of resources for reuse. Every Terraform configuration is implicitly a "module" (root module), and you can create child modules to abstract and reuse infrastructure components (like a module for a VPC, a module for a web server cluster).

Remember: "Check blocks validate infrastructure without blocking applies." They warn instead of failing.

17. True or False? Terraform console should be used carefully as it may modify your resources

Show answer False. terraform console is ready-only.

Under the hood: terraform console loads state and variables, letting you test expressions interactively. Great for debugging interpolations: try type(var.my_list) or length(var.my_map).

18. What templatefile function does?

Show answer Renders a template file and returns the result as string.

Example: templatefile("user_data.sh.tpl", { hostname = var.name }) renders the template with the given variables. Replaces the deprecated template_file data source.

19. What language does Terraform uses?

Show answer A DSL called "HCL" (Hashicorp Configuration Language). A declarative language for defining infrastructure.

Fun fact: HCL was designed to be human-friendly (like YAML) but machine-parseable (like JSON). You can write Terraform in JSON too, but HCL is standard.

20. What does terraform taint do?

Show answer `terraform taint ` marks a resource for destruction and recreation on the next `terraform apply`. Useful when a resource is in a bad state but Terraform thinks it is fine. Modern alternative: `terraform apply -replace=` is preferred since Terraform 0.15.2 and does not require a separate command.
Gotcha: tainting a resource may cause dependent resources to also be updated.

21. Explain the following condition: var.x != "" ? var.x : "yay"

Show answer If `x` is an empty string the result is "yay", otherwise it's the value of `x` variable

Remember: "State locking prevents concurrent modifications." DynamoDB for S3 backend, built-in for Terraform Cloud.

22. What is local-exec and remote-exec in the context of provisioners?

Show answer `local-exec` provisioners run commands on the machine where Terraform is executed, while `remote-exec` provisioners run commands on the remote resource.

Remember: "terraform plan -out=plan.tfplan saves the plan." Then terraform apply plan.tfplan applies exactly that plan.

23. Explain the following condition: var.x ? 1 : 0

Show answer `var.x ? 1 : 0` β€” if variable x evaluates to true, the result is 1; otherwise it is 0. This is commonly used with `count` to conditionally create resources: `count = var.create_resource ? 1 : 0`. When count is 0, the resource is not created at all. This pattern is the standard way to make Terraform resources optional.

24. True or False? Applying the following Terraform configuration will fail since no source or version specific for 'aws' provider

Show answer False. It will look for "aws" provider in the public Terraform registry and will take the latest version.

Remember: "terraform providers lock generates .terraform.lock.hcl." It pins provider versions and checksums for reproducible builds.

25. What is the purpose of terraform plan?

Show answer Shows an execution plan of changes to be applied.

Remember: "Terraform debug: TF_LOG=DEBUG terraform plan shows verbose logs." Levels: TRACE, DEBUG, INFO, WARN, ERROR.

26. What is a "tainted resource"?

Show answer It's a resource which was successfully created but failed during provisioning. Terraform will fail and mark this resource as "tainted".

Remember: "replace_triggered_by forces recreation when another resource changes."

27. What command applies the proposed changes?

Show answer `terraform apply` executes the proposed changes to reach the desired infrastructure state. It first runs a plan (unless you pass a saved plan file), shows the diff, and asks for confirmation. Use `terraform apply -auto-approve` to skip confirmation in CI pipelines.
Gotcha: always run `terraform plan` first in production to review changes before applying.

🟑 Medium (72)

1. You have a list variable called "users" with an object containing a name attribute like this:

Show answer `users[1].name`

Remember: "Terraform has five core commands: init, plan, apply, destroy, and fmt."

Example: terraform init downloads providers, terraform plan shows changes, terraform apply executes them.

2. You have a map variable, called "users", with the keys "name" (string) and "age" (number). Define an output map variable with the key being name in uppercase and value being age in the closest whole number

Show answer ```\noutput "name_and_age" {\n value = {for name, age in var.users : upper(name) => floor(age)\n}\n```

Remember: "terraform init = download providers + initialize backend." Always run init first in a new directory or after adding providers.

3. What's a for_each loop? How is it different from "count"?

Show answer - for_each can applied only on collections like maps or sets (as opposed to count that can be applied on lists)
- for_each helps to deal with the limitation of `count` which isn't optimal for use cases of modifying lists
- for_each supports inline blocks as opposed to `count`

4. Demonstrate how to define locals

Show answer ```\nlocals {\n x = 2\n y = "o"\n z = 2.2\n}\n```

Remember: "terraform plan = dry run." It shows what will be created, changed, or destroyed WITHOUT making changes.

Example: + means create, ~ means modify, - means destroy in plan output.

5. Explain the "depends" parameter of output variable

Show answer It is used to set explicitly dependency between the output variable and any other resource. Use case: some piece of information is available only once another resource is ready.

Remember: "Outputs expose values after apply." Useful for passing info between modules or to other tools.

Example: output "instance_ip" { value = aws_instance.web.public_ip }

6. You would like to change the name of a resource but afraid to cause downtime. What can be done?

Show answer If it's a matter of changing a resource name, you could make use of `terraform state mv `

Under the hood: state mv updates the state file's resource address without modifying real infrastructure. Use it when refactoring code (renaming resources or moving into modules).

Gotcha: always back up state before state operations. Use terraform state pull > backup.json.

7. Explain what depends_on used for and given an example

Show answer `depends_on` used to create an explicit dependency between resources in Terraform. For example, there is an application you would like to deploy in a cluster. If the cluster isn't ready (and also managed by Terraform of course) then you can't deploy the app. In this case, you will define "depends_on" in the app configuration and its value will be the cluster resource.

8. How to define an input variable which is an object with attributes "model" (string), "color" (string), year (number)?

Show answer ```\nvariable "car_model" {\n description = "Car model object"\n type = object({\n model = string\n color = string\n year = number\n })\n}\n```

Note: you can also define a default for it.

Gotcha: create_before_destroy prevents downtime during replacement but can cause name conflicts. prevent_destroy stops accidental deletion.

9. The same variable is defined in the following places:

Show answer Terraform loads variables in the following order, with later sources taking precedence over earlier ones:

- Environment variable
- The file `terraform.tfvars`
- Using `-var` or `-var-file`

Remember: "for_each > count for named resources." count creates indexed resources; for_each creates named resources (aws_instance.web["app1"]).

10. What is a data source? In what scenarios for example would need to use it?

Show answer Data sources lookup or compute values that can be used elsewhere in terraform configuration.

There are quite a few cases you might need to use them:

- you want to reference resources not managed through terraform
- you want to reference resources managed by a different terraform module
- you want to cleanly compute a value with typechecking, such as with `aws_iam_policy_document`

11. What are "Provisioners"? What they are used for?

Show answer Provisioners can be described as plugin to use with Terraform, usually focusing on the aspect of service configuration and make it operational.

Few example of provisioners:

- Run configuration management on a provisioned instance using technology like Ansible, Chef or Puppet.
- Copying files
- Executing remote scripts

12. How do you test terraform syntax?

Show answer A valid answer could be "I write Terraform configuration and try to execute it" but this makes testing cumbersome and quite complex in general.

There is `terraform console` command which allows you to easily execute terraform functions and experiment with general syntax.

13. What type of input variables are supported in Terraform?

Show answer ```\nstring\nnumber\nbool\nlist()\nset()\nmap()\nobject({ = , ... })\ntuple([, ...])\n```

Remember: "Provisioners are a last resort." Use user_data, cloud-init, or config management (Ansible) instead when possible.

14. What happens if you update user_data in the following case and apply the changes?

Show answer Nothing, because user_data is executed on boot so if an instance is already running, it won't change anything.

To make it effective you'll have to use `user_data_replace_on_change = true`.

Remember: "terraform fmt = auto-format HCL." Run it before every commit. terraform fmt -check in CI verifies formatting.

15. What language do Terraform configuration files use?

Show answer The HashiCorp Configuration Language (HCL), which is declarative and human-readable (usually files with .tf extension). Terraform can also optionally accept JSON configuration, but HCL is most common.

Remember: "terraform validate = syntax check." It catches typos, invalid references, and type errors without contacting any provider API.

16. What makes a Terraform code module? In other words, what a module is from practical perspective?

Show answer Basically any file or files in a directory is a module in Terraform. There is no special syntax to use in order to define a module. The root configuration is itself a module, and any module that is called from it is considered a child module.

17. What loops are useful for in Terraform?

Show answer The most common use case is when you need to create multiple resources with only a slight difference (like different name). Instead of defining multiple separate resources, you can define it once and create multiple instances of it using loops.

18. How to reference variable from inside of string literal? (bonus question: how that type of expression is called?)

Show answer Using the syntax: `"${var.VAR_NAME}"`. It's called "interpolation".

Very common to see it used in user_data attribute related to instances.

```\nuser_data = <<-EOF\n This is some fabulos string\n It demonstrates how to use interpolation\n Yes, it's truly ${var.awesome_or_meh}\n EOF\n```

19. Describe in high level what happens behind the scenes when you run terraform init on on the following Terraform configuration

Show answer 1. Terraform checks if there is an aws provider in this address: `registry.terraform.io/hashicorp/aws`
2. Installs latest version of aws provider (assuming the URL exists and valid)

Remember: "Locals = computed constants." Use them to avoid repeating expressions.

Example: locals { env_prefix = "${var.project}-${var.env}" }

20. How do you rename an existing resource?

Show answer `terraform state mv`

Under the hood: state mv updates the state file's resource address without modifying real infrastructure. Use it when refactoring code (renaming resources or moving into modules).

Gotcha: always back up state before state operations. Use terraform state pull > backup.json.

Remember: "Data sources READ existing resources, Resources CREATE/MANAGE them."

21. Discuss the differences between "Terraform Apply" and "Terraform Plan."

Show answer * terraform plan: Generates an execution plan describing the changes Terraform will make without applying them. It's a dry run to preview changes.
* terraform apply: Executes the changes described in the execution plan, applying the proposed modifications to the infrastructure.

22. There is a list variable called "users". You would like to define an output variable with a value of all users in uppercase. How to achieve that?

Show answer ```\noutput "users" {\n value = [for name in var.user_names : upper(name)]\n}\n```

Remember: "depends_on = explicit ordering." Use it when Terraform can't infer the dependency from resource references.

Gotcha: Most dependencies are implicit β€” only use depends_on for hidden dependencies.

23. Does it matter in which order Terraform creates resources?

Show answer Yes, when there is a dependency between different Terraform resources, you want the resources to be created in the right order and this is exactly what Terraform does.

To make it ever more clear, if you have a resource X that references the ID of resource Y, it doesn't makes sense to create first resource X because it won't have any ID to get from a resource that wasn't created yet.

Remember: "terraform destroy = delete everything in state." Always plan before destroy: terraform plan -destroy.

24. How do you test a Terraform module?

Show answer There are multiple answers, but the most common answer would likely to be using the tool `terratest`, and to test that a module can be initialized, can create resources, and can destroy those resources cleanly. You can also rely on `terraform validate`, `terraform plan` with sample configurations, and linting tools such as `tflint`.

25. There is a variable called "values" with the following value: ["mario", "luigi", "peach"]. How to create an output variable with the string value of the items in the list: "mario, luigi, peach," ?

Show answer ```\noutput "users" {\n value = "%{ for name in var.values }${name}, %{ endfor }"\n}\n```

Remember: "Dynamic blocks generate repeated nested blocks." Useful for security group rules, tags, etc.

26. Demonstrate how to use data sources

Show answer Data sources let you fetch information from existing infrastructure.
Example: `data "aws_vpc" "default" { default = true }` reads the default VPC. Reference its attributes with `data.aws_vpc.default.id`. Data sources are read-only β€” Terraform never modifies the referenced resource. Use them to look up AMI IDs, VPC IDs, or AZ lists dynamically.

27. The following resource tries to use for_each loop on a list of strings but it fails, why?

Show answer for_each can applied only on collections like maps or sets so the list should be converted to a set like this: `for_each = toset(var.names)`

Remember: "terraform graph outputs DOT format." Pipe to Graphviz: terraform graph | dot -Tpng > graph.png.

28. Explain data sources in Terraform

Show answer - Data sources used to get data from providers or in general from external resources to Terraform (e.g. public clouds like AWS, GCP, Azure).
- Data sources used for reading. They are not modifying or creating anything
- Many providers expose multiple data sources

Remember: "Workspaces = multiple state files in one config." terraform workspace new staging creates a separate state.

Gotcha: Many teams prefer separate directories over workspaces for clearer separation.

29. Is there such a thing as combining data sources? What would be the use case?

Show answer Yes, you can define a data source while using another data source as a filter for example.

Let's say we want to get AWS subnets but only from our default VPC:

```\ndata "aws_subnets" "default" {\n filter {\n name = "vpc-id"\n values = [data.aws_vpc.default.id]\n }\n}\n```

30. Whenever you run terraform apply, it prompts to enter a value for a given variable. How to avoid being prompted?

Show answer While removing the variable is theoretically a correct answer, it will probably fail the execution.

You can use something like the `-var` option to provide the value and avoid being prompted to insert a value. Another option is to run `export TF_VAR_=`.

31. Explain the role of "Terraform Variables" and their different types.

Show answer Terraform variables are parameters that allow users to input values into configurations. Types of Terraform variables include:
* Input Variables: Defined in configurations and initialized by users when running Terraform commands.
* Output Variables: Represent values that can be queried and used by other configurations.
* Local Variables: Defined within a module and used for intermediate computations.

Remember: "Terraform registry = module marketplace." Use verified modules to avoid reinventing the wheel.

32. Why is it often recommended to use provisioners as last resort?

Show answer Since a provisioner can run a variety of actions, it's not always feasible to plan and understand what will happen when running a certain provisioner. For this reason, it's usually recommended to use Terraform built-in option, whenever's possible.

33. How can list all outputs without applying Terraform changes?

Show answer `terraform output` will list all outputs without applying any changes

Remember: "Version constraints: ~> 1.5 means >= 1.5.0 and < 2.0.0. ~> 1.5.0 means >= 1.5.0 and < 1.6.0."

Gotcha: Pin provider versions to avoid surprise breaking changes.

34. How to cleanup Terraform resources? Why the user should be careful doing so?

Show answer `terraform destroy` will cleanup all the resources tracked by Terraform.

A user should be careful with this command because there is no way to revert it. Sure, you can always run again "apply" but that can take time, generates completely new resources, etc.

Remember: "terraform taint is deprecated β€” use terraform apply -replace=RESOURCE instead (Terraform 0.15.2+)."

35. What do you do next after writing the following in main.tf file?

Show answer Run `terraform init`. This will scan the code in the directory to figure out which providers are used (in this case AWS provider) and will download them.

36. You have a map variable, called "users", with the keys "name" and "age". Define an output list variable with the following "my name is {name} and my age is {age}"

Show answer ```\noutput "name_and_age" {\n value = [for name, age in var.users : "my name is ${name} and my age is ${age}"]\n}\n```

Remember: "sensitive = true hides values in plan/apply output." But values are still in state file β€” encrypt your state.

37. Demonstrate input variable definition with type, description and default parameters

Show answer ```\nvariable "app_id" {\n type = string\n description = "The id of application"\n default = "some_value"\n}\n```

Unrelated note: variables are usually defined in their own file (vars.tf for example).

Remember: "terraform import brings existing resources under Terraform management." It adds to state but does NOT generate config.

Gotcha: Write the HCL first, then import.

38. Discuss the role of "Terraform Count" and its implications on infrastructure scaling.

Show answer terraform count is used to create multiple instances of a resource. Implications include:
* Dynamic Scaling: Allows dynamic scaling based on the count value.
* Resource Duplication: Creates multiple resource instances with similar configurations.
* Consistency: Ensures a consistent approach to scaling infrastructure.

39. How to get data out of a data source?

Show answer The general syntax is `data...`

So if you defined the following data source

```\ndata "aws_vpc" "default {\n default = true\n}\n```

You can retrieve the ID attribute this way: `data.aws_vpc.default.id`

40. You've downloaded the providers, seen the what Terraform will do (with terraform plan) and you are ready to actually apply the changes. What should you do next?

Show answer Run `terraform apply`. That will apply the changes described in your .tf files.

Remember: "Null resource + triggers = run provisioners on changes." Replaced by terraform_data in Terraform 1.4+.

41. What's the result of the following code?

Show answer The above code will fail as it's not possible to reference resource outputs with count, because Terraform has to compute count before any resources are created (or modified).

42. You need to render a template and get it as string. Which function would you use?

Show answer The `templatefile` function renders a template file and returns it as a string.
Example: `templatefile("${path.module}/user-data.sh", { name = var.name })` replaces `${name}` in the template. It replaced the deprecated `template_file` data source. Supports full Terraform expression syntax inside `${}` interpolations.

43. You have the following variable defined in Terraform

Show answer Use `count = length(var.users)` with `var.users[count.index]` to create multiple resources from a list variable.
Example: `resource "aws_iam_user" "user" { count = length(var.users); name = var.users[count.index] }`. Alternative: use `for_each` with a set for more stable resource addresses β€” count-based resources shift indexes when items are removed.

44. What meta-arguments are you familiar with?

Show answer - count: how many resources to create out of one definition of a resource
- lifecycle: how to treat resource creation or removal
- depends_on: create a dependency between resources

Remember: "Terraform functions: lookup(map, key, default), merge(map1, map2), join(sep, list), split(sep, string)."

45. How do you delete all Terraform-managed resources?

Show answer terraform destroy.

Gotcha: terraform destroy deletes ALL managed resources. In production, use targeted destroys: terraform destroy -target=aws_instance.example. Always review the plan before confirming.

Remember: "Preconditions validate inputs, Postconditions validate results." Both go inside lifecycle or variable blocks.

46. Explain the following block of Terraform code

Show answer It's a resource of type "aws_instance" used to provision an instance. The name of the resource (NOT INSTANCE) is "some-instance".

The instance itself will be provisioned with type "t2.micro" and using an image of the AMI "ami-201720221991yay".

47. How to use conditional expressions in Terraform?

Show answer Terraform conditional expression: `condition ? value_if_true : value_if_false`.
Example: `instance_type = var.env == "prod" ? "m5.large" : "t3.micro"` selects instance size based on environment.
Gotcha: both branches must return the same type. You can nest conditionals but prefer locals for complex logic to maintain readability.

48. Demonstrate how to use a local

Show answer if we defined something like this

```\nlocals {\n x = 2\n}\n```

then to use it, you have to use something like this: `local.x`

Remember: "Heredoc syntax for multi-line strings: <<-EOT content EOT." The - allows indentation stripping.

49. What's the use case for using locals?

Show answer You have multiple hardcoded values that repeat themselves in different sections, but at the same time you don't want to expose them as in, allow users to override values.

50. Can conditionals be used with meta-arguments?

Show answer Yes, for example the "count" meta-argument:

```\nresource "aws_instance" "server" {\n count = var.amount ? 1 : 0\n ...\n}\n```

Remember: "Terraform collection types: list (ordered), map (key-value), set (unique, unordered)."

51. Explain the meaning of the following strings that seen at the beginning of each line When you run terraform apply

Show answer - '+' - The resource or attribute is going to be added
- '-' - the resource or attribute is going to be removed
- '-/+' - the resource or attribute is going to be replaced

52. Demonstrate how to define a simple Terraform loop

Show answer ```\nresource "aws_instance" "server" {\n count = 15\n}\n```

The above configuration will create 15 aws instances.

Remember: "Terraform cloud/enterprise adds: remote state, policy as code (Sentinel), VCS integration, and run triggers."

53. Explain the "sensitive" parameter of output variable

Show answer When set to "true", Terraform will avoid logging output variable's data. The use case for it is sensitive data such as password or private keys.

Remember: "Ignore changes with lifecycle { ignore_changes = [tags] }." Useful when external systems modify attributes.

54. Given the same list, how to access attribute "name" of all items?

Show answer `users[*].name` uses the splat expression to access the 'name' attribute of every item in the 'users' list. Equivalent to `[for u in users : u.name]`. The `[*]` syntax works on lists and sets. For maps, use `values(map)[*].attr`.
Gotcha: splat only works one level deep β€” for nested access, use a `for` expression instead.

55. Demonstrate using a module called "amazing_modle" in the path "../modules/amazing-module"

Show answer Reference a module with a source path: `module "amazing_module" { source = "../modules/amazing-module" }`. Sources can also be Git URLs, S3 buckets, or the Terraform Registry. After adding a module, run `terraform init` to download it. Pass variables with `variable_name = value` inside the module block. Outputs are accessed via `module.amazing_module.output_name`.

56. What ways are there to pass values for input variables?

Show answer - Using `-var` option in the CLI
- Using a file by using the `-var-file` option in the CLI
- Environment variable that starts with `TF_VAR_`

If no value given, user will be prompted to provide one.

Remember: "Heredoc syntax: <<-EOT content EOT." The - strips leading whitespace for cleaner indentation.

57. Can you see the output of specific variable without applying terrafom changes?

Show answer Yes, `terraform output ` displays a specific output value without running apply. Use `terraform output -json` for machine-readable format, useful in scripts: `DB_HOST=$(terraform output -raw db_endpoint)`.
Gotcha: outputs only reflect the last applied state β€” if you changed config but haven't applied, the output shows the old value.

58. There is a map called "instances"

Show answer Use the `values()` built-in function: `values(instances)` returns all values from the map as a list. Then `values(instances)[*].name` extracts the name attribute from each value using a splat expression. Alternative: `[for k, v in instances : v.name]` using a for expression.
Gotcha: `values()` returns items in lexicographic key order, not insertion order.

59. You've executed terraform init and now you would like to move forward to creating the resources but you have concerns and would like to make be 100% sure on what you are going to execute. What should you be doing?

Show answer `terraform plan` shows a detailed preview of what Terraform will create, update, or destroy when you run apply. It compares your configuration against the state file and real infrastructure. Save a plan for exact replay: `terraform plan -out=plan.tfplan` then `terraform apply plan.tfplan`. Always review the plan before applying, especially for destructive changes marked with a minus sign.

60. Discuss the use of "Terraform Provisioners" for configuration management.

Show answer Terraform provisioners execute scripts on local or remote machines during resource creation. They are used for tasks like:
* Software Installation: Installing applications or dependencies.
* Configuration: Configuring instances after creation.
* Bootstrapping: Initializing systems for application deployment.

Remember: "Provisioners: local-exec runs on YOUR machine, remote-exec runs on the CREATED resource."

Gotcha: remote-exec needs SSH/WinRM connectivity.

61. How do you preview infrastructure changes in Terraform without applying them?

Show answer Run terraform plan. This will show the diff of what will be created, changed, or destroyed, but will not actually make any changes.

62. Demonstrate how to use the for_each loop

Show answer ```\nresource β€œgoogle_compute_instance” β€œinstances” {\n\n for_each = var.names_map\n name = each.value\n}\n```

Remember: "TF_VAR_name sets variables, TF_LOG sets log level." Environment variables are the safest way to pass secrets.

63. When you update a resource, how it works?

Show answer By default the current resource is deleted, a new one is created and any references pointing the old resource are updated to point the new resource

64. How to define an input variable which is a list of numbers?

Show answer ```\nvariable "list_of_nums" {\n type = list(number)\n description = "An example of list of numbers"\n default = [2, 0, 1, 7]\n}\n```

65. You've deployed a virtual machine with Terraform and you would like to pass data to it (or execute some commands). Which concept of Terraform would you use?

Show answer Use Terraform provisioners to execute commands or scripts on a resource after creation. Types: `remote-exec` (runs commands via SSH/WinRM on the resource), `local-exec` (runs commands on the machine running Terraform), and `file` (copies files to the resource).
Gotcha: HashiCorp recommends provisioners as a last resort β€” prefer cloud-init or user_data for initial VM configuration.

66. Is there a way to print/see the dependencies between the different resources?

Show answer Yes, `terraform graph` outputs a visual representation of resource dependencies in DOT format (a graph description language). Pipe to Graphviz to render: `terraform graph | dot -Tpng > graph.png`. This helps debug dependency chains and understand why resources are created in a particular order. Useful for identifying circular dependencies or unexpected implicit dependencies.

67. How to use for_each loop for inline blocks?

Show answer ```\nresource "some_instance" "instance" {\n\ndynamic "tag" {\n for_each = var.tags\n\n content {\n key = tag.key\n value = tag.value\n }\n }\n}\n```

Remember: "Optional attributes in objects: optional(type, default)." The second argument is the default value.

68. There is a list variable called "users". You would like to define an output variable with a value of all users in uppercase but only if the name is longer than 3 characters. How to achieve that?

Show answer ```\noutput "users" {\n value = [for name in var.user_names : upper(name) if length(name) > 3]\n}\n```

Remember: "Terraform 1.6+ supports testing with terraform test." Write .tftest.hcl files with run blocks that assert conditions.

69. You manage ASG with Terraform which means you also have "aws_launch_configuration" resources. The problem is that launch configurations are immutable and sometimes you need to change them. This creates a problem where Terraform isn't able to delete ASG because they reference old launch configuration. How to do deal with it?

Show answer Add the following to "aws_launch_configuration" resource

```\nlifecycle {\n create_before_destroy = true\n}\n```

This will change the order of how Terraform works. First it will create the new resource (launch configuration). then it will update other resources to reference the new launch configuration and finally, it will remove old resources

Remember: "Custom conditions: precondition, postcondition, and variable validation all use condition + error_message blocks."

70. Is it possible to combine conditionals and loop?

Show answer Yes, for example:

```\ndynamic "tag" {\n for_each = {\n for key, value in var.tags:\n key => value\n if key != ""\n }\n}\n```

71. You try to deploy a cluster and an app on that cluster, but the app resource was created before the cluster. How to manage such situation?

Show answer Use the meta-argument `depends_on` in the app resource definition. This way the app will depend on the cluster resource and order will be maintained in creation of the resources.

72. How would you enforce users that use your variables to provide values with certain constraints? For example, a number greater than 1

Show answer Using `validation` block

```\nvariable "some_var" {\n type = number\n\n validation {\n condition = var.some_var > 1\n error_message = "you have to specify a number greater than 1"\n }\n\n}\n```

Remember: "terraform refresh updates state from real infrastructure." Prefer: terraform apply -refresh-only for explicit control.

πŸ”΄ Hard (28)

1. Discuss the concept of "Terraform HCL" and its syntax.

Show answer Terraform HashiCorp Configuration Language (HCL) is a domain-specific language used for writing Terraform configurations. Key syntax features include:
* Blocks: Defined by braces {} and contain configurations for resources, variables, etc.
* Arguments: Key-value pairs within blocks, defining resource attributes or variable values.
* Variables: Declared using the variable block and referenced using interpolation syntax.
* Providers: Declared using the provider block to specify the infrastructure platform.
* Expressions: Interpolation syntax ${} for referencing variables or performing computations.

2. Discuss the use of Terraform's "count" and "for_each" meta-arguments.

Show answer Both count and for_each are meta-arguments in Terraform used to create multiple instances of a resource.
count: Specifies the number of resource instances to create based on an integer value. For example, count = 3 creates three instances of the resource.
for_each: Allows you to create multiple instances based on a map or set of strings. Each key-value pair or string in the set represents a unique instance. This is more flexible than count as it allows dynamic creation of instances based on the elements in the map or set.

3. Explain the concept of Terraform interpolation syntax.

Show answer Terraform interpolation syntax allows you to embed expressions within strings or configurations. It is denoted by ${}. Interpolation is commonly used for referencing variables, attributes of resources, or performing calculations. For example:
```resource "aws_instance" "example" {\n ami = var.ami_id\n instance_type = "t2.micro"\n tags = {\n Name = "Example Instance - ${var.environment}"\n }\n}\n```
In this example, ${var.environment} is an interpolation that references the value of the environment variable within the string.

Gotcha: Always review the plan before applying. terraform apply -auto-approve skips confirmation (use in CI only, never interactively).

4. How do you initialize a Terraform configuration?

Show answer To initialize a Terraform configuration, you use the terraform init command. This command initializes the working directory, downloads the required providers and modules specified in the configuration, and sets up the backend. Running terraform init is typically the first step after creating or cloning a Terraform configuration. It ensures that the necessary dependencies are in place before applying any changes.

5. Explain the difference between terraform plan and terraform apply.

Show answer These are the two main commands in Terraform's workflow:

terraform plan:
- Shows what changes will be made WITHOUT executing them
- Compares current state with desired configuration
- Output shows: create, update, or destroy actions
- Safe to run repeatedly
- Can save plan to file with -out flag

terraform apply:
- Actually creates/modifies/destroys resources
- By default, shows plan first and asks for confirmation
- Can skip confirmation with -auto-approve (use cautiously)
- Can apply a saved plan file

6. How do you reference variables in Terraform configuration files?

Show answer Variables are referenced in Terraform configuration files using the syntax ${var.variable_name}. For example, if you have a variable named environment in your configuration, you can reference it in a resource block like this:
```\nresource "aws_instance" "example" {\n ami = "ami-abc123"\n instance_type = var.instance_type\n tags = {\n Name = "Example Instance - ${var.environment}"\n }\n}\n```
In this example, var.instance_type references the value of the instance_type variable, allowing for dynamic configuration based on the provided variable values.

7. Explain the concept of resources in Terraform.

Show answer In Terraform, resources represent the infrastructure components that you want to manage. Resources are declared in Terraform configuration files and correspond to entities such as virtual machines, networks, databases, and more. Each resource type is associated with a specific provider, and its configuration defines the desired characteristics of that resource. Terraform uses the configurations to create, update, or destroy the corresponding resources in the target environment.

8. How can you implement conditional logic in Terraform configurations?

Show answer Conditional logic in Terraform can be implemented using the count and for_each meta-arguments, as well as the locals block. For example:
```resource "aws_instance" "example" {\n count = var.create_instance ? 1 : 0\n ami = var.ami_id\n // other attributes\n}\n```
Here, the instance is created only if the create_instance variable is true. The locals block can be used for more complex conditions. Terraform doesn't support traditional programming constructs like if-else directly but provides these mechanisms for achieving conditional behavior.

Remember: "terraform console = interactive REPL." Test expressions before putting them in code.

9. Explain the differences between "Terraform Outputs" and "Terraform Data Sources."

Show answer * terraform outputs: Defines values that will be outputted after a successful terraform apply. Used for exposing specific information about the infrastructure.
* terraform data: Retrieves data from external sources or existing resources. Used for importing data that isn't managed by Terraform.
*Outputs provide information about the infrastructure, while data sources fetch external information for use within Terraform configurations.

10. What's the difference between terraform plan and terraform apply?

Show answer terraform plan creates an execution plan – it shows what changes Terraform would make to match the configuration (adding, changing, destroying resources) without actually performing them. terraform apply actually executes those changes to real infrastructure (and by default will also show a plan and ask for approval before proceeding).

11. Explain the purpose of "Terraform Null Resources" and when you might use them.

Show answer Null Resources in Terraform represent resources with no direct parallel in the target infrastructure. They are used for:
* Dependency Creation: Establishing dependencies between resources.
* Local Provisioning: Running local provisioners without creating a tangible resource.
* Conditional Logic: Implementing conditional logic based on changes or triggers.
Null Resources are useful for scenarios where a real resource doesn't exist, but some actions need to be performed.

Remember: "Conditional = condition ? true_val : false_val. Splat = resource[*].attribute."

Example: instance_type = var.env == "prod" ? "m5.large" : "t3.micro"

12. Explain the role of "Terraform Locals" and how they enhance configuration readability.

Show answer Terraform Locals allow the definition of named expressions to enhance configuration readability by:
* Variable Naming: Naming complex expressions for better understanding.
* Code Reusability: Enabling reuse of computed values across the configuration.
* Complex Expression Simplification: Breaking down complex expressions into more manageable parts.
* Reduced Redundancy: Avoiding redundant calculations by storing intermediate values.
* Improved Maintainability: Enhancing code maintainability by encapsulating logic.

Remember: "moved blocks handle refactoring." moved { from = old to = new } tells Terraform the resource was renamed, not deleted.

13. Discuss the role of Terraform "provisioners" in bootstrapping instances.

Show answer Terraform provisioners are used to execute scripts or commands on instances after resource creation. They play a crucial role in bootstrapping instances by:
* Configuration: Setting up software or configuring instances post-creation.
* Initialization: Running scripts for software installations or customizations.
* Integration: Coordinating with configuration management tools.
* Dependencies: Handling dependencies before applications start.

Remember: "terraform.tfvars = default variable values file." Loaded automatically. Use *.auto.tfvars for additional auto-loaded files.

14. Discuss the use of "count" and "for_each" with modules in Terraform.

Show answer count and for_each are meta-arguments in Terraform used for creating multiple instances of resources or modules.
count: Specifies the number of resource instances to create, like creating multiple identical instances.
for_each: Allows creating instances based on a map or set, enabling more dynamic configurations.
Example:
```module "example" {\n source = "./modules/example"\n count = 3\n name = "instance-${count.index}"\n}\n```
Here, the count meta-argument creates three instances of the "example" module with distinct names.

Remember: "Variable validation blocks enforce constraints before plan." Type + validation = defense in depth.

15. How can you use "Terraform Variables" to achieve dynamic configurations?

Show answer Terraform variables can be used dynamically by:
* Variable Types: Utilizing different variable types, such as string, list, map, or boolean.
* Conditional Logic: Implementing conditionals based on variable values.
* Variable Overrides: Allowing users to override default variable values.
* Dynamic Blocks: Using dynamic blocks to create dynamic configurations.
* Input Validation: Applying validation rules to ensure proper variable values.

16. What is a variable in Terraform, and how is it defined?

Show answer In Terraform, variables are placeholders for values that can be passed into the configuration. They enable the reuse and parameterization of values within Terraform files. Variables can be defined in a separate variable file (e.g., variables.tf) or directly in the main configuration file. Variable definitions include a name, a type, an optional default value, and other attributes. They can be referenced throughout the configuration to provide flexibility and make it easier to customize Terraform deployments for different scenarios.

Remember: "Count creates numbered instances, for_each creates named instances." for_each is safer because removing an item doesn't renumber everything.

17. How do you handle dependencies between resources in Terraform?

Show answer Terraform automatically handles dependencies based on the resource references in the configuration. When one resource references another, Terraform establishes an implicit dependency, ensuring that the referenced resource is created or updated before the dependent resource. You can also use explicit dependencies using the depends_on meta-argument to define custom dependencies between resources. However, it's generally recommended to rely on implicit dependencies for better readability and maintainability.

Remember: "Resource meta-arguments: count, for_each, provider, depends_on, lifecycle." These control how Terraform manages the resource.

18. Is there any limitation to "count" meta-argument?

Show answer - `count` isn't supported within an inline block
- It's quite limited when it comes to lists.You'll notice that modifying items in lists or even operations like removal sometimes interpreted in a way you didn't expect. For example, removing an item from a list, may shift other items to a new position and since each position represents a resource with count, that may lead to a result where wrong resources are being modified and removed. There are ways to do deal it, but still using count with lists is not always straightforward

Remember: "Splat expressions: aws_instance.web[*].id collects all IDs into a list."

19. Explain the role of "Terraform Lifecycle" and its configuration options.

Show answer Terraform Lifecycle configuration controls various aspects of resource management. Key options include:
* Create Before Destroy: Determines whether to create replacements before destroying existing resources.
* Prevent Destroy: Prevents accidental destruction of critical resources.
* Ignore Changes: Ignores specific changes during Terraform operations.
* Deprecation Warning: Provides warnings for deprecated configurations.
* Custom Hooks: Executes custom scripts or commands at specific lifecycle events.
* Parallelism Control: Adjusts the level of concurrency during resource operations.

Remember: "Terraform has no for loop β€” use for expressions." [for s in var.list : upper(s)] transforms a list.

20. Is it possible to modify the default lifecycle? How? Why?

Show answer Yes, it's possible. There are different lifecycles one can choose from. For example "create_before_destroy" which inverts the order and first creates the new resource, updates all the references from old resource to the new resource and then removes the old resource.

How to use it:

```\nlifecycle {\n create_before_destroy = true\n}\n```

Why to use it in the first place: you might have resources that have dependency where they dependency itself is immutable (= you can't modify it hence you have to create a new one), in such case the default lifecycle won't work because you won't be able to remove the resource that has the dependency as it still references an old resource. AWS ASG + launch configurations is a good example of such use case.

21. True or False? If an expression's result depends on a value that won't be known until after apply, Terraform will display (known after apply).

Show answer TRUE.

This happens when:
- Value computed at apply time
- Depends on external resource
- Generated by provider during creation

Examples:
- Instance IP address (assigned at creation)
- Generated passwords
- ARNs (include IDs assigned by AWS)
- Timestamps

In plan output:
+ resource "aws_instance" "web" {
public_ip = (known after apply)
id = (known after apply)
}

Implications:
- Can't use value in other resources until apply
- May need targeted apply
- Multiple applies sometimes needed

Related:
- depends_on for explicit dependencies
- data sources for existing resources

Remember: "terraform show displays state or plan in human-readable format." -json flag outputs machine-readable JSON.

22. How can you use variables in a dynamic block in Terraform?

Show answer In Terraform, dynamic blocks allow for the creation of repeated nested blocks dynamically. To use variables in a dynamic block, you can reference the variable using the var. prefix. For example:
```\ndynamic "security_group" {\n for_each = var.security_group_rules\n\n content {\n type = security_group.value["type"]\n description = security_group.value["description"]\n // other attributes\n }\n}\n```
Here, var.security_group_rules is a map variable that defines a set of security group rules, and the dynamic block creates multiple security group blocks based on the rules specified in the variable.

Remember: "Terraform has three type families: primitive (string, number, bool), collection (list, map, set), structural (object, tuple)."

23. What is the purpose of the "terraform.tfvars" file?

Show answer The terraform.tfvars file is a standard filename that Terraform automatically loads to populate input variables with values. This file can include variable assignments, providing a convenient way to set default values for variables used in the Terraform configuration. It allows users to store variable values outside the main configuration files, facilitating a separation between sensitive or environment-specific values and the main configuration logic.

Remember: "Terraform state list shows all resources in state." terraform state show RESOURCE shows details of one resource.

24. Sometimes you need to reference some resources in the same or separate .tf file. Why and how it's done?

Show answer Why: because resources are sometimes connected or need to be connected. For example, you create an AWS instance with "aws_instance" resource but, at the same time you would like also to allow some traffic to it (because by default traffic is not allowed). For that you'll create a "aws_security_group" resource and then, in your aws_instance resource, you'll reference it.

How:

Using the syntax ..

In your AWS instance it would like that:

```\nresource "aws_instance" "some-instance" {\n\n ami = "some-ami"\n instance_type = "t2.micro"\n vpc_security_group_ids = [aws_security_group.instance.id]\n\n}\n```

Remember: "terraform state list shows all resources." terraform state show RESOURCE shows attributes.

25. What are output variables? Why do we need them?

Show answer Output variable allow you to display/print certain piece of data as part of Terraform execution.

The most common use case for it is probably to print the IP address of an instance. Imagine you provision an instance and you would like to know what the IP address to connect to it. Instead of looking for it for the console/OS, you can use the output variable and print that piece of information to the screen

Remember: "Terraform 1.5+ supports import blocks for declarative imports." import { to = resource id = "id" } in config.

26. Explain the difference between "provisioners" and "remote-exec" in Terraform.

Show answer Both provisioners and remote-exec are mechanisms in Terraform for executing scripts on resources after they are created.
Provisioners: Include a broader set of options, such as local-exec (running scripts locally), remote-exec (running scripts on remote instances), and others. Provisioners are defined within a resource block and are used for tasks like software installation, configuration, or bootstrapping.
**remote-exec:** Specifically refers to a provisioner that executes scripts on a remote machine. It's often used for executing commands or scripts on provisioned instances, typically in the context of configuration management.

Remember: "Override files: terraform.override.tf is loaded last and merges." Use for local development only.

27. What is the purpose of "Terraform Resource Targeting," and when would you use it?

Show answer Terraform Resource Targeting allows the focus on specific resources during operations like apply or destroy. Use cases include:
* Selective Operations: Targeting specific resources for creation, modification, or destruction.
* Parallel Execution: Running operations concurrently on targeted resources.
* Isolated Changes: Applying changes to a subset of resources for risk mitigation.
* Reduced Execution Time: Limiting operations to a smaller set of resources for faster execution.
* Operational Safety: Minimizing the impact by focusing on a particular resource or resource type.

Remember: "terraform output -json produces machine-readable output." Pipe to jq for scripting.

28. How do you destroy infrastructure using Terraform?

Show answer To destroy infrastructure provisioned with Terraform, you use the terraform destroy command. This command reads the Terraform configuration, identifies the resources created, and prompts for confirmation before destroying them. It's important to note that this operation is irreversible, and it's recommended to review the execution plan using terraform plan before applying the destroy. Additionally, Terraform will prompt for confirmation to ensure intentional destruction of resources.