github.com/hashicorp/packer@v1.14.3/website/content/guides/hcl/variables.mdx (about)

     1  ---
     2  page_title: Input and Local Variables guide
     3  description: |-
     4    This page introduces input variables and local variables as a way to
     5    parameterize a configuration.
     6  ---
     7  
     8  # Input Variables and local variables
     9  
    10  @include 'guides/hcl2-beta-note.mdx'
    11  
    12  This page introduces input variables and local variables as a way to
    13  parameterize a configuration. Once defined, input variables are settable from a
    14  default value, environment, special var files, and command line arguments.
    15  Local variables can be a compound of input variables and local variables.
    16  
    17  ## Defining Variables and locals
    18  
    19  In the legacy JSON Packer templates, any variables we hadn't already defined in
    20  the "variables" stanza of our json template could simply be passed in via the
    21  command line or a `var-file`; if a variable was never defined it would generally
    22  be interpolated to an empty string.
    23  
    24  _In the HCL2 Packer templates, we must always pre-define our variables in the
    25  HCL equivalent of the "variables" stanza._
    26  
    27  Another difference between JSON and HCL Packer templates is that in JSON packer
    28  templates, the "variables" stanza, if used, was always in the same .json file
    29  as the builds and builders. In HCL, it can exist in its own file if you want it
    30  to.
    31  
    32  To demonstrate, let's create a file `variables.pkr.hcl` with the following
    33  contents.
    34  
    35  -> **Note**: that the file can be named anything, since Packer loads all
    36  files ending in `.pkr.hcl` in a directory. If you split your configuration
    37  across multiple files, use
    38  `packer build <command line flags> <source directory>` to initiate a build.
    39  
    40  ```hcl
    41  //  variables.pkr.hcl
    42  
    43  // For those variables that you don't provide a default for, you must
    44  // set them from the command line, a var-file, or the environment.
    45  
    46  variable "weekday" {}
    47  
    48  variable "sudo_password" {
    49    type =  string
    50    default = "mypassword"
    51    // Sensitive vars are hidden from output as of Packer v1.6.5
    52    sensitive = true
    53  }
    54  
    55  variable "flavor" {
    56    type = string
    57    default = "strawberry"
    58  }
    59  
    60  variable "exit_codes" {
    61    type = list(number)
    62    default = [0]
    63  }
    64  
    65  locals {
    66    ice_cream_flavor = "${var.flavor}-ice-cream"
    67    foo             = "bar"
    68  }
    69  ```
    70  
    71  This defines several variables within your Packer configuration, each showing
    72  off a different way to set them. The first variable, "weekday", is an empty
    73  block `{}`, without a type or a default.
    74  
    75  However, it's generally best to provide the type in your variable definition,
    76  as you can see in variable "flavor", which we have given a type of "string",
    77  and variable "exit_codes", which we have given a type of "list(number)",
    78  meaning it is a list/array of numbers.
    79  
    80  When a variable is passed from the cli or environment and the variable's type
    81  is not set, Packer will expect it to be a string. But if it is passed from a
    82  var-file where Packer can interpret HCL properly it can be a slice or any
    83  supported type.
    84  
    85  In addition to setting the type, the "flavor" and "exit_codes" variables also
    86  provide a default. If you set a default value, then you don't need to set the
    87  variable at run time. Packer will use a provided command-line var,
    88  var-file, or environment var if it exists, but if not Packer will fall back to
    89  this default value.
    90  
    91  If you do not set a default value, Packer will fail immediately when you try to
    92  run a `build` if you have not provided the missing variable via the
    93  command-line, a var-file, or the environment. The `validate`, `inspect` and
    94  `console` commands will work, but variables with unknown values will be
    95  `<unknown>`.
    96  
    97  This also defines two locals: `ice_cream_flavor` and `foo`.
    98  
    99  -> **Note**: that it is _not_ possible to reference a variable in the
   100  definition of another variable. But it _is_ possible to use locals and
   101  variables in the definition of a local, as shown in the ice_cream_flavor
   102  definition.
   103  
   104  ## Using Variables and locals in Configuration
   105  
   106  For simplicity's sake, we're going to put a null source in the same file as
   107  we are putting the build configuration. This file demonstrates how to use the
   108  variables we previously defined.
   109  
   110  ```hcl
   111  // null_example.pkr.hcl
   112  
   113  source "null" "example" {
   114      communicator = "none"
   115  }
   116  
   117  build {
   118    sources = [
   119      "source.null.example"
   120    ]
   121    provisioner "shell-local" {
   122      // Note that for options that are documented as template engines,
   123      // we still have to use the Go template engine syntax rather than our
   124      // specialized HCL2 variable syntax. This example shows a combination of
   125      // an HCL2 variable and the Go template engines built into the
   126      // execute_command option
   127      execute_command  = ["/bin/sh", "-c", "echo ${var.sudo_password}| {{.Vars}} {{.Script}}"]
   128      environment_vars = ["HELLO_USER=packeruser", "UUID=${build.PackerRunUUID}"]
   129      inline           = ["echo the Packer run uuid is $UUID"]
   130    }
   131    provisioner "shell-local" {
   132      inline           = ["echo var.flavor is: ${var.flavor}",
   133                          "echo local.ice_cream_flavor is: ${local.ice_cream_flavor}"]
   134      valid_exit_codes = var.exit_codes
   135    }
   136  }
   137  ```
   138  
   139  As you can see in the example, you can access your variables directly by
   140  giving them the `var.` or `local.` prefix. If you want to embed the variables
   141  in a string, you can do so with the `${}` HCL interpolation syntax. If you are
   142  using an option that is a template engine, you still need to use the Go
   143  templating engine syntax `{{ .OPTION }}` for those engines.
   144  
   145  ## Assigning Variables
   146  
   147  There are multiple ways to assign variables. Below is also the order
   148  in which variable values are chosen. The following is the descending order
   149  of precedence in which variables are considered. So first defined; first used.
   150  
   151  #### Command-line flags
   152  
   153  You can set variables directly on the command-line with the
   154  `-var` flag.:
   155  
   156  ```shell-session
   157  $ packer build \
   158    -var "weekday=Sunday" \
   159    -var "flavor=chocolate" \
   160    -var "sudo_password=hunter42" .
   161  ```
   162  
   163  Once again, setting variables this way will not save them, and they'll
   164  have to be input repeatedly as commands are executed.
   165  
   166  If you plan to assign variables via the command line, we strongly recommend that
   167  you at least set a default type instead of using empty blocks; this helps the
   168  HCL parser understand what is being set. Otherwise it will interpret all of your
   169  command line variables as strings.
   170  
   171  #### From a file
   172  
   173  To persist variable values, create a file and assign variables within
   174  this file. A variable definitions file uses the same basic syntax as Packer language files,
   175  but consists only of variable name assignments.
   176  
   177  ```hcl
   178  sudo_password = "partyparrot"
   179  weekday       = "Sunday"
   180  ```
   181  
   182  When assigning values in a variable definitions file please make sure to quote any string values,
   183  wrap list values within brackets `[...]`, and wrap maps within curly-braces `{...}`.
   184  
   185  Given a file named `variables.pkrvars.hcl` Packer can be instructed to use the
   186  variable definitions file by using the `-var-file` command line flag.
   187  
   188  ```shell-session
   189  $ packer build -var-file="variables.pkrvars.hcl" .
   190  ```
   191  
   192  Packer will automatically load any var file that matches the name
   193  `*.auto.pkrvars.hcl`, without the need to pass the file via the command line.
   194  If we rename the above variable definitions file from `variables.pkrvars.hcl` to
   195  `variables.auto.pkrvars.hcl`, then we can run our build simply by calling
   196  
   197  ```shell-session
   198  $ packer build .
   199  ```
   200  
   201  You may provide as many -var-file flags as you would like:
   202  
   203  ```shell-session
   204  $ packer build \
   205    -var-file="secret.pkrvars.hcl" \
   206    -var-file="production.pkrvars.hcl" .
   207  ```
   208  
   209  These files can also be JSON:
   210  
   211  variables.json:
   212  
   213  ```json
   214  {
   215    "weekday": "sunday",
   216    "flavor": "mint"
   217  }
   218  ```
   219  
   220  ```shell-session
   221  $ packer build -var-file=variables.json
   222  ```
   223  
   224  We don't recommend saving sensitive information to version control, but you
   225  can create a local secret variables file and use `-var-file` to load it.
   226  
   227  You can use multiple `-var-file` arguments in a single command, with some
   228  checked in to version control and others not checked in. For example:
   229  
   230  ```shell-session
   231  $ packer build \
   232    -var-file="secret.pkrvars.hcl" \
   233    -var-file="production.pkrvars.hcl" .
   234  ```
   235  
   236  #### From environment variables
   237  
   238  Packer will read environment variables in the form of `PKR_VAR_name` to find
   239  the value for a variable. For example, the `PKR_VAR_access_key` variable can be
   240  set to set the `access_key` variable.
   241  
   242  ```shell-session
   243  $ export PKR_VAR_weekday=Monday
   244  $ packer build .
   245  ```
   246  
   247  #### Variable Defaults
   248  
   249  If no value is assigned to a variable via any of these methods and the
   250  variable has a `default` key in its declaration, that value will be used
   251  for the variable.
   252  
   253  If all of your variables have defaults, then you can call a packer build using:
   254  
   255  ```shell-session
   256  $ packer build .
   257  ```
   258  
   259  You can make this work for yourself using the variable example file above by
   260  commenting out or removing the "weekday" variable declaration, since it is not
   261  actually used in the example build.
   262  
   263  If your variable definitions are stored in the same file as your source and
   264  build, you can call the build against that specific file:
   265  
   266  ```shell-session
   267  $ packer build self_contained_example.pkr.hcl
   268  ```
   269  
   270  #### Unspecified Values Fail
   271  
   272  If you call `packer build` with any variables defined but not set, Packer will
   273  error.
   274  
   275  ## Variable Type Reference
   276  
   277  ### Lists
   278  
   279  Lists are defined either explicitly or implicitly
   280  
   281  ```hcl
   282  # implicitly by using brackets [...]
   283  variable "cidrs" { default = [] }
   284  
   285  # explicitly
   286  variable "cidrs" { type = list }
   287  ```
   288  
   289  You can specify lists in a `variables.pkrvars.hcl` file:
   290  
   291  ```hcl
   292  cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]
   293  ```
   294  
   295  ### Maps
   296  
   297  Maps are a way to create variables that are lookup tables. An example
   298  will show this best. Let's extract our AMIs into a map and add
   299  support for the `us-west-2` region as well:
   300  
   301  ```hcl
   302  variable "amis" {
   303    type = map(string)
   304    default = {
   305      "us-east-1" = "ami-b374d5a5"
   306      "us-west-2" = "ami-4b32be2b"
   307    }
   308  }
   309  ```
   310  
   311  A variable can have a `map` type assigned explicitly, or it can be implicitly
   312  declared as a map by specifying a default value that is a map. The above
   313  demonstrates both.
   314  
   315  Then we can `lookup` in maps like in the following:
   316  
   317  ```hcl
   318  source "amazon-ebs" "example" {
   319    source_ami    = "${lookup(var.amis, var.region)}"
   320    instance_type = "t2.micro"
   321  }
   322  ```
   323  
   324  This introduces a new type of interpolation: a function call. The
   325  `lookup` function does a dynamic lookup in a map for a key. The
   326  key is `var.region`, which specifies that the value of the region
   327  variables is the key.
   328  
   329  You can also do a static lookup of a map directly with
   330  `${var.amis["us-east-1"]}`.
   331  
   332  ## Assigning Maps
   333  
   334  We set defaults above, but maps can also be set using the `-var` and
   335  `-var-file` values. For example:
   336  
   337  ```shell-session
   338  $ packer build -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
   339  # ...
   340  ```
   341  
   342  Here is an example of setting a map's keys from a file. Starting with these
   343  variable definitions:
   344  
   345  ```hcl
   346  variable "region" {}
   347  variable "amis" {
   348    type = map
   349  }
   350  ```
   351  
   352  You can specify keys in a `variables.pkrvars.hcl` file:
   353  
   354  ```hcl
   355  amis = {
   356    "us-east-1" = "ami-abc123"
   357    "us-west-2" = "ami-def456"
   358  }
   359  ```
   360  
   361  And access them via `lookup()`:
   362  
   363  ```hcl
   364  output "ami" {
   365    value = "${lookup(var.amis, var.region)}"
   366  }
   367  ```
   368  
   369  Like so:
   370  
   371  ```shell-session
   372  $ packer build -var region=us-west-2
   373  ```