This repository is still under development, more practical and easily deployable labs are still under development and will soon be included.
-
If you wish to add change suggestions, I would please ask you to submit your ideas as an issue, and I can evaluate it and see if we can include it to the repo.
-
I'm open to adding and improving this repository so it can become a better source to gain the necessary information and practice to learn enough Terraform to get certified, and for newcomers to the tool, enough information and practice to start using it in real projects.
-
Thank you for collaborating and taking your time to check these guides.
- It is the idea of managing infrastructure defined in a file or set of files, hence the name Infrastructure as Code, instead of managing the pieces by hand.
- It makes working with Infrastructure, versionable, automatable and reusable. It also can be shared with the organization and it helps you keep track of the changes in the Infrastructure.
-
Multi-cloud support allows for creating multi-cloud architectures, leveraging the benefits of several clouds or a hybrid cloud.
-
Being provider-agnostic also allows the tool to be used by more providers that create their own plugins to manage their Infrastructure/Tools via Terraform.
-
State allows for the mapping of the current configuration of the Infrastructure with the Definition File Representation.
-
Terraform State besides tracking resources can track metadata such as resource dependencies.
-
It can also be cached locally so the state doesn't lose track of the current state of the resources, increasing performance when running
terraform plan
- The recommended way to handle the definition, installation and versioning of a provider is by using the
required_providers
block. Example. Note, this works for Terraform version 0.13 and above.
terraform {
required_providers {
mycloud = {
source = "mycorp/mycloud"
version = "~> 1.0"
}
}
}
- For versions 0.12.
terraform {
required_providers {
aws = "~> 1.0"
}
}
-
Terraform is built on a plugin-based architecture so developers can create and extend Terraform's functionality.
-
There exist two main parts to Terraform:
Terraform Core
andTerraform Plugins
.
-
When
terraform init
is run, Terraform reads the existing configuration files to determine which plugins are going to be used or have been required in the project. It searches for the plugins, it downloads them, and installs the determined pinned or version from the allowed version range. Finally, it writes a lock file to ensure Terraform will use the same plugin versions in the working directory untilterraform init
is run again. -
There are three types of provisioners/plugins.
-
Built-in provisioners. Which are always available, since they are included in the Terraform binary.
-
Providers distributed by HashiCorp . Which are automatically downloaded if not already installed/present.
-
Third-party providers and provisioners. They must always be manually installed.
-
-
The
local-exec
provisioner invokes a local executable command after a resource is created. Note that the process is run on the local machine where Terraform is being used, not the resources Terraform is managing. -
The
remote-exec
provisioner invokes a command on a remote resource after it is created. This can help running the first commands required for configuration management tools, initial bootstrapping, etc. The commands are executed viassh
orwinrm
connections.
-
The
terraform fmt
command is used to rewrite the Terraform configuration files, applying some language style conventions and other adjustments for a standard and consistent format. -
The formatting may change between versions.
- Eg.
0.12.X vs 0.13.X
or0.13.X vs 0.14.X
- So it may be wise to run
terraform fmt
when upgrading Terraform versions.
- Eg.
-
Usage:
terraform fmt [options] [DIR]
(Default DIR is current DIR)-list=false
- This option allows you to not list files that have formatting differences.-write=false
- When you run the command with this option, it doesn't overwrite the files, but does tell you which don't have the standard format.-diff
- With this option enabled you display a diff of the formatting changes that you are wanting to take place.-check
- This option allows you to "check" if the files have correct formatting, no rewriting is taking place, if they don't it will return a non-zero exit code, this can be used for linting scripts or tools.-recursive
- When using this option, you also enable the formatting to process files in subdirectories. Useful when dealing with multiple folder/file layouts.
For more detailed information run terraform fmt --help
To get more hands on experience come and try the commands and the options in the Lab
-
The
terraform taint
command manually marks a resource that is being managed by Terraform as atainted
resource, atainted
resource is forced to be destroyed and recreated on the nextterraform apply
. -
The command itself does not modify the infrastructure, it marks the state file so Terraform knows what to do to the resource after the next plan/apply.
-
This is useful when you want to cause a certain side effect of recreating that is not visible in the attributes of a resource. Like re-running a bootstrap script, change the instance's IP address, etc. Or simply because you want to make Terraform re-create a resource even if Terraform doesn't think it's necessary due to its default behaviour.
-
Usage:
terraform taint [options] address
-
The
address
argument is the address of the resource to taint. -
All of the command-line flags are all optional.
-allow-missing
- If specified, the command will succeed even if the resource is missing. It will only error in extreme erroneous cases.-backup=path
- Path to the backup file. Defaults to-state-out
with the ".backup" extension. Disabled by setting to "-".-lock=true
- Lock the state file when locking is supported.-lock-timeout=0s
- Duration to retry a state lock.-state=path
- Path to read and write the state file to. Ignored when remote state is used.-state-out=path
- Path to write updated state file. By default, the-state
path will be used. Ignored when remote state is used.-ignore-remote-version
- When using the enhanced remote backend with Terraform Cloud, continue even if remote and local Terraform versions differ. Use with extreme caution.
-
Tainting a single resource can be done like this:
terraform taint aws_instance.foo.instance_name
-
Tainting a specific instance from a list of similar resources can be done like this:
terraform taint aws_instance.instance_naame[1]
-
Tainting a resource within a module can be done like this:
terraform taint module.module_name.aws_instance.instance_name
-
For more detailed information run
terraform taint --help
To get more hands on experience come and try the commands and the options in the Lab
4c. Given a scenario: choose when to use terraform import
to import existing infrastructure into your Terraform state
-
The
terraform import
command will find the resource associated with the address provided and import it into your Terraform state. -
Usage:
terraform import [options] ADDRESS_ID
The address must be a valid resource address that depends on the resource type that is trying to be imported. Check the provider documentation for more information.
-
All of the command-line flags are optional. The list of available flags are:
-backup=path
- Used to indicate the path to backup the existing state file.-config=path
- Path to directory of Terraform configuration files that configure the provider for import.-input=true
- Whether to ask for input for provider configuration.-lock=true
- Lock the state file when locking is supported.-lock-timeout=0s
- Duration to retry a state lock.-no-color
- If specified, output won't contain any color.-parallelism=n
- Limit the number of concurrent operations as Terraform walks the graph. Defaults to 10.-state=path
- Path to the source state file to read from.-state-out=path
- Path to the destination state file to write to.-var 'foo=bar'
- Set a variable in the Terraform configuration.-var-file=foo
- Set variables in the Terraform configuration from a variable file.-ignore-remote-version
- When using the enhanced remote backend with Terraform Cloud, continue even if remote and local Terraform versions differ. Use with extreme caution.
-
No labs are provided since existing resources are required to run the commands and demonstrate their use.
-
For more detailed information run
terraform import --help
-
Terraform configuration has an associated backend that defines how operations are executed and where persistent data such as the Terraform
state
are stored. The persistent data stored in the backend, the state, belongs to aworkspace
. -
Terraform workspaces allow you to store your Terraform state in multiple, separate, named workspaces. Terraform by default saves your state in a workspace called
default
. -
The
default
workspace cannot be deleted. -
Managing workspaces is done via the
terraform workspace
command. -
Usage:
terraform workspace [options] WORKSPACE_NAME
-
Depending on the option, you may not need to specify the workspace name.
-
The available options for the
terraform workspace
command are the following:delete WORKSPACE_NAME
- Delete a specific workspace.list
- Lists available workspaces.new WORKSPACE_NAME
- Create a new workspace.select WORKSPACE_NAME
- Select a specific workspace.show
- Show the name of the current workspace.
-
For more detailed information run
terraform workspace --help
To get more hands on experience, come and try the available options in the Lab
-
Situations when are Multiple Workspaces useful and more information about Workspaces.
-
One use is to create a parallel copy of the infrastructure you are working on, in order to test a specific set of changes before modifying the main production infrastructure.
-
To work on and replicate the infrastructure for several environments, also for isolating the state files between environment resources as a best practice. Although workspaces do not solve all the problems, sometimes you will need to separate environment resources across several Cloud Provider Accounts as well.
-
-
The
terraform state
command is used for advanced state management. -
In some cases you will need to modify or work with the state files, so instead of editing them directly, you will manipulate them via the
terraform state
command. -
As you will later on discover, the
terraform state
command works the same with remote state as it were local state. Reads and writes may take longer, since the state needs to be retrieved before doind any state operations. -
Usage:
terraform state <subcommand> [options] [args]
-
For reading and updating the state, Terraform includes several commands.
-
terraform state list
- This command shows the resource addresses for every resource Terraform knows about in a configuration, optionally filtered by partial resource address. -
terraform state show
- This command displays detailed state data about one resource. -
terraform refresh
- This command updates the state data to match the real-world condition of the managed resources. This is done automatically during plans and applies, but not when interacting with state directly.
-
As we say briefly in the
terraform taint
command, we can use the taint command to force re-creation of a resource during nextterraform apply
if we think it's necessary. -
terraform taint
- This command tells Terraform to destroy and re-create a resource on the nextterraform apply
, regardless of the default strategy of Terraform to edit in-place if this was the case. -
terraform untaint
- This command undoes a previously applied taint, this is mostly used if you tainted the incorrect resource or you no longer require tainting the resource.
-
Terraform's state associates each real-world infrastructure piece with a configured resource at a specific resource address.
-
But Terraform can lose track of a resource if you change its name, move it to a different module, or change it's provider.
-
In the case you want to preserve an existing infrastructure object, you can tell Terraform to associate it with a different configured resource.
-
terraform state mv
- This command changes which address in your configuration is associated with a particular real-world object. Use this to preserve an object when renaming a resource, or when moving a resource into or out of a child module. -
terraform state rm
- This command tells Terraform to stop managing a resource as part of the current working directory and workspace, without actually destroying the corresponding real-world infrastructure object. If you need to recover management in a different workspace or project, you can useterraform import
. -
terraform state replace-provider
- This command transfers existing resources to a new provider without requiring them to be re-created.
-
If something goes terribly wrong with your state files, you may need to take drastic actions to recover your state files.
-
terraform force-unlock
- This command can help you override the protection Terraform uses to prevent two processes from modifying the state file at the same time. You might need this command in the case that a Terraform process like aterraform apply
is unexpectedly terminated and the state lock isn't released for the state backend. Do not run this command unless you are very sure about what occurred and that this can solve your state locking problem. -
terraform state pull
- This command can help you read entire state files from the configured backend. You might need it to obtain a state backup. -
terraform state push
- This command can help you write entire state files to the configured backend. You might need it to restore a state backup if the current state is not working.
-
When you are working on your usual day to day work and you notice some behaviour from Terraform that's unexpected or that doesn't work at all is the most common reason for why you might want to enable verbose logging to get a sense of what is going wrong.
-
To enable verbose logging of the Terraform CLI you will need to set the
TF_LOG
environment variable to one of the following:TRACE
DEBUG
INFO
WARN
ERROR
And setting the environment variable is done like this in a *nix system.
export TF_LOG=TRACE
- Note that when enabling other Log levels, we get the following message from the Terraform CLI
[WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward compatibility.
Use TF_LOG=TRACE to see Terraform's internal logs.
-
Terraform modules help you manage the increasing complexity of managing configuration between many projects and when infrastructure and services grow.
-
Modules help with the following points:
- Organize Configuration
- Encapsulate Configuration
- Re-use Configuration
- Provide consistency and ensure best practices.
- The Terraform Registry is integrated directly into Terraform, so a Terraform configuration can refer to any module published in the registry. The syntax for specifying a registry module is
<NAMESPACE>/<NAME>/<PROVIDER>
. For examplehashicorp/consul/aws
module "consul" {
source = "hashicorp/consul/aws"
version = "0.1.0"
}
-
The
terraform init
command will download and cache any modules referenced by a configuration. -
You can also use modules from a private registry, like the one provided by Terraform Cloud. Private registry modules have source strings in the form
<HOSTNAME>/<NAMESPACE>/<NAME>/<PROVIDER>
module "vpc" {
source = "app.terraform.io/example_corp/vpc/aws"
version = "0.9.3"
}
- Another way of using modules from private registries/repositories is using the following syntax:
module "vpc" {
source = "github.com/my_org/tf_modules/vpc?ref=1.2.6"
}
- Note that we are using a tagged version of the module and setting a version constraint here, this setup is recommended for general use, and upgrades are made easier and with more purpose.
-
Terraform modules have two sets of variables that we can use to compose and configure our Infrastructure.
-
Input Variables
-
Output Variables
-
-
Input variables are the same type of variables we are familiar with already, like the ones used in previous labs/examples. We can configure the variables that we wish to use in the module to give it flexibility for the data it will admit. E.g
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.21.0"
name = var.vpc_name
cidr = var.vpc_cidr
azs = var.vpc_azs
private_subnets = var.vpc_private_subnets
public_subnets = var.vpc_public_subnets
enable_nat_gateway = var.vpc_enable_nat_gateway
tags = var.vpc_tags
}
- Output variables are similar as well, they function in a similar way as the output variables we have used already. In the root module of our project we can use the output variables we configure in the modules we are using. E.g.
# main.tf
resource "aws_elb" "example" {
# ...
instances = module.servers.instance_ids
}
# modules/servers/outputs.tf
output "instance_ids" {
value = aws_instance.this.*.id
}
-
The root module can use it's own variables and can use the values output by the child modules it's using.
-
The child modules only have access to the variables that they are passed and are set as default. The child module does not have access to the full scope of variables available to the root module.
-
When using in a project modules installed from a module registry, the best practice is to explicitly constrain or pin the version numbers to avoid unexpected or unwanted changes if another version is released and it changes something undesired in your underlying infrastructure.
-
Use the
version
argument in themodule
block to specify versions:
module "consul" {
source = "hashicorp/consul/aws"
version = "0.0.5"
servers = 3
}
-
Meta-arguments
-
Along with
source
andversion
. Terraform defines a few more optional meta-arguments that have special meaning across all modules.-
count
- Creates multiple instances of a module from a singlemodule
block. -
for_each
- Creates multiple instances of a module from a singlemodule
block. -
providers
- Passes provider configurations to a child module. If not specified, the child module inherits all of the default (un-aliased) provider configurations from the calling module. -
depends_on
- Creates explicit dependencies between the entire module and the listed targets.
-
-
-
When developing Terraform code in a project you will repeat many core steps before successfully configuring your Infrastructure, some of these steps are.
- Writing your Initial Terraform configuration.
- Initializing a Terraform directory.
- Validating a Terraform configuration.
- Generating and reviewing a Terraform execution plan.
- Executing changes to Infrastructure with Terraform
- Destroying Infrastructure with Terraform
- Writing changes to your Terraform configuration.
-
According to HashiCorp there exists a Core Terraform Workflow, which has three steps:
1.- Write - Author infrastructure as code.
2.- Plan - Preview changes before applying.
3.- Apply - Provision reproducible infrastructure.
-
This step is simple, it initializes a working directory that container Terraform configuration and takes care of installing providers, modules and initialize the corresponding configured backend.
-
terraform init
-
This step is used to validate if a Terraform configuration is valid, but does not access any remote services or check into any remote state, provider APIs, etc.
-
Validate runs checks that verify whether a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state. It is thus primarily useful for general verification of reusable modules, including correctness of attribute names and value types.
-
terraform validate
-
Once you have validated your configuration, you are ready to create an execution plan.
-
terraform plan
-
This command is a convenient way to check whether the execution plan for a set of changes matches your expectations without making any changes to real resources or to the state.
-
When you are ready to apply the changes you authored, you run the next command.
-
terraform apply
-
You can see an execution plan prior to running the command.
-
When you need to remove the Infrastructure you have been managing with Terraform, you run the destroy command.
-
terraform destroy
-
This command orders Cloud Providers to destroy/deprovision a resource, so be careful which resources you destroy!
-
When working on terraform operations such as
terraform plan
orterraform apply
on some infrastructure project you were working on, the place where all of the operations are performed and where state snapshots are stored is in the terraform backend. -
State
-
Terraform uses persistent state data to keep track of the resources it's managing for you.
-
When using the
local
backend, the state is stored on your local disk, at the same directory of your terraform project with the following name:terraform.tfstate
-
State is never recommended to be edited by hand.
-
-
Operations
-
Refers to performing API requests against infrastructure services in order to create, read, update, or destroy resources. Not every
terraform
subcommand performs API operations; many of them only operate on state data. -
The
local
backend performs API operations directly from the machine where theterraform
command is run. -
The
remote
backend can perform API operations remotely, using Terraform Cloud or Terraform Enterprise. The remote system requires cloud credentials or network access to the resources being managed.
-
-
The default
local
backend is that one which does not have any extra configuration or remote backend configured, in which the state and operations are performed locally on the machine. -
Collaboration with this type of backend is very hard and not recommended.
-
If supported by the type of backend being used, Terraform will lock your state for all operations that could write state. This prevents others from acquiring the lock and potentially corrupt your state in the scenario where two developers try to issue some
terraform apply
on the same infrastructure with different sets of changes. -
State locking happens automatically on all operations that could write state. You won't see any message that it is happening. If state locking fails, Terraform will not continue.
-
Not all backends support locking.
-
If required, you can manually unlock the state for the defined configuration.
-
This will not modify your infrastructure. This command removes the lock on the state for the current configuration.
-
Usage:
terraform force-unlock [options] LOCK_ID [DIR]
- Options:
-force
- Don't ask for input for unlock confirmation.
- Options:
-
Which manually unlocks the state for the defined configuration.
-
Backend authentication methods vary slightly between different backends, but most rely on having access to the CLI or gaining authentication via certificates (Kubernetes) or passwords.
-
There also exists a command to obtain and save API tokens for Terraform services.
-
The
terraform login
command can be used to automatically obtain and save an API token for Terraform Cloud, Terraform Enterprise, or any other host that offers Terraform services.
-
Terraform's backends are divided into two main types, according to how they handle state and operations:
-
Enhanced backends can both store state and perform operations. There are only two enhanced backends:
local
andremote
. -
Standard backends only store state, and rely on the
local
backend for performing operations.
-
-
The different available Standard Backends for Terraform are the following:
- artifactory
- azurerm
- consul
- cos
- etcd
- etcdv3
- gcs
- http
- kubernetes
- manta
- oss
- pg
- swift
-
The
terraform refresh
command is used to reconcile the state Terraform knows about with the real-world infrastructure. -
This can be used to detect any drift from the last-known state, and to update the state file.
-
It can also help to reconcile or sync the state Terraform needs when initializing for the first time a repository that uses
remote
state and we don't have the current state of the infrastructure. -
This does not modify infrastructure in the end, it rather modifies the state file. If the state is changed, this may cause changes to occur during the next plan or apply.
-
Usage:
terraform refresh
-
The
terraform refresh
command accepts the following options:-compact-warnings
- If Terraform produces any warnings that are not accompanied by errors, show them in a more compact form that includes only the summary messages.-input=true
- Ask for input for variables if not directly set.-lock=true
- Lock the state file when locking is supported.-lock-timeout=0s
- Duration to try a state lock.-no-color
- If specified, the console output won't contain any color.-parallelism=n
- Limit the number of concurrent operations as Terraform walks the graph. Defaults to 10.-target=resource
- A Resource Address to target. This limits the operation to the resource and it's dependencies. This flag can be used multiple times.-var 'foo=bar'
- Set a variable in the Terraform configuration. This flag can be used multiple times.-var-file=env_vars/dev.tfvars
- Set variables in the Terraform configuration from a variable file. If aterraform.tfvars
or any.auto.tfvars
files are present in the current directory, they will be automatically loaded.terraform.tfvars
is loaded first and the.auto.tfvars
files after in alphabetical order. Any files specified by-var-file
override any values set automatically from files in the working directory. This flag can be used multiple times.
-
-
Each Terraform project can specify a backend, which defines exactly where and how operations are performed, where state snapshots are stored, etc.
-
The backend block, backends are configured with a nested
backend
block within the top-levelterraform
block:
terraform {
backend "remote" {
organization = "example_corp"
workspaces {
name = "my-app-prod"
}
}
}
-
Some things to take in account when using the backend configuration block are:
-
A configuration can only provide one backend block.
-
A backend block cannot refer to names values (like input variables, locals, or data source attributes).
-
-
You can choose the Backend Type in the label of the backend block that reads
"remote"
, this one is choosing the Remote Backend Type. -
Some backends allow providing access credentials directly as part of the configuration for use in unusual situations, for pragmatic reasons. However, as part of best practices, it is not recommended to include access credentials as part of the backend configuration.
-
Instead, leave those arguments unset and provide credentials via the credentials files or environment variables that are conventional for the target system, as described in the documentation for each backend.
-
Partial Configurations
-
You do not need to specify every required argument in the backend configuration.
-
Omitting certain arguments may be desirable if some arguments are provided automatically by an automation script running Terraform.
-
When some or all of the arguments are omitted, we call this a partial configuration.
-
With a partial configuration, the remaining configuration arguments must be provided as part of the initialization process. There are several ways to supply the remaining arguments:
-
File: A configuration file may be specified via the
init
command line. To specify a file, use the-backend-config=PATH
option when runningterraform init
. If the file contains secrets it may be kept in a secure data store, such as Vault, in which case it must be downloaded to the local disk before running Terraform. -
Command-line key/values pairs: Key/value pairs can be specified via the
init
command line. Note that many shells retain command-line flags in a history file, so this isn't recommended for secrets. To specify a single key/value pair, use the-backend-config="KEY=VALUE"
option when runningterraform init
. -
Interactively: Terraform will interactively ask you for the required values, unless interactive input is disabled. Terraform will not prompt for optional values.
-
When using partial configuration, Terraform requires at a minimum that an empty backend configuration is specified in one of the root Terraform configuration files, to specify the backend type. For example:
-
terraform { backend "s3" { key = "state/partial-configuration.tfstate" region = "us-east-1" encrypt = true } }
-
And the rest of the configuration arguments are provided in this example via the command line as such:
-
terraform init -input=false -backend-config="bucket=state-bucket" -backend-config="dynamodb_table=locks-table"
-
Which would be equivalent to:
-
terraform { backend "s3" { key = "state/partial-configuration.tfstate" region = "us-east-1" encrypt = true bucket = state-bucket dynamodb_table = locks-table } }
-
-
-
Terraform state can contain sensitive data, depending on the resources in use and your personal or organization's definition of "sensitive". The state contains resource IDs and all the resource attributes. For resources such as databases, this may contain initial passwords.
-
When using local state, state is stored in plain-text JSON files.
-
When using remote state, state is only ever held in memory when used by Terraform. It may be encrypted at rest, but this depends on the specific state backend.
-
Overall recommendations is to use TLS connections, encryption at rest options for standard backends to protect your remote state. Also limit any access policies so only the required people can access it if required.
- Lab
-
Secrets Injection using Vault, facilitates the creation of short-lived authentication credentials for provisioning infrastructure.
-
It also helps reduce insider threats, if you create dynamic secrets with Vault.
-
IT helps against accidental leaks of secrets that end up exposed in Version Control or other places.
-
Safely delivering dynamic secrets via encrypted means.
-
Complex types are a type that group multiple values into a single value.
-
There are two categories of complex types: collection types (for grouping similar values), and structural types (for grouping potentially dissimilar values).
-
Collection Types
-
Collection types allow for multiple values of one other type to be grouped together as a single value. The type of value within a collection is called its element type. For example a
list(string)
is a list of strings. -
list(...)
- Collection of values of the same assigned type. -
map(...)
- Collection of values where each is identified by a string label. -
set(...)
- Collection of unique values that do not have any secondary identifiers or ordering.
-
-
Structural Types
-
A structural type allows multiple values of several distinct types to be grouped together as a single value. Structural types require a schema as an argument, to specify which types are allowed for which elements.
-
object(...)
- Collection of names attributes that each have their own type.-
For example: an object type of
object({ name=string, age=number })
would match a value like the following:{ name = "John", age = 52 }
-
-
tuple(...)
- A sequence of elements identified by consecutive whole numbers starting with zero, where each element has its own type.-
Finally, a tuple type of
tuple([string, number, bool])
would match a value like the following:["a", 15, true]
-
-
-
-
resource
-
A resource address is a string that references a specific resource in a large set of infrastructure.
-
Example:
aws_instance.web_instance
-
-
data
-
Data sources allow data to be fetched or computed for use elsewhere in Terraform configuration. Use of data sources allows a Terraform configuration to make use of information defined outside of Terraform, or defined by another separate Terraform configuration.
-
Example:
-
data "aws_ami" "ubuntu_ami" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}
-
This data source computes and fetches the information relating to the AWS AMI using the filters and owners as the main parameters.
-
Finally the AMI ID is consumed like this:
ami = data.aws_ami.ubuntu_ami.id
- Lab
- The Terraform language includes a number of built-in functions that you can call from within expressions to transform and combine values. The general syntax for function calls is a function name followed by a comma-separated arguments in parentheses:
> max(5, 12, 9)
12
> lower("HELLO")
hello
- You can also chain together several functions to create more complex configurations.
- Within top-level block constructs like resources, expressions can usually be used only when assigning a value to an argument using the
name = expression
form. This covers many uses, but some resource types include repeatable nested blocks in their arguments, which typically represent separate objects that are related to (or embedded within) the containing object:
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "test-name" # can use expressions here
setting {
# but the "setting" block is always a literal block and the same
}
}
- You can dynamically construct repeatable nested blocks like
setting
using a specialdynamic
block type, which is supported insideresource
,data
,provider
, andprovisioner
blocks:
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "test-name"
application = "${aws_elastic_beanstalk_application.tftest.name}"
solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"
dynamic "setting" {
for_each = var.settings
content {
namespace = setting.value["namespace"]
name = setting.value["name"]
value = setting.value["value"]
}
}
}
-
A
dynamic
block acts much like afor
expression, but produces nested blocks instead of a complex typed value. It iterates over a given complex value, and generates a nested block for each element of that complex value. -
Best practices for
dynamic
blocks.- Overuse of
dynamic
blocks can make configuration hard to read and maintain, so we recommend using them only when you need to hide details in order to build a clean user interface for a reusable module. Always write nested blocks out literally where possible.
- Overuse of
-
Terraform most of the time is able to determine dependencies between resources based on the configuration provided, so that resources can be created and destroyed in the correct order.
-
However, this isn't always the case, sometimes Terraform runs into problems determining dependencies between parts of your infrastructure, and you will need to create an explicit dependency with the
depends_on
argument. -
Implicit dependencies are the primary way that Terraform understands the relationships between your resources. Sometimes there are dependencies between resources that are not visible to Terraform, however. The depends_on argument is accepted by any resource or module block and accepts a list of resources to create explicit dependencies for.
-
To illustrate this, assume you have an application running on your EC2 instance that expects to use a specific Amazon S3 bucket. This dependency is configured inside the application, and thus not visible to Terraform. You can use depends_on to explicitly declare the dependency. You can also specify multiple resources in the depends_on argument, and Terraform will wait until all of them have been created before creating the target resource.
resource "aws_s3_bucket" "example" {
acl = "private"
}
resource "aws_instance" "example_c" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
depends_on = [aws_s3_bucket.example]
}
module "example_sqs_queue" {
source = "terraform-aws-modules/sqs/aws"
version = "2.1.0"
depends_on = [aws_s3_bucket.example, aws_instance.example_c]
}
-
Benefits of Sentinel
-
Sentinel allows for applying the same coding practices that are applied to infrastructure, now for enforcing and managing policies.
-
Codifying policy removes the need for ticketing queues, without sacrificing enforcement.
-
Allows for creating, versioning and enforcing policies onto tools like Terraform.
-
Sentinel also has a full testing framework.
-
-
Benefits of Module Registry
-
The Terraform Module registry gives terraform users easy access to templates for setting up and running their infrastructure with verified and community modules.
-
It allows module consumers to discover, use, and collaborate on modules.
-
The Module Registry makes it easier for partners and community members to share and collaborate on modules and also to update and version modules to continuously make improvements to infrastructure configurations.
-
It also allows expert users to share their knowledge and beginners can get up and running on Terraform faster.
-
-
Terraform Enterprise Workspaces
-
Allows for creating specific permissions for roles. RBAC.
-
Allows for running Sentinel on the infrastructure.
-
Allows for modularizing the infrastructure into workspaces for reusing stacks of infrastructure on multiple applications.
-
-
Working with Terraform involves managing collections of infrastructure resources, and most organizations manage many different collections.
-
Terraform Cloud manages infrastructure collections with workspaces instead of directories. A workspace contains everything Terraform needs to manage a given collection of infrastructure, and separate workspaces function like completely separate working directories.
-
Workspace - Associate it with some set of configurations. In version control.
-
Variables - Configuration Files and Variables
-
OSS workspaces
- Plan
- Apply
-
TFE workpaces
- Run (Plan, Sentinel, Apply) - Can run in parallelism
- State file
- Permissions
-
Terraform Cloud is a free to use, self-service SaaS platform that extends the capabilities of the open source Terraform CLI.
-
It adds automation and collaboration features, and performs Terraform functionality remotely, making it ideal for collaborative and production environments.
-
Allows for Team Management & Governance - Manage & enforce teams & policies (as code).
-
Advanced Security, Compliance, and Governance - SSO, Audit, Private Datacenter Networking
-
Self-Service Infrastructure - Support for ServiceNow / Configuration Designer workflows
-
Concurrent runs.