---
#
# This is the canonical configuration for the `README.md`
# Run `make readme` to rebuild the `README.md`
#

# Name of this project
name: "terraform-root-modules"

# Tags of this project
tags:
  - terraform
  - terraform-modules
  - aws
  - root
  - geodesic
  - reference-implementation
  - reference-architecture

# Categories of this project
categories:
  - terraform-modules/root

# Logo for this project
#logo: docs/logo.png

# License of this project
license: "APACHE2"

# Canonical GitHub repo
github_repo: "cloudposse/terraform-root-modules"

# Badges to display
badges:
  - name: "Build Status"
    image: "https://travis-ci.org/cloudposse/terraform-root-modules.svg?branch=master"
    url: "https://travis-ci.org/cloudposse/terraform-root-modules"
  - name: "Codefresh Build Status"
    image: "https://g.codefresh.io/api/badges/build?repoOwner=cloudposse&repoName=terraform-root-modules&branch=master&pipelineName=terraform-root-modules&accountName=cloudposse&type=cf-1"
    url: "https://g.codefresh.io/pipelines/terraform-root-modules/builds"
  - name: "Latest Release"
    image: "https://img.shields.io/github/release/cloudposse/terraform-root-modules.svg"
    url: "https://github.com/cloudposse/terraform-root-modules/releases/latest"
  - name: "Slack Community"
    image: "https://slack.cloudposse.com/badge.svg"
    url: "https://slack.cloudposse.com"

references:
  - name: "Cloud Posse Documentation"
    description: "Complete documentation for the Cloud Posse solution"
    url: "https://docs.cloudposse.com"

related:
  - name: "reference-architectures"
    description: "Get up and running quickly with one of our reference architecture using our fully automated cold-start process." 
    url: "https://github.com/cloudposse/reference-architectures"
  - name: "audit.cloudposse.co"
    description: "Example Terraform Reference Architecture of a Geodesic Module for an Audit Logs Organization in AWS." 
    url: "https://github.com/cloudposse/audit.cloudposse.co"
  - name: "prod.cloudposse.co"
    description: "Example Terraform Reference Architecture of a Geodesic Module for a Production Organization in AWS." 
    url: "https://github.com/cloudposse/prod.cloudposse.co"
  - name: "staging.cloudposse.co"
    description: "Example Terraform Reference Architecture of a Geodesic Module for a Staging Organization in AWS." 
    url: "https://github.com/cloudposse/staging.cloudposse.co"
  - name: "dev.cloudposse.co"
    description: "Example Terraform Reference Architecture of a Geodesic Module for a Development Sandbox Organization in AWS." 
    url: "https://github.com/cloudposse/dev.cloudposse.co"

# Short description of this project
description: |-
  This is a collection of reusable [Terraform "root modules" invocations](https://docs.cloudposse.com/terraform-modules/root/) for CloudPosse AWS accounts. 

  Terraform defines a "root module" as the current working directory holding the Terraform configuration files where the terraform apply or terraform get is run. 

introduction: |-
  In this repo you'll find real-world examples of how we've implemented various common patterns using our [terraform modules](https://cpco.io/terraform-modules) for our customers.  

  The "root modules" form the module catalog of your organization.  It's from this catalog that other developers in your organization will pick and choose from anytime they need to deploy some new capability. 

  Normally, a company should build up their own service catalog of terraform modules like this one, which is just a collection of terraform modules that capture the business logic, opinions, "best practices" and non-functional requirements of the organization. 
  No two companies will ever have the same assembly of `terraform-root-modules`. 
  
  The root modules are the most opinionated incarnations of modules that seldom translate verbatim across organizations.  This is your secret sauce.  We could never implement this in a sufficiently generic way without creating crazy bloat and complexity.  Therefore treat the terraform-root-modules in this repository as your “starting off point” where you hardfork/diverge.  
  These modules are very specific to how we do things in our environment, so they might not "drop in" smoothly in other environments as they make a lot of assumptions on how things are organized. 

  A company writes their own root modules.  It’s their flavor of how to leverage the [generic building blocks](https://cpco.io/terraform-modules) to achieve the specific customizations that are required without needing to write everything from the ground up because they are leveraging our general purpose modules. 
  The idea is to write all of the [`terraform-aws-*`](https://cpco.io/terraform-modules) type modules very generically so they are easily composable inside of other modules. 
  
  These `terraform-root-modules` make a lot of assumptions about how we've configured our environments.  That said, they can still serve as an excellent reference for others. 

  We recommend that you start with your clean `terraform-root-module` repo.  Then start by creating a new project in there to describe the infrastructure that you want. 

  ## Best Practices
  
  * Every "root module" should include a `Makefile` that defines `init`, `plan`, and `apply` targets.  
    This establishes a common interface for interacting with terraform without the need of a wrapper like `terragrunt`. 
  * Never compose "root modules" inside of other root modules.  If or when this is desired, then the module should be split off into a new repository and versioned independently as a standalone module. 

  ## Example Makefile

  Here's a good example of a `Makefile` for a terraform project:

  ```
  ## Initialize terraform remote state
  init:
  	[ -f .terraform/terraform.tfstate ] || terraform $@

  ## Clean up the project
  clean:
  	rm -rf .terraform *.tfstate*

  ## Pass arguments through to terraform which require remote state
  apply console destroy graph plan output providers show: init
  	terraform $@

  ## Pass arguments through to terraform which do not require remote state
  get fmt validate version:
  	terraform $@
  ```

# How to use this project
usage: |-
  As of this writing, our `terraform-root-modules` and nearly all of our Terraform modules only work
  with Terraform v0.11.  Terraform v0.12 uses a major redesign
  of HCL, the language in which Terraform modules are written, and is not compatible with the language used in v0.11. 
  It is expected that this will result in a strong split between how v0.11 is used and how v0.12 is used in the
  future.  Theses instructions are for environments exclusively using Terraform v0.11. 

  With the CloudPosse [reference architecture](https://github.com/cloudposse/reference-architectures), each environment
  (e.g. staging and prod) has its own, customized
  version of [Geodesic](https://github.com/cloudposse/geodesic).  The process for using one of these Terraform root modules
  is one of further customizing the environment's Geodesic as follows:
  1.  Create a directory under `/conf` to contain the files related to the root module.  Normally the directory has the same name
  as the root module. 
  1.  Copy the `.envrc`, `Makefile.tasks`, and `terraform.envrc` files
  from [`cloudposse/reference-architectures/templates/conf/kops`](https://github.com/cloudposse/reference-architectures/tree/0.13.0/templates/conf/kops)
  into the new directory.  The `.envrc` and `Makefile.tasks` files are boilerplate and do not need to be changed. 
  1.  Edit the `terraform.envrc` file so that the `TF_CLI_INIT_FROM_MODULE` points to the desired Terraform root module. 
  Be sure to pin it to a specific version.  Add additional environment variable settings if desired. 
  1.  Add a `terraform.tfvars` file that sets the values
  of all the inputs to your Terraform root module that need to be set (i.e. that do not
  have acceptable defaults). 

  Then build, install, and run your Geodesic shell. 

  Then, from within the Geodesic shell, after going through the authorization steps such as `assume-role`, `cd` to the
  new folder.  The built-in `envrc` hook will configure the shell for Terraform automatically as a result of the `cd`. 

  Then, `make deps` will download the Terraform modules and initialze the Terraform state. 

  Then you can use `terraform plan` and `terraform apply` to preview and apply the changes dictated by the module. 

examples: |-
  For example usage, refer to the "Related Projects" section.  This is were we use `terraform-root-modules` to provision essential account-level infrastructure, among other services. 

include:
  - "docs/targets.md"
  - "docs/terraform.md"

# Contributors to this project
contributors:
  - name: "Erik Osterman"
    github: "osterman"
  - name: "Igor Rodionov"
    github: "goruha"
  - name: "Andriy Knysh"
    github: "aknysh"
