website: Remove extra copy of "Getting Started", update links

This guide now lives at:

- https://learn.hashicorp.com/terraform#getting-started

...and terraform.io has been redirecting to there for quite a while. This commit
removes the extra copy so that the text of the two versions doesn't drift, and
updates existing links to point to the new location.
This commit is contained in:
Nick Fagerlund 2018-11-13 17:31:35 -08:00 committed by Nick Fagerlund
parent a797152648
commit 6494591ec1
19 changed files with 7 additions and 1670 deletions

View File

@ -23,7 +23,7 @@ When you declare them in [child modules](./modules.html),
the calling module should pass values in the `module` block.
Input variable usage is introduced in the Getting Started guide section
[_Input Variables_](/intro/getting-started/variables.html).
[_Input Variables_](https://learn.hashicorp.com/terraform/getting-started/variables).
-> **Note:** For brevity, input variables are often referred to as just
"variables" or "Terraform variables" when it is clear from context what sort of

View File

@ -13,7 +13,7 @@ topic in Terraform, and is not required knowledge for day-to-day usage.
If you don't plan on writing any plugins, this section of the documentation is
not necessary to read. For general use of Terraform, please see our
[Intro to Terraform](/intro/index.html) and [Getting
Started](/intro/getting-started/install.html) guides.
Started](https://learn.hashicorp.com/terraform/getting-started/install) guides.
This page documents the basics of how the plugin system in Terraform
works, and how to setup a basic development environment for plugin development

View File

@ -13,7 +13,7 @@ topic in Terraform, and is not required knowledge for day-to-day usage.
If you don't plan on writing any plugins, this section of the documentation is
not necessary to read. For general use of Terraform, please see our
[Intro to Terraform](/intro/index.html) and [Getting
Started](/intro/getting-started/install.html) guides.
Started](https://learn.hashicorp.com/terraform/getting-started/install) guides.
A provider in Terraform is responsible for the lifecycle of a resource:
create, read, update, delete. An example of a provider is AWS, which

View File

@ -36,7 +36,7 @@ visiting the [Web UI](https://demo.consul.io/ui/dc1/kv/). We can see
that the `tf_test/id` and `tf_test/public_dns` values have been
set.
You can now [tear down the infrastructure](/intro/getting-started/destroy.html)
You can now [tear down the infrastructure](https://learn.hashicorp.com/terraform/getting-started/destroy).
Because we set the `delete` property of two of the Consul keys, Terraform
will clean up those keys on destroy. We can verify this by using
the Web UI.

View File

@ -25,7 +25,7 @@ Experimenting in this way can help you learn how the Terraform lifecycle
works, as well as how to repeatedly create and destroy infrastructure.
If you're completely new to Terraform, we recommend reading the
[getting started guide](/intro/getting-started/install.html) before diving into
[getting started guide](https://learn.hashicorp.com/terraform/getting-started/install) before diving into
the examples. However, due to the intuitive configuration Terraform
uses it isn't required.

View File

@ -1,291 +0,0 @@
---
layout: "intro"
page_title: "Build Infrastructure"
sidebar_current: "gettingstarted-build"
description: |-
With Terraform installed, let's dive right into it and start creating some infrastructure.
---
# Build Infrastructure
With Terraform installed, let's dive right into it and start creating
some infrastructure.
We'll build infrastructure on
[AWS](https://aws.amazon.com) for this Getting Started guide
since it is popular and generally understood, but Terraform
can [manage many providers](/docs/providers/index.html),
including multiple providers in a single configuration.
Some examples of this are in the
[use cases section](/intro/use-cases.html).
If you don't have an AWS account,
[create one now](https://aws.amazon.com/free/).
For the getting started guide, we'll only be using resources
which qualify under the AWS
[free-tier](https://aws.amazon.com/free/),
meaning it will be free.
~> **Warning!** If you're not using an account that qualifies under the AWS
[free-tier](https://aws.amazon.com/free/), you may be charged to run these
examples. The most you should be charged should only be a few dollars, but
we're not responsible for any charges that may incur.
## Configuration
The set of files used to describe infrastructure in Terraform is simply
known as a Terraform _configuration_. We're going to write our first
configuration now to launch a single AWS EC2 instance.
The format of the configuration files is
[documented here](/docs/configuration/index.html).
Configuration files can
[also be JSON](/docs/configuration/syntax.html), but we recommend only using JSON when the
configuration is generated by a machine.
The entire configuration is shown below. We'll go over each part
after. Save the contents to a file named `example.tf`. Verify that
there are no other `*.tf` files in your directory, since Terraform
loads all of them.
```hcl
provider "aws" {
access_key = "ACCESS_KEY_HERE"
secret_key = "SECRET_KEY_HERE"
region = "us-east-1"
}
resource "aws_instance" "example" {
ami = "ami-2757f631"
instance_type = "t2.micro"
}
```
~> **Note**: The above configuration is designed to work on most EC2 accounts,
with access to a default VPC. For EC2 Classic users, please use `t1.micro` for
`instance_type`, and `ami-408c7f28` for the `ami`. If you use a region other than
`us-east-1` then you will need to choose an AMI in that region
as AMI IDs are region specific.
Replace the `ACCESS_KEY_HERE` and `SECRET_KEY_HERE` with your
AWS access key and secret key, available from
[this page](https://console.aws.amazon.com/iam/home?#security_credential).
We're hardcoding them for now, but will extract these into
variables later in the getting started guide.
~> **Note**: If you simply leave out AWS credentials, Terraform will
automatically search for saved API credentials (for example,
in `~/.aws/credentials`) or IAM instance profile credentials.
This option is much cleaner for situations where tf files are checked into
source control or where there is more than one admin user.
See details [here](https://aws.amazon.com/blogs/apn/terraform-beyond-the-basics-with-aws/).
Leaving IAM credentials out of the Terraform configs allows you to leave those
credentials out of source control, and also use different IAM credentials
for each user without having to modify the configuration files.
This is a complete configuration that Terraform is ready to apply.
The general structure should be intuitive and straightforward.
The `provider` block is used to configure the named provider, in
our case "aws". A provider is responsible for creating and
managing resources. Multiple provider blocks can exist in a
Terraform configuration if the infrastructure needs them.
The `resource` block defines a resource that exists within
the infrastructure. A resource might be a physical component such
as an EC2 instance, or it can be a logical resource such as
a Heroku application.
The resource block has two strings before opening the block:
the resource type and the resource name. In our example, the
resource type is "aws\_instance" and the name is "example."
The prefix of the type maps to the provider. In our case
"aws\_instance" automatically tells Terraform that it is
managed by the "aws" provider.
Within the resource block itself is configuration for that
resource. This is dependent on each resource provider and
is fully documented within our
[providers reference](/docs/providers/index.html). For our EC2 instance, we specify
an AMI for Ubuntu, and request a "t2.micro" instance so we
qualify under the free tier.
## Initialization
The first command to run for a new configuration -- or after checking out
an existing configuration from version control -- is `terraform init`, which
initializes various local settings and data that will be used by subsequent
commands.
Terraform uses a plugin based architecture to support the numerous infrastructure
and service providers available. As of Terraform version 0.10.0, each "Provider" is its
own encapsulated binary distributed separately from Terraform itself. The
`terraform init` command will automatically download and install any Provider
binary for the providers in use within the configuration, which in this case is
just the `aws` provider:
```
$ terraform init
Initializing the backend...
Initializing provider plugins...
- downloading plugin for provider "aws"...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.aws: version = "~> 1.0"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your environment. If you forget, other
commands will detect it and remind you to do so if necessary.
```
The `aws` provider plugin is downloaded and installed in a subdirectory of
the current working directory, along with various other book-keeping files.
The output specifies which version of the plugin was installed, and suggests
specifying that version in configuration to ensure that running
`terraform init` in future will install a compatible version. This step
is not necessary for following the getting started guide, since this
configuration will be discarded at the end.
## Apply Changes
~> **Note:** The commands shown in this guide apply to Terraform 0.11 and
above. Earlier versions require using the `terraform plan` command to
see the execution plan before applying it. Use `terraform version`
to confirm your running version.
In the same directory as the `example.tf` file you created, run
`terraform apply`. You should see output similar to below, though we've
truncated some of the output to save space:
```
$ terraform apply
# ...
+ aws_instance.example
ami: "ami-2757f631"
availability_zone: "<computed>"
ebs_block_device.#: "<computed>"
ephemeral_block_device.#: "<computed>"
instance_state: "<computed>"
instance_type: "t2.micro"
key_name: "<computed>"
placement_group: "<computed>"
private_dns: "<computed>"
private_ip: "<computed>"
public_dns: "<computed>"
public_ip: "<computed>"
root_block_device.#: "<computed>"
security_groups.#: "<computed>"
source_dest_check: "true"
subnet_id: "<computed>"
tenancy: "<computed>"
vpc_security_group_ids.#: "<computed>"
```
This output shows the _execution plan_, describing which actions Terraform
will take in order to change real infrastructure to match the configuration.
The output format is similar to the diff format generated by tools
such as Git. The output has a `+` next to `aws_instance.example`,
meaning that Terraform will create this resource. Beneath that,
it shows the attributes that will be set. When the value displayed
is `<computed>`, it means that the value won't be known
until the resource is created.
If `terraform apply` failed with an error, read the error message
and fix the error that occurred. At this stage, it is likely to be a
syntax error in the configuration.
If the plan was created successfully, Terraform will now pause and wait for
approval before proceeding. If anything in the plan seems incorrect or
dangerous, it is safe to abort here with no changes made to your infrastructure.
In this case the plan looks acceptable, so type `yes` at the confirmation
prompt to proceed.
Executing the plan will take a few minutes since Terraform waits for the EC2
instance to become available:
```
# ...
aws_instance.example: Creating...
ami: "" => "ami-2757f631"
instance_type: "" => "t2.micro"
[...]
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
# ...
```
After this, Terraform is all done! You can go to the EC2 console to see the newly
created EC2 instance. (Make sure you're looking at the same region that was
configured in the provider configuration!)
Terraform also wrote some data into the `terraform.tfstate` file. This state
file is extremely important; it keeps track of the IDs of created resources
so that Terraform knows what it is managing. This file must be saved and
distributed to anyone who might run Terraform. It is generally recommended to
[setup remote state](https://www.terraform.io/docs/state/remote.html)
when working with Terraform, to share the state automatically, but this is
not necessary for simple situations like this Getting Started guide.
You can inspect the current state using `terraform show`:
```
$ terraform show
aws_instance.example:
id = i-32cf65a8
ami = ami-2757f631
availability_zone = us-east-1a
instance_state = running
instance_type = t2.micro
private_ip = 172.31.30.244
public_dns = ec2-52-90-212-55.compute-1.amazonaws.com
public_ip = 52.90.212.55
subnet_id = subnet-1497024d
vpc_security_group_ids.# = 1
vpc_security_group_ids.3348721628 = sg-67652003
```
You can see that by creating our resource, we've also gathered
a lot of information about it. These values can actually be referenced
to configure other resources or outputs, which will be covered later in
the getting started guide.
## Provisioning
The EC2 instance we launched at this point is based on the AMI
given, but has no additional software installed. If you're running
an image-based infrastructure (perhaps creating images with
[Packer](https://www.packer.io)), then this is all you need.
However, many infrastructures still require some sort of initialization
or software provisioning step. Terraform supports provisioners,
which we'll cover a little bit later in the getting started guide,
in order to do this.
## Next
Congratulations! You've built your first infrastructure with Terraform.
You've seen the configuration syntax, an example of a basic execution
plan, and understand the state file.
Next, we're going to move on to [changing and destroying infrastructure](/intro/getting-started/change.html).

View File

@ -1,123 +0,0 @@
---
layout: "intro"
page_title: "Change Infrastructure"
sidebar_current: "gettingstarted-change"
description: |-
In the previous page, you created your first infrastructure with Terraform: a single EC2 instance. In this page, we're going to modify that resource, and see how Terraform handles change.
---
# Change Infrastructure
In the previous page, you created your first infrastructure with
Terraform: a single EC2 instance. In this page, we're going to
modify that resource, and see how Terraform handles change.
Infrastructure is continuously evolving, and Terraform was built
to help manage and enact that change. As you change Terraform
configurations, Terraform builds an execution plan that only
modifies what is necessary to reach your desired state.
By using Terraform to change infrastructure, you can version
control not only your configurations but also your state so you
can see how the infrastructure evolved over time.
## Configuration
Let's modify the `ami` of our instance. Edit the `aws_instance.example`
resource in your configuration and change it to the following:
```hcl
resource "aws_instance" "example" {
ami = "ami-b374d5a5"
instance_type = "t2.micro"
}
```
~> **Note:** EC2 Classic users please use AMI `ami-656be372` and type `t1.micro`
We've changed the AMI from being an Ubuntu 16.04 LTS AMI to being
an Ubuntu 16.10 AMI. Terraform configurations are meant to be
changed like this. You can also completely remove resources
and Terraform will know to destroy the old one.
## Apply Changes
After changing the configuration, run `terraform apply` again to see how
Terraform will apply this change to the existing resources.
```
$ terraform apply
# ...
-/+ aws_instance.example
ami: "ami-2757f631" => "ami-b374d5a5" (forces new resource)
availability_zone: "us-east-1a" => "<computed>"
ebs_block_device.#: "0" => "<computed>"
ephemeral_block_device.#: "0" => "<computed>"
instance_state: "running" => "<computed>"
instance_type: "t2.micro" => "t2.micro"
private_dns: "ip-172-31-17-94.ec2.internal" => "<computed>"
private_ip: "172.31.17.94" => "<computed>"
public_dns: "ec2-54-82-183-4.compute-1.amazonaws.com" => "<computed>"
public_ip: "54.82.183.4" => "<computed>"
subnet_id: "subnet-1497024d" => "<computed>"
vpc_security_group_ids.#: "1" => "<computed>"
```
The prefix `-/+` means that Terraform will destroy and recreate
the resource, rather than updating it in-place. While some attributes
can be updated in-place (which are shown with the `~` prefix), changing the
AMI for an EC2 instance requires recreating it. Terraform handles these details
for you, and the execution plan makes it clear what Terraform will do.
Additionally, the execution plan shows that the AMI change is what
required the resource to be replaced. Using this information,
you can adjust your changes to possibly avoid destroy/create updates
if they are not acceptable in some situations.
Once again, Terraform prompts for approval of the execution plan before
proceeding. Answer `yes` to execute the planned steps:
```
# ...
aws_instance.example: Refreshing state... (ID: i-64c268fe)
aws_instance.example: Destroying...
aws_instance.example: Destruction complete
aws_instance.example: Creating...
ami: "" => "ami-b374d5a5"
availability_zone: "" => "<computed>"
ebs_block_device.#: "" => "<computed>"
ephemeral_block_device.#: "" => "<computed>"
instance_state: "" => "<computed>"
instance_type: "" => "t2.micro"
key_name: "" => "<computed>"
placement_group: "" => "<computed>"
private_dns: "" => "<computed>"
private_ip: "" => "<computed>"
public_dns: "" => "<computed>"
public_ip: "" => "<computed>"
root_block_device.#: "" => "<computed>"
security_groups.#: "" => "<computed>"
source_dest_check: "" => "true"
subnet_id: "" => "<computed>"
tenancy: "" => "<computed>"
vpc_security_group_ids.#: "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Creation complete
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
# ...
```
As indicated by the execution plan, Terraform first destroyed the existing
instance and then created a new one in its place. You can use `terraform show`
again to see the new values associated with this instance.
## Next
You've now seen how easy it is to modify infrastructure with
Terraform. Feel free to play around with this more before continuing.
In the next section we're going to [destroy our infrastructure](/intro/getting-started/destroy.html).

View File

@ -1,201 +0,0 @@
---
layout: "intro"
page_title: "Resource Dependencies"
sidebar_current: "gettingstarted-deps"
description: |-
In this page, we're going to introduce resource dependencies, where we'll not only see a configuration with multiple resources for the first time, but also scenarios where resource parameters use information from other resources.
---
# Resource Dependencies
In this page, we're going to introduce resource dependencies,
where we'll not only see a configuration with multiple resources
for the first time, but also scenarios where resource parameters
use information from other resources.
Up to this point, our example has only contained a single resource.
Real infrastructure has a diverse set of resources and resource
types. Terraform configurations can contain multiple resources,
multiple resource types, and these types can even span multiple
providers.
On this page, we'll show a basic example of multiple resources
and how to reference the attributes of other resources to configure
subsequent resources.
## Assigning an Elastic IP
We'll improve our configuration by assigning an elastic IP to
the EC2 instance we're managing. Modify your `example.tf` and
add the following:
```hcl
resource "aws_eip" "ip" {
instance = "${aws_instance.example.id}"
}
```
This should look familiar from the earlier example of adding
an EC2 instance resource, except this time we're building
an "aws\_eip" resource type. This resource type allocates
and associates an
[elastic IP](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)
to an EC2 instance.
The only parameter for
[aws\_eip](/docs/providers/aws/r/eip.html) is "instance" which
is the EC2 instance to assign the IP to. For this value, we
use an interpolation to use an attribute from the EC2 instance
we managed earlier.
The syntax for this interpolation should be straightforward:
it requests the "id" attribute from the "aws\_instance.example"
resource.
## Apply Changes
Run `terraform apply` to see how Terraform plans to apply this change.
The output will look similar to the following:
```
$ terraform apply
+ aws_eip.ip
allocation_id: "<computed>"
association_id: "<computed>"
domain: "<computed>"
instance: "${aws_instance.example.id}"
network_interface: "<computed>"
private_ip: "<computed>"
public_ip: "<computed>"
+ aws_instance.example
ami: "ami-b374d5a5"
availability_zone: "<computed>"
ebs_block_device.#: "<computed>"
ephemeral_block_device.#: "<computed>"
instance_state: "<computed>"
instance_type: "t2.micro"
key_name: "<computed>"
placement_group: "<computed>"
private_dns: "<computed>"
private_ip: "<computed>"
public_dns: "<computed>"
public_ip: "<computed>"
root_block_device.#: "<computed>"
security_groups.#: "<computed>"
source_dest_check: "true"
subnet_id: "<computed>"
tenancy: "<computed>"
vpc_security_group_ids.#: "<computed>"
```
Terraform will create two resources: the instance and the elastic
IP. In the "instance" value for the "aws\_eip", you can see the
raw interpolation is still present. This is because this variable
won't be known until the "aws\_instance" is created. It will be
replaced at apply-time.
As usual, Terraform prompts for confirmation before making any changes.
Answer `yes` to apply. The continued output will look similar to the
following:
```
# ...
aws_instance.example: Creating...
ami: "" => "ami-b374d5a5"
instance_type: "" => "t2.micro"
[..]
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Creation complete
aws_eip.ip: Creating...
allocation_id: "" => "<computed>"
association_id: "" => "<computed>"
domain: "" => "<computed>"
instance: "" => "i-f3d77d69"
network_interface: "" => "<computed>"
private_ip: "" => "<computed>"
public_ip: "" => "<computed>"
aws_eip.ip: Creation complete
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
```
As shown above, Terraform created the EC2 instance before creating the Elastic
IP address. Due to the interpolation expression that passes the ID of the EC2
instance to the Elastic IP address, Terraform is able to infer a dependency,
and knows it must create the instance first.
## Implicit and Explicit Dependencies
By studying the resource attributes used in interpolation expressions,
Terraform can automatically infer when one resource depends on another.
In the example above, the expression `${aws_instance.example.id}` creates
an _implicit dependency_ on the `aws_instance` named `example`.
Terraform uses this dependency information to determine the correct order
in which to create the different resources. In the example above, Terraform
knows that the `aws_instance` must be created before the `aws_eip`.
Implicit dependencies via interpolation expressions are the primary way
to inform Terraform about these relationships, and should be used whenever
possible.
Sometimes there are dependencies between resources that are _not_ visible to
Terraform. The `depends_on` argument is accepted by any resource and accepts
a list of resources to create _explicit dependencies_ for.
For example, perhaps an application we will run on our EC2 instance expects
to use a specific Amazon S3 bucket, but that dependency is configured
inside the application code and thus not visible to Terraform. In
that case, we can use `depends_on` to explicitly declare the dependency:
```hcl
# New resource for the S3 bucket our application will use.
resource "aws_s3_bucket" "example" {
# NOTE: S3 bucket names must be unique across _all_ AWS accounts, so
# this name must be changed before applying this example to avoid naming
# conflicts.
bucket = "terraform-getting-started-guide"
acl = "private"
}
# Change the aws_instance we declared earlier to now include "depends_on"
resource "aws_instance" "example" {
ami = "ami-2757f631"
instance_type = "t2.micro"
# Tells Terraform that this EC2 instance must be created only after the
# S3 bucket has been created.
depends_on = ["aws_s3_bucket.example"]
}
```
## Non-Dependent Resources
We can continue to build this configuration by adding another EC2 instance:
```hcl
resource "aws_instance" "another" {
ami = "ami-b374d5a5"
instance_type = "t2.micro"
}
```
Because this new instance does not depend on any other resource, it can
be created in parallel with the other resources. Where possible, Terraform
will perform operations concurrently to reduce the total time taken to
apply changes.
Before moving on, remove this new resource from your configuration and
run `terraform apply` again to destroy it. We won't use this second instance
any further in the getting started guide.
## Next
In this page you were introduced to using multiple resources, interpolating
attributes from one resource into another, and declaring dependencies between
resources to define operation ordering.
In the next section, [we'll use provisioners](/intro/getting-started/provision.html)
to do some basic bootstrapping of our launched instance.

View File

@ -1,62 +0,0 @@
---
layout: "intro"
page_title: "Destroy Infrastructure"
sidebar_current: "gettingstarted-destroy"
description: |-
We've now seen how to build and change infrastructure. Before we move on to creating multiple resources and showing resource dependencies, we're going to go over how to completely destroy the Terraform-managed infrastructure.
---
# Destroy Infrastructure
We've now seen how to build and change infrastructure. Before we
move on to creating multiple resources and showing resource
dependencies, we're going to go over how to completely destroy
the Terraform-managed infrastructure.
Destroying your infrastructure is a rare event in production
environments. But if you're using Terraform to spin up multiple
environments such as development, test, QA environments, then
destroying is a useful action.
## Destroy
Resources can be destroyed using the `terraform destroy` command, which is
similar to `terraform apply` but it behaves as if all of the resources have
been removed from the configuration.
```
$ terraform destroy
# ...
- aws_instance.example
```
The `-` prefix indicates that the instance will be destroyed. As with apply,
Terraform shows its execution plan and waits for approval before making any
changes.
Answer `yes` to execute this plan and destroy the infrastructure:
```
# ...
aws_instance.example: Destroying...
Destroy complete! Resources: 1 destroyed.
# ...
```
Just like with `apply`, Terraform determines the order in which
things must be destroyed. In this case there was only one resource, so no
ordering was necessary. In more complicated cases with multiple resources,
Terraform will destroy them in a suitable order to respect dependencies,
as we'll see later in this guide.
## Next
You now know how to create, modify, and destroy infrastructure
from a local machine.
Next, we move on to features that make Terraform configurations
slightly more useful: [variables, resource dependencies, provisioning,
and more](/intro/getting-started/dependencies.html).

View File

@ -1,64 +0,0 @@
---
layout: "intro"
page_title: "Installing Terraform"
sidebar_current: "gettingstarted-install"
description: |-
Terraform must first be installed on your machine. Terraform is distributed as
a binary package for all supported platforms and architecture. This page will
not cover how to compile Terraform from source.
---
# Install Terraform
Terraform must first be installed on your machine. Terraform is distributed as a
[binary package](/downloads.html) for all supported platforms and architectures.
This page will not cover how to compile Terraform from source, but compiling
from source is covered in the [documentation](/docs/index.html) for those who
want to be sure they're compiling source they trust into the final binary.
## Installing Terraform
To install Terraform, find the [appropriate package](/downloads.html) for your
system and download it. Terraform is packaged as a zip archive.
After downloading Terraform, unzip the package. Terraform runs as a single
binary named `terraform`. Any other files in the package can be safely removed
and Terraform will still function.
The final step is to make sure that the `terraform` binary is available on the `PATH`.
See [this page](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux)
for instructions on setting the PATH on Linux and Mac.
[This page](https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows)
contains instructions for setting the PATH on Windows.
## Verifying the Installation
After installing Terraform, verify the installation worked by opening a new
terminal session and checking that `terraform` is available. By executing
`terraform` you should see help output similar to this:
```text
$ terraform
Usage: terraform [--version] [--help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.
Common commands:
apply Builds or changes infrastructure
console Interactive console for Terraform interpolations
# ...
```
If you get an error that `terraform` could not be found, your `PATH` environment
variable was not set up properly. Please go back and ensure that your `PATH`
variable contains the directory where Terraform was installed.
## Next Steps
Time to [build infrastructure](/intro/getting-started/build.html) using a
minimal Terraform configuration file. You will be able to examine Terraform's
execution plan before you deploy it to AWS.

View File

@ -1,269 +0,0 @@
---
layout: "intro"
page_title: "Modules"
sidebar_current: "gettingstarted-modules"
description: |-
Up to this point, we've been configuring Terraform by editing Terraform configurations directly. As our infrastructure grows, this practice has a few key problems: a lack of organization, a lack of reusability, and difficulties in management for teams.
---
# Modules
Up to this point, we've been configuring Terraform by editing Terraform
configurations directly. As our infrastructure grows, this practice has a few
key problems: a lack of organization, a lack of reusability, and difficulties
in management for teams.
_Modules_ in Terraform are self-contained packages of Terraform configurations
that are managed as a group. Modules are used to create reusable components,
improve organization, and to treat pieces of infrastructure as a black box.
This section of the getting started will cover the basics of using modules.
Writing modules is covered in more detail in the
[modules documentation](/docs/modules/index.html).
~> **Warning!** The examples on this page are _**not** eligible_ for
[the AWS free tier](https://aws.amazon.com/free/). Do not try the examples
on this page unless you're willing to spend a small amount of money.
## Using Modules
If you have any instances running from prior steps in the getting
started guide, use `terraform destroy` to destroy them, and remove all
configuration files.
The [Terraform Registry](https://registry.terraform.io/) includes a directory
of ready-to-use modules for various common purposes, which can serve as
larger building-blocks for your infrastructure.
In this example, we're going to use
[the Consul Terraform module for AWS](https://registry.terraform.io/modules/hashicorp/consul/aws),
which will set up a complete [Consul](https://www.consul.io) cluster.
This and other modules can be found via the search feature on the Terraform
Registry site.
Create a configuration file with the following contents:
```hcl
provider "aws" {
access_key = "AWS ACCESS KEY"
secret_key = "AWS SECRET KEY"
region = "us-east-1"
}
module "consul" {
source = "hashicorp/consul/aws"
num_servers = "3"
}
```
The `module` block begins with the example given on the Terraform Registry
page for this module, telling Terraform to create and manage this module.
This is similar to a `resource` block: it has a name used within this
configuration -- in this case, `"consul"` -- and a set of input values
that are listed in
[the module's "Inputs" documentation](https://registry.terraform.io/modules/hashicorp/consul/aws?tab=inputs).
(Note that the `provider` block can be omitted in favor of environment
variables. See the [AWS Provider docs](/docs/providers/aws/index.html)
for details. This module requires that your AWS account has a default VPC.)
The `source` attribute is the only mandatory argument for modules. It tells
Terraform where the module can be retrieved. Terraform automatically
downloads and manages modules for you.
In this case, the module is retrieved from the official Terraform Registry.
Terraform can also retrieve modules from a variety of sources, including
private module registries or directly from Git, Mercurial, HTTP, and local
files.
The other attributes shown are inputs to our module. This module supports many
additional inputs, but all are optional and have reasonable values for
experimentation.
After adding a new module to configuration, it is necessary to run (or re-run)
`terraform init` to obtain and install the new module's source code:
```
$ terraform init
# ...
```
By default, this command does not check for new module versions that may be
available, so it is safe to run multiple times. The `-upgrade` option will
additionally check for any newer versions of existing modules and providers
that may be available.
## Apply Changes
With the Consul module (and its dependencies) installed, we can now apply
these changes to create the resources described within.
If you run `terraform apply`, you will see a large list of all of the
resources encapsulated in the module. The output is similar to what we
saw when using resources directly, but the resource names now have
module paths prefixed to their names, like in the following example:
```
+ module.consul.module.consul_clients.aws_autoscaling_group.autoscaling_group
id: <computed>
arn: <computed>
default_cooldown: <computed>
desired_capacity: "6"
force_delete: "false"
health_check_grace_period: "300"
health_check_type: "EC2"
launch_configuration: "${aws_launch_configuration.launch_configuration.name}"
max_size: "6"
metrics_granularity: "1Minute"
min_size: "6"
name: <computed>
protect_from_scale_in: "false"
tag.#: "2"
tag.2151078592.key: "consul-clients"
tag.2151078592.propagate_at_launch: "true"
tag.2151078592.value: "consul-example"
tag.462896764.key: "Name"
tag.462896764.propagate_at_launch: "true"
tag.462896764.value: "consul-example-client"
termination_policies.#: "1"
termination_policies.0: "Default"
vpc_zone_identifier.#: "6"
vpc_zone_identifier.1880739334: "subnet-5ce4282a"
vpc_zone_identifier.3458061785: "subnet-16600f73"
vpc_zone_identifier.4176925006: "subnet-485abd10"
vpc_zone_identifier.4226228233: "subnet-40a9b86b"
vpc_zone_identifier.595613151: "subnet-5131b95d"
vpc_zone_identifier.765942872: "subnet-595ae164"
wait_for_capacity_timeout: "10m"
```
The `module.consul.module.consul_clients` prefix shown above indicates
not only that the resource is from the `module "consul"` block we wrote,
but in fact that this module has its own `module "consul_clients"` block
within it. Modules can be nested to decompose complex systems into
manageable components.
The full set of resources created by this module includes an autoscaling group,
security groups, IAM roles and other individual resources that all support
the Consul cluster that will be created.
Note that as we warned above, the resources created by this module are
not eligible for the AWS free tier and so proceeding further will have some
cost associated. To proceed with the creation of the Consul cluster, type
`yes` at the confirmation prompt.
```
# ...
module.consul.module.consul_clients.aws_security_group.lc_security_group: Creating...
description: "" => "Security group for the consul-example-client launch configuration"
egress.#: "" => "<computed>"
ingress.#: "" => "<computed>"
name: "" => "<computed>"
name_prefix: "" => "consul-example-client"
owner_id: "" => "<computed>"
revoke_rules_on_delete: "" => "false"
vpc_id: "" => "vpc-22099946"
# ...
Apply complete! Resources: 34 added, 0 changed, 0 destroyed.
```
After several minutes and many log messages about all of the resources
being created, you'll have a three-server Consul cluster up and running.
Without needing any knowledge of how Consul works, how to install Consul,
or how to form a Consul cluster, you've created a working cluster in just
a few minutes.
## Module Outputs
Just as the module instance had input arguments such as `num_servers` above,
a module can also produce _output_ values, similar to resource attributes.
[The module's outputs reference](https://registry.terraform.io/modules/hashicorp/consul/aws?tab=outputs)
describes all of the different values it produces. Overall, it exposes the
id of each of the resources it creates, as well as echoing back some of the
input values.
One of the supported outputs is called `asg_name_servers`, and its value
is the name of the auto-scaling group that was created to manage the Consul
servers.
To reference this, we'll just put it into our _own_ output value. This
value could actually be used anywhere: in another resource, to configure
another provider, etc.
Add the following to the end of the existing configuration file created
above:
```hcl
output "consul_server_asg_name" {
value = "${module.consul.asg_name_servers}"
}
```
The syntax for referencing module outputs is `${module.NAME.OUTPUT}`, where
`NAME` is the module name given in the header of the `module` configuration
block and `OUTPUT` is the name of the output to reference.
If you run `terraform apply` again, Terraform will make no changes to
infrastructure, but you'll now see the "consul\_server\_asg\_name" output with
the name of the created auto-scaling group:
```
# ...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
consul_server_asg_name = tf-asg-2017103123350991200000000a
```
If you look in the Auto-scaling Groups section of the EC2 console you should
find an autoscaling group of this name, and from there find the three
Consul servers it is running. (If you can't find it, make sure you're looking
in the right region!)
## Destroy
Just as with top-level resources, we can destroy the resources created by
the Consul module to avoid ongoing costs:
```
$ terraform destroy
# ...
Terraform will perform the following actions:
- module.consul.module.consul_clients.aws_autoscaling_group.autoscaling_group
- module.consul.module.consul_clients.aws_iam_instance_profile.instance_profile
- module.consul.module.consul_clients.aws_iam_role.instance_role
# ...
```
As usual, Terraform describes all of the actions it will take. In this case,
it plans to destroy all of the resources that were created by the module.
Type `yes` to confirm and, after a few minutes and even more log output,
all of the resources should be destroyed:
```
Destroy complete! Resources: 34 destroyed.
```
With all of the resources destroyed, you can delete the configuration file
we created above. We will not make any further use of it, and so this avoids
the risk of accidentally re-creating the Consul cluster.
## Next
For more information on modules, the types of sources supported, how
to write modules, and more, read the in-depth
[module documentation](/docs/modules/index.html).
Next, we learn about [Terraform's remote collaboration features](/intro/getting-started/remote.html).

View File

@ -1,30 +0,0 @@
---
layout: "intro"
page_title: "Next Steps"
sidebar_current: "gettingstarted-nextsteps"
description: |-
That concludes the getting started guide for Terraform. Hopefully you're now able to not only see what Terraform is useful for, but you're also able to put this knowledge to use to improve building your own infrastructure.
---
# Next Steps
That concludes the getting started guide for Terraform. Hopefully
you're now able to not only see what Terraform is useful for, but
you're also able to put this knowledge to use to improve building
your own infrastructure.
We've covered the basics for all of these features in this guide.
As a next step, the following resources are available:
* [Documentation](/docs/index.html) - The documentation is an in-depth
reference guide to all the features of Terraform, including
technical details about the internals of how Terraform operates.
* [Examples](/intro/examples/index.html) - The examples have more full
featured configuration files, showing some of the possibilities
with Terraform.
* [Import](/docs/import/index.html) - The import section of the documentation
covers importing existing infrastructure into Terraform.

View File

@ -1,84 +0,0 @@
---
layout: "intro"
page_title: "Output Variables"
sidebar_current: "gettingstarted-outputs"
description: |-
In the previous section, we introduced input variables as a way to parameterize Terraform configurations. In this page, we introduce output variables as a way to organize data to be easily queried and shown back to the Terraform user.
---
# Output Variables
In the previous section, we introduced input variables as a way
to parameterize Terraform configurations. In this page, we
introduce output variables as a way to organize data to be
easily queried and shown back to the Terraform user.
When building potentially complex infrastructure, Terraform
stores hundreds or thousands of attribute values for all your
resources. But as a user of Terraform, you may only be interested
in a few values of importance, such as a load balancer IP,
VPN address, etc.
Outputs are a way to tell Terraform what data is important.
This data is outputted when `apply` is called, and can be
queried using the `terraform output` command.
## Defining Outputs
Let's define an output to show us the public IP address of the
elastic IP address that we create. Add this to any of your
`*.tf` files:
```hcl
output "ip" {
value = "${aws_eip.ip.public_ip}"
}
```
This defines an output variable named "ip". The name of the variable
must conform to Terraform variable naming conventions if it is
to be used as an input to other modules. The `value` field
specifies what the value will be, and almost always contains
one or more interpolations, since the output data is typically
dynamic. In this case, we're outputting the
`public_ip` attribute of the elastic IP address.
Multiple `output` blocks can be defined to specify multiple
output variables.
## Viewing Outputs
Run `terraform apply` to populate the output. This only needs
to be done once after the output is defined. The apply output
should change slightly. At the end you should see this:
```
$ terraform apply
...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
ip = 50.17.232.209
```
`apply` highlights the outputs. You can also query the outputs
after apply-time using `terraform output`:
```
$ terraform output ip
50.17.232.209
```
This command is useful for scripts to extract outputs.
## Next
You now know how to parameterize configurations with input
variables, extract important data using output variables,
and bootstrap resources using provisioners.
Next, we're going to take a look at
[how to use modules](/intro/getting-started/modules.html), a useful
abstraction to organize and reuse Terraform configurations.

View File

@ -1,128 +0,0 @@
---
layout: "intro"
page_title: "Provision"
sidebar_current: "gettingstarted-provision"
description: |-
Introduces provisioners that can initialize instances when they're created.
---
# Provision
You're now able to create and modify infrastructure. Now let's see
how to use provisioners to initialize instances when they're created.
If you're using an image-based infrastructure (perhaps with images
created with [Packer](https://www.packer.io)), then what you've
learned so far is good enough. But if you need to do some initial
setup on your instances, then provisioners let you upload files,
run shell scripts, or install and trigger other software like
configuration management tools, etc.
## Defining a Provisioner
To define a provisioner, modify the resource block defining the
"example" EC2 instance to look like the following:
```hcl
resource "aws_instance" "example" {
ami = "ami-b374d5a5"
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo ${aws_instance.example.public_ip} > ip_address.txt"
}
}
```
This adds a `provisioner` block within the `resource` block. Multiple
`provisioner` blocks can be added to define multiple provisioning steps.
Terraform supports
[multiple provisioners](/docs/provisioners/index.html),
but for this example we are using the `local-exec` provisioner.
The `local-exec` provisioner executes a command locally on the machine
running Terraform. We're using this provisioner versus the others so
we don't have to worry about specifying any
[connection info](/docs/provisioners/connection.html) right now.
## Running Provisioners
Provisioners are only run when a resource is _created_. They
are not a replacement for configuration management and changing
the software of an already-running server, and are instead just
meant as a way to bootstrap a server. For configuration management,
you should use Terraform provisioning to invoke a real configuration
management solution.
Make sure that your infrastructure is
[destroyed](/intro/getting-started/destroy.html) if it isn't already,
then run `apply`:
```
$ terraform apply
# ...
aws_instance.example: Creating...
ami: "" => "ami-b374d5a5"
instance_type: "" => "t2.micro"
aws_eip.ip: Creating...
instance: "" => "i-213f350a"
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
```
Terraform will output anything from provisioners to the console,
but in this case there is no output. However, we can verify
everything worked by looking at the `ip_address.txt` file:
```
$ cat ip_address.txt
54.192.26.128
```
It contains the IP, just as we asked!
## Failed Provisioners and Tainted Resources
If a resource successfully creates but fails during provisioning,
Terraform will error and mark the resource as "tainted". A
resource that is tainted has been physically created, but can't
be considered safe to use since provisioning failed.
When you generate your next execution plan, Terraform will not attempt to restart
provisioning on the same resource because it isn't guaranteed to be safe. Instead,
Terraform will remove any tainted resources and create new resources, attempting to
provision them again after creation.
Terraform also does not automatically roll back and destroy the resource
during the apply when the failure happens, because that would go
against the execution plan: the execution plan would've said a
resource will be created, but does not say it will ever be deleted.
If you create an execution plan with a tainted resource, however, the
plan will clearly state that the resource will be destroyed because
it is tainted.
## Destroy Provisioners
Provisioners can also be defined that run only during a destroy
operation. These are useful for performing system cleanup, extracting
data, etc.
For many resources, using built-in cleanup mechanisms is recommended
if possible (such as init scripts), but provisioners can be used if
necessary.
The getting started guide won't show any destroy provisioner examples.
If you need to use destroy provisioners, please
[see the provisioner documentation](/docs/provisioners).
## Next
Provisioning is important for being able to bootstrap instances.
As another reminder, it is not a replacement for configuration
management. It is meant to simply bootstrap machines. If you use
configuration management, you should use the provisioning as a way
to bootstrap the configuration management tool.
In the next section, we start looking at [variables as a way to
parameterize our configurations](/intro/getting-started/variables.html).

View File

@ -1,113 +0,0 @@
---
layout: "intro"
page_title: "Terraform Remote"
sidebar_current: "gettingstarted-remote"
description: |-
We've now seen how to build, change, and destroy infrastructure from a local machine. However, you can use Atlas by HashiCorp to run Terraform remotely to version and audit the history of your infrastructure.
---
# Remote Backends
We've now seen how to build, change, and destroy infrastructure
from a local machine. This is great for testing and development,
but in production environments it is more responsible to share responsibility
for infrastructure. The best way to do this is by running Terraform in a remote
environment with shared access to state.
Terraform supports team-based workflows with a feature known as [remote
backends](/docs/backends). Remote backends allow Terraform to use a shared
storage space for state data, so any member of your team can use Terraform to
manage the same infrastructure.
Depending on the features you wish to use, Terraform has multiple remote
backend options. You could use Consul for state storage, locking, and
environments. This is a free and open source option. You can use S3 which
only supports state storage, for a low cost and minimally featured solution.
[Terraform Cloud](https://www.hashicorp.com/products/terraform/?utm_source=oss&utm_medium=getting-started&utm_campaign=terraform)
is HashiCorp's commercial solution and also acts as a remote backend.
Terraform Cloud allows teams to easily version, audit, and collaborate
on infrastructure changes. Each proposed change generates
a Terraform plan which can be reviewed and collaborated on as a team.
When a proposed change is accepted, the Terraform logs are stored,
resulting in a linear history of infrastructure states to
help with auditing and policy enforcement. Additional benefits to
running Terraform remotely include moving access
credentials off of developer machines and freeing local machines
from long-running Terraform processes.
## How to Store State Remotely
First, we'll use [Consul](https://www.consul.io) as our backend. Consul
is a free and open source solution that provides state storage, locking, and
environments. It is a great way to get started with Terraform backends.
We'll use the [demo Consul server](https://demo.consul.io) for this guide.
This should not be used for real data. Additionally, the demo server doesn't
permit locking. If you want to play with [state locking](/docs/state/locking.html),
you'll have to run your own Consul server or use a backend that supports locking.
First, configure the backend in your configuration:
```hcl
terraform {
backend "consul" {
address = "demo.consul.io"
path = "getting-started-RANDOMSTRING"
lock = false
scheme = "https"
}
}
```
Please replace "RANDOMSTRING" with some random text. The demo server is
public and we want to try to avoid overlapping with someone else running
through the getting started guide.
The `backend` section configures the backend you want to use. After
configuring a backend, run `terraform init` to setup Terraform. It should
ask if you want to migrate your state to Consul. Say "yes" and Terraform
will copy your state.
Now, if you run `terraform apply`, Terraform should state that there are
no changes:
```
$ terraform apply
# ...
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, Terraform
doesn't need to do anything.
```
Terraform is now storing your state remotely in Consul. Remote state
storage makes collaboration easier and keeps state and secret information
off your local disk. Remote state is loaded only in memory when it is used.
If you want to move back to local state, you can remove the backend configuration
block from your configuration and run `terraform init` again. Terraform will
once again ask if you want to migrate your state back to local.
## Terraform Cloud
[Terraform Cloud](https://www.hashicorp.com/products/terraform/?utm_source=oss&utm_medium=getting-started&utm_campaign=terraform) is a commercial solution which combines a predictable and reliable shared run environment with tools to help you work together on Terraform configurations and modules.
Although Terraform Cloud can act as a standard remote backend to support Terraform runs on local machines, it works even better as a remote run environment. It supports two main workflows for performing Terraform runs:
- A VCS-driven workflow, in which it automatically queues plans whenever changes are committed to your configuration's VCS repo.
- An API-driven workflow, in which a CI pipeline or other automated tool can upload configurations directly.
For a hands-on introduction to Terraform Cloud, [follow the Terraform Cloud getting started guide](/docs/cloud/getting-started/index.html).
## Next
You now know how to create, modify, destroy, version, and
collaborate on infrastructure. With these building blocks,
you can effectively experiment with any part of Terraform.
We've now concluded the getting started guide, however
there are a number of [next steps](/intro/getting-started/next-steps.html)
to get started with Terraform.

View File

@ -1,259 +0,0 @@
---
layout: "intro"
page_title: "Input Variables"
sidebar_current: "gettingstarted-variables"
description: |-
You now have enough Terraform knowledge to create useful configurations, but we're still hardcoding access keys, AMIs, etc. To become truly shareable and committable to version control, we need to parameterize the configurations. This page introduces input variables as a way to do this.
---
# Input Variables
You now have enough Terraform knowledge to create useful
configurations, but we're still hard-coding access keys,
AMIs, etc. To become truly shareable and version
controlled, we need to parameterize the configurations. This page
introduces input variables as a way to do this.
## Defining Variables
Let's first extract our access key, secret key, and region
into a few variables. Create another file `variables.tf` with
the following contents.
-> **Note**: that the file can be named anything, since Terraform loads all
files ending in `.tf` in a directory.
```hcl
variable "access_key" {}
variable "secret_key" {}
variable "region" {
default = "us-east-1"
}
```
This defines three variables within your Terraform configuration. The first
two have empty blocks `{}`. The third sets a default. If a default value is
set, the variable is optional. Otherwise, the variable is required. If you run
`terraform plan` now, Terraform will prompt you for the values for unset string
variables.
## Using Variables in Configuration
Next, replace the AWS provider configuration with the following:
```hcl
provider "aws" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}
```
This uses more interpolations, this time prefixed with `var.`. This
tells Terraform that you're accessing variables. This configures
the AWS provider with the given variables.
## Assigning Variables
There are multiple ways to assign variables. Below is also the order
in which variable values are chosen. The following is the descending order
of precedence in which variables are considered.
#### Command-line flags
You can set variables directly on the command-line with the
`-var` flag. Any command in Terraform that inspects the configuration
accepts this flag, such as `apply`, `plan`, and `refresh`:
```
$ terraform apply \
-var 'access_key=foo' \
-var 'secret_key=bar'
# ...
```
Once again, setting variables this way will not save them, and they'll
have to be input repeatedly as commands are executed.
#### From a file
To persist variable values, create a file and assign variables within
this file. Create a file named `terraform.tfvars` with the following
contents:
```hcl
access_key = "foo"
secret_key = "bar"
```
For all files which match `terraform.tfvars` or `*.auto.tfvars` present in the
current directory, Terraform automatically loads them to populate variables. If
the file is named something else, you can use the `-var-file` flag directly to
specify a file. These files are the same syntax as Terraform
configuration files. And like Terraform configuration files, these files
can also be JSON.
We don't recommend saving usernames and password to version control, but you
can create a local secret variables file and use `-var-file` to load it.
You can use multiple `-var-file` arguments in a single command, with some
checked in to version control and others not checked in. For example:
```
$ terraform apply \
-var-file="secret.tfvars" \
-var-file="production.tfvars"
```
#### From environment variables
Terraform will read environment variables in the form of `TF_VAR_name`
to find the value for a variable. For example, the `TF_VAR_access_key`
variable can be set to set the `access_key` variable.
-> **Note**: Environment variables can only populate string-type variables.
List and map type variables must be populated via one of the other mechanisms.
#### UI Input
If you execute `terraform apply` with certain variables unspecified,
Terraform will ask you to input their values interactively. These
values are not saved, but this provides a convenient workflow when getting
started with Terraform. UI Input is not recommended for everyday use of
Terraform.
-> **Note**: In Terraform versions 0.11 and earlier, UI Input is only supported
for string variables. List and map variables must be populated via one of the
other mechanisms. Terraform 0.12 introduces the ability to populate complex
variable types from the UI prompt.
#### Variable Defaults
If no value is assigned to a variable via any of these methods and the
variable has a `default` key in its declaration, that value will be used
for the variable.
<a id="lists"></a>
## Lists
Lists are defined either explicitly or implicitly
```hcl
# implicitly by using brackets [...]
variable "cidrs" { default = [] }
# explicitly
variable "cidrs" { type = "list" }
```
You can specify lists in a `terraform.tfvars` file:
```hcl
cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]
```
## Maps
We've replaced our sensitive strings with variables, but we still
are hard-coding AMIs. Unfortunately, AMIs are specific to the region
that is in use. One option is to just ask the user to input the proper
AMI for the region, but Terraform can do better than that with
_maps_.
Maps are a way to create variables that are lookup tables. An example
will show this best. Let's extract our AMIs into a map and add
support for the `us-west-2` region as well:
```hcl
variable "amis" {
type = "map"
default = {
"us-east-1" = "ami-b374d5a5"
"us-west-2" = "ami-4b32be2b"
}
}
```
A variable can have a `map` type assigned explicitly, or it can be implicitly
declared as a map by specifying a default value that is a map. The above
demonstrates both.
Then, replace the `aws_instance` with the following:
```hcl
resource "aws_instance" "example" {
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.micro"
}
```
This introduces a new type of interpolation: a function call. The
`lookup` function does a dynamic lookup in a map for a key. The
key is `var.region`, which specifies that the value of the region
variables is the key.
While we don't use it in our example, it is worth noting that you
can also do a static lookup of a map directly with
`${var.amis["us-east-1"]}`.
## Assigning Maps
We set defaults above, but maps can also be set using the `-var` and
`-var-file` values. For example:
```
$ terraform apply -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
# ...
```
-> **Note**: Even if every key will be assigned as input, the variable must be
established as a map by setting its default to `{}`.
Here is an example of setting a map's keys from a file. Starting with these
variable definitions:
```hcl
variable "region" {}
variable "amis" {
type = "map"
}
```
You can specify keys in a `terraform.tfvars` file:
```hcl
amis = {
"us-east-1" = "ami-abc123"
"us-west-2" = "ami-def456"
}
```
And access them via `lookup()`:
```hcl
output "ami" {
value = "${lookup(var.amis, var.region)}"
}
```
Like so:
```
$ terraform apply -var region=us-west-2
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
ami = ami-def456
```
## Next
Terraform provides variables for parameterizing your configurations.
Maps let you build lookup tables in cases where that makes sense.
Setting and using variables is uniform throughout your configurations.
In the next section, we'll take a look at
[output variables](/intro/getting-started/outputs.html) as a mechanism
to expose certain values more prominently to the Terraform operator.

View File

@ -75,5 +75,5 @@ See the page on [Terraform use cases](/intro/use-cases.html) to see the
multiple ways Terraform can be used. Then see
[how Terraform compares to other software](/intro/vs/index.html)
to see how it fits into your existing infrastructure. Finally, continue onwards with
the [getting started guide](/intro/getting-started/install.html) to use
the [getting started guide](https://learn.hashicorp.com/terraform/getting-started/install) to use
Terraform to manage real infrastructure and to see how it works.

View File

@ -4,7 +4,7 @@
<ul class="nav docs-sidenav">
<li<%= sidebar_current("guides-getting-started") %>>
<a href="/intro/getting-started/install.html">Getting Started</a>
<a href="https://learn.hashicorp.com/terraform#getting-started">Getting Started</a>
</li>
<li<%= sidebar_current("guides-core-workflow") %>>

View File

@ -34,45 +34,6 @@
</ul>
</li>
<li<%= sidebar_current("gettingstarted") %>>
<a href="/intro/getting-started/install.html">Getting Started</a>
<ul class="nav">
<li<%= sidebar_current("gettingstarted-install") %>>
<a href="/intro/getting-started/install.html">Install Terraform</a>
</li>
<li<%= sidebar_current("gettingstarted-build") %>>
<a href="/intro/getting-started/build.html">Build Infrastructure</a>
</li>
<li<%= sidebar_current("gettingstarted-change") %>>
<a href="/intro/getting-started/change.html">Change Infrastructure</a>
</li>
<li<%= sidebar_current("gettingstarted-destroy") %>>
<a href="/intro/getting-started/destroy.html">Destroy Infrastructure</a>
</li>
<li<%= sidebar_current("gettingstarted-deps") %>>
<a href="/intro/getting-started/dependencies.html">Resource Dependencies</a>
</li>
<li<%= sidebar_current("gettingstarted-provision") %>>
<a href="/intro/getting-started/provision.html">Provision</a>
</li>
<li<%= sidebar_current("gettingstarted-variables") %>>
<a href="/intro/getting-started/variables.html">Input Variables</a>
</li>
<li<%= sidebar_current("gettingstarted-outputs") %>>
<a href="/intro/getting-started/outputs.html">Output Variables</a>
</li>
<li<%= sidebar_current("gettingstarted-modules") %>>
<a href="/intro/getting-started/modules.html">Modules</a>
</li>
<li<%= sidebar_current("gettingstarted-remote") %>>
<a href="/intro/getting-started/remote.html">Remote Backends</a>
</li>
<li<%= sidebar_current("gettingstarted-nextsteps") %>>
<a href="/intro/getting-started/next-steps.html">Next Steps</a>
</li>
</ul>
</li>
<li<%= sidebar_current("examples") %>>
<a href="/intro/examples/index.html">Example Configurations</a>
<ul class="nav">