github.com/pdecat/terraform@v0.11.9-beta1/website/docs/modules/create.html.markdown (about)

     1  ---
     2  layout: "docs"
     3  page_title: "Creating Modules"
     4  sidebar_current: "docs-modules-create"
     5  description: How to create modules.
     6  ---
     7  
     8  # Creating Modules
     9  
    10  Creating modules in Terraform is easy. You may want to do this to better organize your code, to make a reusable component, or just to learn more about Terraform. For any reason, if you already know the basics of Terraform, then creating a module is a piece of cake.
    11  
    12  Modules in Terraform are folders with Terraform files. In fact, when you run `terraform apply`, the current working directory holding
    13  the Terraform files you're applying comprise what is called the _root module_. This itself is a valid module.
    14  
    15  Therefore, you can enter the source of any module, satisfy any required variables, run `terraform apply`, and expect it to work.
    16  
    17  Modules that are created for reuse should follow the
    18  [standard structure](#standard-module-structure). This structure enables tooling
    19  such as the [Terraform Registry](/docs/registry/index.html) to inspect and
    20  generate documentation, read examples, and more.
    21  
    22  ## An Example Module
    23  
    24  Within a folder containing Terraform configurations, create a subfolder called `child`. In this subfolder, make one empty `main.tf` file. Then, back in the root folder containing the `child` folder, add this to one of your Terraform configuration files:
    25  
    26  ```hcl
    27  module "child" {
    28    source = "./child"
    29  }
    30  ```
    31  
    32  You've now created your first module! You can now add resources to the `child` module.
    33  
    34  **Note:** Prior to running the above, you'll have to run [the get command](/docs/commands/get.html) for Terraform to sync
    35  your modules. This should be instant since the module is a local path.
    36  
    37  ## Inputs/Outputs
    38  
    39  To make modules more useful than simple isolated containers of Terraform configurations, modules can be configured and also have outputs that can be consumed by your Terraform configuration.
    40  
    41  Inputs of a module are [variables](/docs/configuration/variables.html) and outputs are [outputs](/docs/configuration/outputs.html). There is no special syntax to define these, they're defined just like any other variables or outputs. You can think about these variables and outputs as the API interface to your module.
    42  
    43  Let's add a variable and an output to our `child` module.
    44  
    45  ```hcl
    46  variable "memory" {}
    47  
    48  output "received" {
    49    value = "${var.memory}"
    50  }
    51  ```
    52  
    53  This will create a required variable, `memory`, and then an output, `received`, that will be the value of the `memory` variable.
    54  
    55  You can then configure the module and use the output like so:
    56  
    57  ```hcl
    58  module "child" {
    59    source = "./child"
    60  
    61    memory = "1G"
    62  }
    63  
    64  output "child_memory" {
    65    value = "${module.child.received}"
    66  }
    67  ```
    68  
    69  If you now run `terraform apply`, you see how this works.
    70  
    71  ## Paths and Embedded Files
    72  
    73  It is sometimes useful to embed files within the module that aren't Terraform configuration files, such as a script to provision a resource or a file to upload.
    74  
    75  In these cases, you can't use a relative path, since paths in Terraform are generally relative to the working directory from which Terraform was executed. Instead, you want to use a module-relative path. To do this, you should use the [path interpolated variables](/docs/configuration/interpolation.html).
    76  
    77  ```hcl
    78  resource "aws_instance" "server" {
    79    # ...
    80  
    81    provisioner "remote-exec" {
    82      script = "${path.module}/script.sh"
    83    }
    84  }
    85  ```
    86  
    87  Here we use `${path.module}` to get a module-relative path.
    88  
    89  ## Nested Modules
    90  
    91  You can nest a module within another module. This module will be hidden from your root configuration, so you'll have to re-expose any
    92  variables and outputs you require.
    93  
    94  The [get command](/docs/commands/get.html) will automatically get all nested modules.
    95  
    96  You don't have to worry about conflicting versions of modules, since Terraform builds isolated subtrees of all dependencies. For example, one module might use version 1.0 of module `foo` and another module might use version 2.0, and this will all work fine within Terraform since the modules are created separately.
    97  
    98  ## Standard Module Structure
    99  
   100  The standard module structure is a file and folder layout we recommend for
   101  reusable modules. Terraform tooling is built to understand the standard
   102  module structure and use that structure to generate documentation, index
   103  modules for the registry, and more.
   104  
   105  The standard module expects the structure documented below. The list may appear
   106  long, but everything is optional except for the root module. All items are
   107  documented in detail. Most modules don't need to do any work to follow the
   108  standard structure.
   109  
   110  * **Root module**. This is the **only required element** for the standard
   111    module structure. Terraform files must exist in the root directory of
   112    the module. This should be the primary entrypoint for the module and is
   113    expected to be opinionated. For the
   114    [Consul module](https://registry.terraform.io/modules/hashicorp/consul)
   115    the root module sets up a complete Consul cluster. A lot of assumptions
   116    are made, however, and it is fully expected that advanced users will use
   117    specific nested modules to more carefully control what they want.
   118  
   119  * **README**. The root module and any nested modules should have README
   120    files. This file should be named `README` or `README.md`. The latter will
   121    be treated as markdown. There should be a description of the module and 
   122    what it should be used for. If you want to include an example for how this
   123    module can be used in combination with other resources, put it in an [examples
   124    directory like this](https://github.com/hashicorp/terraform-aws-consul/tree/master/examples).
   125    Consider including a visual diagram depicting the infrastructure resources 
   126    the module may create and their relationship. The README doesn't need to 
   127    document inputs or outputs of the module because tooling will automatically 
   128    generate this. If you are linking to a file or embedding an image contained
   129    in the repository itself, use a commit-specific absolute URL so the link won't
   130    point to the wrong version of a resource in the future.
   131  
   132  * **LICENSE**. The license under which this module is available. If you are
   133    publishing a module publicly, many organizations will not adopt a module
   134    unless a clear license is present. We recommend always having a license
   135    file, even if the license is non-public.
   136  
   137  * **main.tf, variables.tf, outputs.tf**. These are the recommended filenames for
   138    a minimal module, even if they're empty. `main.tf` should be the primary
   139    entrypoint. For a simple module, this may be where all the resources are
   140    created. For a complex module, resource creation may be split into multiple
   141    files but all nested module usage should be in the main file. `variables.tf`
   142    and `outputs.tf` should contain the declarations for variables and outputs,
   143    respectively.
   144  
   145  * **Variables and outputs should have descriptions.** All variables and
   146    outputs should have one or two sentence descriptions that explain their
   147    purpose. This is used for documentation. See the documentation for
   148    [variable configuration](/docs/configuration/variables.html) and
   149    [output configuration](/docs/configuration/outputs.html) for more details.
   150  
   151  * **Nested modules**. Nested modules should exist under the `modules/`
   152    subdirectory. Any nested module with a `README.md` is considered usable
   153    by an external user. If a README doesn't exist, it is considered for internal
   154    use only. These are purely advisory; Terraform will not actively deny usage
   155    of internal modules. Nested modules should be used to split complex behavior
   156    into multiple small modules that advanced users can carefully pick and
   157    choose. For example, the
   158    [Consul module](https://registry.terraform.io/modules/hashicorp/consul)
   159    has a nested module for creating the Cluster that is separate from the
   160    module to setup necessary IAM policies. This allows a user to bring in their
   161    own IAM policy choices.
   162  
   163  * **Examples**. Examples of using the module should exist under the
   164    `examples/` subdirectory at the root of the repository. Each example may have
   165    a README to explain the goal and usage of the example. Examples for
   166    submodules should also be placed in the root `examples/` directory.
   167  
   168  A minimal recommended module following the standard structure is shown below.
   169  While the root module is the only required element, we recommend the structure
   170  below as the minimum:
   171  
   172  ```sh
   173  $ tree minimal-module/
   174  .
   175  ├── README.md
   176  ├── main.tf
   177  ├── variables.tf
   178  ├── outputs.tf
   179  ```
   180  
   181  A complete example of a module following the standard structure is shown below.
   182  This example includes all optional elements and is therefore the most
   183  complex a module can become:
   184  
   185  ```sh
   186  $ tree complete-module/
   187  .
   188  ├── README.md
   189  ├── main.tf
   190  ├── variables.tf
   191  ├── outputs.tf
   192  ├── ...
   193  ├── modules/
   194  │   ├── nestedA/
   195  │   │   ├── README.md
   196  │   │   ├── variables.tf
   197  │   │   ├── main.tf
   198  │   │   ├── outputs.tf
   199  │   ├── nestedB/
   200  │   ├── .../
   201  ├── examples/
   202  │   ├── exampleA/
   203  │   │   ├── main.tf
   204  │   ├── exampleB/
   205  │   ├── .../
   206  ```
   207  
   208  ## Publishing Modules
   209  
   210  If you've built a module that you intend to be reused, we recommend
   211  [publishing the module](/docs/registry/modules/publish.html) on the
   212  [Terraform Registry](https://registry.terraform.io). This will version
   213  your module, generate documentation, and more.
   214  
   215  Published modules can be easily consumed by Terraform, and (from Terraform
   216  0.11) you can also [constrain module versions](usage.html#module-versions) for safe and predictable
   217  updates. The following example shows how easy it is to consume a module
   218  from the registry:
   219  
   220  ```hcl
   221  module "consul" {
   222    source = "hashicorp/consul/aws"
   223  }
   224  ```
   225  
   226  You can also gain all the benefits of the registry for private modules
   227  by signing up for a [private registry](/docs/registry/private.html).