Sunteți pe pagina 1din 6

Introduction to HashiCorp Configuration

Language (HCL)

HCL is a configuration language authored by HashiCorp. HCL is used with


HashiCorp’s cloud infrastructure automation tools, like Terraform. The language was
created with the goal of being both human and machine friendly. It is JSON
compatible, which means it is interoperable with other systems outside of the
Terraform product line.
This guide provides an introduction to HCL syntax and some commonly used HCL
terminology.

Note
Terraform’s Linode Provider has been updated and now requires Terraform version 0.12+. To
learn how to safely upgrade to Terraform version 0.12+, see Terraform’s official documentation.
View Terraform v0.12’s changelog for a full list of new features and version incompatibility notes.
The examples in this guide were written to be compatible with Terraform version 0.11 and will be
updated in the near future.

HCL Syntax OverviewPermalink


HashiCorp’s configuration syntax is easy to read and write. It was created to have a
more clearly visible and defined structure when compared with other well known
configuration languages, like YAML.

~/terraform/main.tf
1 # Linode provider block. Installs Linode plugin.
2 provider "linode" {
3 token = "${var.token}"
4 }
5
6 variable "region" {
7 description = "This is the location where the Linode instance is deployed."
8 }
9
10 /* A multi
11 line comment. */
12 resource "linode_instance" "example_linode" {
13 image = "linode/ubuntu18.04"
14 label = "example-linode"
15 region = "${var.region}"
16 type = "g6-standard-1"
17 authorized_keys = [ "my-key" ]
18 root_pass = "example-password"
19 }
20

Note
You should not include sensitive data in your resource declarations. For more information on
secrets management, see Secrets Management with Terraform.
Key Elements of HCLPermalink
 HCL syntax is composed of stanzas or blocks that define a variety of configurations
available to Terraform. Provider plugins expand on the available base Terraform
configurations.
 Stanzas or blocks are comprised of key = value pairs. Terraform accepts values of type
string, number, boolean, map, and list.
 Single line comments start with #, while multi-line comments use an opening /* and a
closing */.
 Interpolation syntax can be used to reference values stored outside of a configuration
block, like in an input variable, or from a Terraform module’s output.
An interpolated variable reference is constructed with the "${var.region}" syntax. This
example references a variable named region, which is prefixed by var.. The
opening ${ and closing } indicate the start of interpolation syntax.
 You can include multi-line strings by using an opening <<EOF, followed by a closing EOF on
its own line.
 Strings are wrapped in double quotes.
 Lists of primitive types (string, number, and boolean) are wrapped in square
brackets: ["Andy", "Leslie", "Nate", "Angel", "Chris"].
 Maps use curly braces {} and colons :, as follows: { "password" : "my_password",
"db_name" : "wordpress" }.
See Terraform’s Configuration Syntax documentation for more details.

ProvidersPermalink
In Terraform, a provider is used to interact with an Infrastructure as a Service (IaaS)
or Platform as a Service (PaaS) API, like the Linode APIv4. The provider determines
which resources are exposed and available to create, read, update, and delete. A
credentials set or token is usually required to interface with your service account. For
example, the Linode Terraform provider requires your Linode API access token. A
list of all official Terraform providers is available from HashiCorp.
Configuring a Linode as your provider requires that you include a block which
specifies Linode as the provider and sets your Linode API token in one of
your .tf files:
~/terraform/terraform.tf
1 provider "linode" {
2 token = "my-token"
3 }

Once your provider is declared, you can begin configuring resources available from
the provider.

Note
Providers are packaged as plugins for Terraform. Whenever declaring a new provider in your
Terraform configuration files, the terraform init command should be run. This command will
complete several initialization steps that are necessary before you can apply your Terraform
configuration, including downloading the plugins for any providers you’ve specified.

ResourcesPermalink
A Terraform resource is any component of your infrastructure that can be managed
by your provider. Resources available with the Linode provider range from a Linode
instance, to a block storage volume, to a DNS record. Terraform’s Linode
Provider documentation contains a full listing of all supported resources.
Resources are declared with a resource block in a .tf configuration file. This
example block deploys a 2GB Linode instance located in the US East data center
from an Ubuntu 18.04 image. Values are also provided for the Linode’s label, public
SSH key, and root password:
~/terraform/main.tf
1 resource "linode_instance" "WordPress" {
2 image = "linode/ubuntu18.04"
3 label = "WPServer"
4 region = "us-east"
5 type = "g6-standard-1"
6 authorized_keys = [ "example-key" ]
7 root_pass = "example-root-pass"
8 }

HCL-specific meta-parameters are available to all resources and are independent of


the provider you use. Meta-parameters allow you to do things like customize the
lifecycle behavior of the resource, define the number of resources to create, or
protect certain resources from being destroyed. See Terraform’s Resource
Configuration documentation for more information on meta-parameters.

ModulesPermalink
A module is an encapsulated set of Terraform configurations used to organize the
creation of resources in reusable configurations.
The Terraform Module Registry is a repository of community modules that can help
you get started creating resources for various providers. You can also create your
own modules to better organize your Terraform configurations and make them
available for reuse. Once you have created your modules, you can distribute them
via a remote version control repository, like GitHub.

Using ModulesPermalink
A module block instructs Terraform to create an instance of a module. This block
instantiates any resources defined within that module.

The only universally required configuration for all module blocks is


the source parameter which indicates the location of the module’s source code. All
other required configurations will vary from module to module. If you are using a
local module you can use a relative path as the source value. The source path for a
Terraform Module Registry module will be available on the module’s registry page.
This example creates an instance of a module named linode-module-example and
provides a relative path as the location of the module’s source code:
~/terraform/main.tf
1 module "linode-module-example" {
2 source = "/modules/linode-module-example"
3 }

Authoring modules involves defining resource requirements and parameterizing


configurations using input variables, variable files, and outputs. To learn how to write
your own Terraform modules, see Create a Terraform Module.
Input VariablesPermalink
You can define input variables to serve as Terraform configuration parameters. By
convention, input variables are normally defined within a file named variables.tf.
Terraform will load all files ending in .tf, so you can also define variables in files with
other names.
 Terraform accepts variables of type string, number, boolean, map, and list. If a variable
type is not explicitly defined, Terraform will default to type = "string".
 It is good practice to provide a meaningful description for all your input variables.
 If a variable does not contain a default value, or if you would like to override a variable’s
default value, you must provide a value as an environment variable or within a variable
values file.

Variable Declaration ExamplePermalink


~/terraform/variables.tf
1 variable "token" {
2 description = "This is your Linode APIv4 Token."
3 }
4
5 variable "region" {
6 description: "This is the location where the Linode instance is deployed."
7 default = "us-east"
8 }

Two input variables named token and region are defined, respectively.
The region variable defines a default value. Both variables will default to type =
"string", since a type is not explicitly declared.

Supplying Variable ValuesPermalink


Variable values can be specified in .tfvars files. These files use the same syntax as
Terraform configuration files:
~/terraform/terraform.tfvars
1 token = "my-token"
2 region = "us-west"

Terraform will automatically load values from filenames which


match terraform.tfvars or *.auto.tfvars. If you store values in a file with another name,
you need to specify that file with the -var-file option when running terraform apply.
The -var-file option can be invoked multiple times:
terraform apply \
-var-file="variable-values-1.tfvars" \
-var-file="variable-values-2.tfvars"

Values can also be specified in environment variables when running terraform apply.
The name of the variable should be prefixed with TF_VAR_:
TF_VAR_token=my-token-value TF_VAR_region=us-west terraform apply

Note
Environment variables can only assign values to variables of type = "string"

Referencing VariablesPermalink
You can call existing input variables within your configuration file using Terraform’s
interpolation syntax. Observe the value of the region parameter:
~/terraform/main.tf
1 resource "linode_instance" "WordPress" {
2 image = "linode/ubuntu18.04"
3 label = "WPServer"
4 region = "${var.region}"
5 type = "g6-standard-1"
6 authorized_keys = [ "example-key" ]
7 root_pass = "example-root-pass"
8 }

Note
If a variable value is not provided in any of the ways discussed above, and the variable is called
in a resource configuration, Terraform will prompt you for the value when you run terraform
apply.

For more information on variables, see Terraform’s Input Variables documentation.

InterpolationPermalink
HCL supports the interpolation of values. Interpolations are wrapped in an
opening ${ and a closing }. Input variable names are prefixed with var.:
~/terraform/terraform.tf
1 provider "linode" {
2 token = "${var.token}"
3 }

Interpolation syntax is powerful and includes the ability to reference attributes of


other resources, call built-in functions, and use conditionals and templates.

This resource’s configuration uses a conditional to provide a value for


the tags parameter:
~/terraform/terraform.tf
1 resource "linode_instance" "web" {
2 tags = ["${var.env == "production" ? var.prod_subnet : var.dev_subnet}"]
3 }

If the env variable has the value production, then the prod_subnet variable is used. If not,
then the variable dev_subent is used.

FunctionsPermalink
Terraform has built-in computational functions that perform a variety of operations,
including reading files, concatenating lists, encrypting or creating a checksum of an
object, and searching and replacing.

~/terraform/terraform.tf
1 resource "linode_sshkey" "main_key" {
2 label = "foo"
3 ssh_key = "${chomp(file("~/.ssh/id_rsa.pub"))}"
4 }
In this example, ssh_key = "${chomp(file("~/.ssh/id_rsa.pub"))}" uses Terraform’s built-
in function file() to provide a local file path to the public SSH key’s location.
The chomp() function removes trailing new lines from the SSH key. Observe that the
nested functions are wrapped in opening ${ and closing } to indicate that the value
should be interpolated.
Note
Running terraform console creates an environment where you can test interpolation functions.
For example:
terraform console

> list("newark", "atlanta", "dallas")


[
"newark",
"atlanta",
"dallas",
]
>

Terraform’s official documentation includes a complete list of supported built-in


functions.

TemplatesPermalink
Templates can be used to store large strings of data. The template provider exposes
the data sources for other Terraform resources or outputs to consume. The data
source can be a file or an inline template.

The data source can use Terraform’s standard interpolation syntax for variables. The
template is then rendered with variable values that you supply in the data block.

This example template resource substitutes in the value


from ${linode_instance.web.ip_address} anywhere ${web_ip} appears inside the template
file ips.json:
1 data "template_file" "web" {
2 template = "${file("${path.module}/ips.json")}"
3
4 vars {
5 web_ip = "${linode_instance.web.ip_address}"
6 }
7 }

You could then define an output variable to view the rendered template when you
later run terraform apply:
1 output "ip" {
2 value = "${data.template_file.web.rendered}"
3 }

Terraform’s official documentation has a list of all available components of


interpolation syntax.

S-ar putea să vă placă și