github.com/jzbruno/terraform@v0.10.3-0.20180104230435-18975d727047/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. Each example may have a README to explain the
   165    goal and usage of the example.
   166  
   167  A minimal recommended module following the standard structure is shown below.
   168  While the root module is the only required element, we recommend the structure
   169  below as the minimum:
   170  
   171  ```sh
   172  $ tree minimal-module/
   173  .
   174  ├── README.md
   175  ├── main.tf
   176  ├── variables.tf
   177  ├── outputs.tf
   178  ```
   179  
   180  A complete example of a module following the standard structure is shown below.
   181  This example includes all optional elements and is therefore the most
   182  complex a module can become:
   183  
   184  ```sh
   185  $ tree complete-module/
   186  .
   187  ├── README.md
   188  ├── main.tf
   189  ├── variables.tf
   190  ├── outputs.tf
   191  ├── ...
   192  ├── modules/
   193  │   ├── nestedA/
   194  │   │   ├── README.md
   195  │   │   ├── variables.tf
   196  │   │   ├── main.tf
   197  │   │   ├── outputs.tf
   198  │   ├── nestedB/
   199  │   ├── .../
   200  ├── examples/
   201  │   ├── exampleA/
   202  │   │   ├── main.tf
   203  │   ├── exampleB/
   204  │   ├── .../
   205  ```
   206  
   207  ## Publishing Modules
   208  
   209  If you've built a module that you intend to be reused, we recommend
   210  [publishing the module](/docs/registry/modules/publish.html) on the
   211  [Terraform Registry](https://registry.terraform.io). This will version
   212  your module, generate documentation, and more.
   213  
   214  Published modules can be easily consumed by Terraform, and in Terraform
   215  0.11 you'll also be able to constrain module versions for safe and predictable
   216  updates. The following example shows how easy it is to consume a module
   217  from the registry:
   218  
   219  ```hcl
   220  module "consul" {
   221    source = "hashicorp/consul/aws"
   222  }
   223  ```
   224  
   225  You can also gain all the benefits of the registry for private modules
   226  by signing up for a [private registry](/docs/registry/private.html).