Skip to content

Latest commit

 

History

History
168 lines (114 loc) · 8.83 KB

README.md

File metadata and controls

168 lines (114 loc) · 8.83 KB

Terraform

The persistent AWS infrastructure is deployed as Cloud.gov assets via Terraform. For a description of persistent infrastructure and how it differs from ephemeral infrastructure see the root README.md.

These docs are verbose because this is technology with which developers will rarely interact. I suggest you settle in for a nice long read with your favorite drink of choice.

Set up

  1. Install Terraform

  2. Use githook for formatting

    Terraform has a specific whitespace formatting style that is difficult to maintain. Terraform includes a formatting command, terraform fmt, to help developers maintain the correct style. This repository contains a pre-commit hook that runs terraform fmt on all staged files so you don't have to remember to run this command.

    If you are not using your own custom pre-commit hooks:

    # start from repo root directory
    
    # make the pre-commit file executable
    chmod 755 .githooks/pre-commit
    
    # change your default hooks directory to `.githooks`.
    git config core.hooksPath .githooks

    If you are already using git hooks, add the .githooks/pre-commit contents to your hooks directory or current pre-commit hook. Remember to make the file executable.

  3. Install Version 7 of the Cloud Foundry CLI tool

    • On MacOS: brew install cloudfoundry/tap/cf-cli@7
    • On other platforms: Download and install cf. Be sure to get version 7.x
  4. Add target environment credentials

    We are using Terraform to create Cloud Foundry resources in a Cloud.gov account. Creating infrastructure on the Cloud.gov platform requires a Cloud.gov service account username and password. These keys are specific to each cloud.gov organization/space, i.e. each deployment environment, and can be generated by developers who have proper Cloud.gov permissions at any time.

    Follow the steps below to generate a new set of credentials. If you need more information, check out the service account docs.

    # login
    cf login -a api.fr.cloud.gov --sso
    # follow temporary authorization code prompts
    # select org "hhs-acf-ohs-tta", and the space (env) within which you want to build infrastructure
    # sandbox = ttahub-sandbox
    # dev = ttahub-dev
    # staging = ttahub-staging
    # prod = ttahub-prod
    
    # create a service instance that can provision service accounts
    # the value for < YOUR-NAME > can be any version of your name, it isn't significant
    cf create-service cloud-gov-service-account space-deployer < YOUR-NAME >
    
    # bind a service key to the service instance
    cf create-service-key < YOUR-NAME > space-deployer-key
    
    # return a username/password pair for the service instance
    cf service-key < YOUR-NAME > space-deployer-key

    Add the username and password output from the last command to a secrets.auto.tfvars file in each environment directory. Terraform automatically loads this variable definition file. You can also provide variable values via environment variables. For more on this, check out terraform variable definitions.

    For example, your terraform/dev/secrets.auto.tfvars file should look something like this:

    cf_user = "some-dev-user"
    cf_password = "some-dev-password"
    

    Additionally, for environments other than dev and production, we need to grant the space deployer credentials access to the dev space to enable setting up network policies to the dev ClamAV server.

    # Grant some-dev-user from previous step SpaceDeveloper access to ttahub-dev
    cf set-space-role <some-dev-user from previous step> hhs-acf-ohs-tta ttahub-dev SpaceDeveloper
    
  5. Create S3 bucket credentials

    We are using an S3 bucket created by Cloud Foundry in Cloud.gov as our remote backend for Terraform. The backend maintains the "state" of Terraform and makes it possible for multiple developers to implement changes in a linear fashion.

    Follow these directions to create a new service account and generate credentials. If you need more information check out the services docs.

    # login
    cf login -a api.fr.cloud.gov --sso
    # follow temporary authorization code prompts
    # select org "hhs-acf-ohs-tta", space "infrastructure-config"
    
    # create a service instance
    # the value for < YOUR-NAME > can be any version of your name
    # it can be the same or different from the name you used for environment credentials in the previous step
    cf create-service-key ohs-ttahub-iac-state < YOUR-NAME >
    
    # return a username/password pair for the service instance
    cf service-key ohs-ttahub-iac-state < YOUR-NAME >

    These credentials are for an S3 bucket that is used for holding the state of the dev, staging, and prod terraform environments; you only need to create one set of these ohs-ttahub-iac-state S3 bucket credentials. If you're already using AWS CLI you may simply add your newly generated access_key_id, secret_access_key values to ~/.aws/credentials, and your region value to ~/.aws/config. If this is your first time using AWS CLI install the tool and then follow the Quick Configuration with aws configure guide.

    Your ~/.aws/credentials file should look something like this:

    [default]
    aws_access_key_id = foo
    aws_secret_access_key = bar
    

    Your ~/.aws/config file should look something like this:

    [default]
    region = us-gov-west-1
    

Terraform workflow

Tip: You run terraform files from the directory in which they are stored. For example, to instantiate a database described in terraform/dev/main.tf you would run all the commands below from terraform/dev.

  1. Initialize your working directory

    The first time you are working in a new environment, for example, after cloning this repository, you will need to initialize a working directory containing Terraform configuration files using the init command. It is safe to run this command multiple times.

    terraform init
  2. Check that your state is clean

    Terraform configuration files committed to the main branch should describe the infrastructure that is currently in use. This is described as a "clean state". Use the plan command to display a list of infrastructure that Terraform will need to update, delete or create to match what is in your local Terraform configuration files.

    • If state is clean, plan will not display any changes.
    • If state is not clean and you are working on a feature branch try merging in the main branch; your local terraform files might be behind the current/applied state. If plan still shows an unclean state, reach out to your fellow developers for clarification and advice on how to proceed. It is very likely that changes were accidentally applied and a developer is currently working on a fix.
    terraform plan
  3. Make changes and get feedback

    Make any needed changes to your local Terraform configuration files. Open a PR for those changes. In your PR include the output from terraform plan so reviewers can see what resources will be updated, created and destroyed.

  4. Merge and apply changes immediately

    Tip: Before you merge your PR ensure you have enough time to sit and work through any unexpected problems that could arise. Database changes can take upwards of ten minutes to apply.

    Merge your PR into main and then immediately apply your changes. Always merge and apply in one sitting.

    terraform apply
  5. Bind the infrastructure to the application

    CloudFoundry/cloud.gov requires that some "services" (e.g. AWS infrastructure) be "bound" to the application instance. S3, and Redis are all services that require this "binding" step. See the cloud.gov documentation for more direction on this. Also, check out PR#71 for an example of how this was done for the RDS instances.