|
| 1 | +# Contributing |
| 2 | + |
| 3 | +This document provides guidelines for contributing to the Google Cloud Project Factory Terraform Module. |
| 4 | + |
| 5 | +## Dependencies |
| 6 | + |
| 7 | +The following dependencies must be installed on the development system: |
| 8 | + |
| 9 | +- [Docker Engine][docker-engine] |
| 10 | +- [Google Cloud SDK][google-cloud-sdk] |
| 11 | +- [make] |
| 12 | + |
| 13 | +### File structure |
| 14 | + |
| 15 | +The project has the following folders and files: |
| 16 | + |
| 17 | +- /: root folder |
| 18 | +- /examples: examples for using this module |
| 19 | +- /scripts: Scripts for specific tasks on module (see Infrastructure section on |
| 20 | + this file) |
| 21 | +- /test: Folders with files for testing the module (see Testing section on this |
| 22 | + file) |
| 23 | +- /helpers: Optional helper scripts for ease of use |
| 24 | +- /main.tf: main file for this module, contains all the resources to create |
| 25 | +- /variables.tf: all the variables for the module |
| 26 | +- /output.tf: the outputs of the module |
| 27 | +- /readme.md: this file |
| 28 | + |
| 29 | +## Generating Documentation for Inputs and Outputs |
| 30 | + |
| 31 | +The Inputs and Outputs tables in the READMEs of the root module, |
| 32 | +submodules, and example modules are automatically generated based on |
| 33 | +the `variables` and `outputs` of the respective modules. These tables |
| 34 | +must be refreshed if the module interfaces are changed. |
| 35 | + |
| 36 | +### Execution |
| 37 | + |
| 38 | +Run `make generate_docs` to generate new Inputs and Outputs tables. |
| 39 | + |
| 40 | +## Integration Testing |
| 41 | + |
| 42 | +Integration tests are used to verify the behaviour of the root module, |
| 43 | +submodules, and example modules. Additions, changes, and fixes should |
| 44 | +be accompanied with tests. |
| 45 | + |
| 46 | +The integration tests are run using [Kitchen][kitchen], |
| 47 | +[Kitchen-Terraform][kitchen-terraform], and [InSpec][inspec]. These |
| 48 | +tools are packaged within a Docker image for convenience. |
| 49 | + |
| 50 | +The general strategy for these tests is to verify the behaviour of the |
| 51 | +[example modules](./examples/), thus ensuring that the root module, |
| 52 | +submodules, and example modules are all functionally correct. |
| 53 | + |
| 54 | +### Test Environment |
| 55 | +The easiest way to test the module is in an isolated test project. The setup for such a project is defined in [test/setup](./test/setup/) directory. |
| 56 | + |
| 57 | +To use this setup, you need a service account with Project Creator access on a folder. Export the Service Account credentials to your environment like so: |
| 58 | + |
| 59 | +``` |
| 60 | +export SERVICE_ACCOUNT_JSON=$(< credentials.json) |
| 61 | +``` |
| 62 | + |
| 63 | +You will also need to set a few environment variables: |
| 64 | +``` |
| 65 | +export TF_VAR_org_id="your_org_id" |
| 66 | +export TF_VAR_folder_id="your_folder_id" |
| 67 | +export TF_VAR_billing_account="your_billing_account_id" |
| 68 | +export TF_VAR_gsuite_admin_email="your_gsuite_admin_email" |
| 69 | +export TF_VAR_gsuite_domain="your_gsuite_domain" |
| 70 | +``` |
| 71 | + |
| 72 | +With these settings in place, you can prepare a test project using Docker: |
| 73 | + |
| 74 | +``` |
| 75 | +make docker_test_prepare |
| 76 | +``` |
| 77 | + |
| 78 | +### Noninteractive Execution |
| 79 | + |
| 80 | +Run `make docker_test_integration` to test all of the example modules |
| 81 | +noninteractively, using the prepared test project. |
| 82 | + |
| 83 | +### Interactive Execution |
| 84 | + |
| 85 | +1. Run `make docker_run` to start the testing Docker container in |
| 86 | + interactive mode. |
| 87 | + |
| 88 | +1. Run `kitchen_do create <EXAMPLE_NAME>` to initialize the working |
| 89 | + directory for an example module. |
| 90 | + |
| 91 | +1. Run `kitchen_do converge <EXAMPLE_NAME>` to apply the example module. |
| 92 | + |
| 93 | +1. Run `kitchen_do verify <EXAMPLE_NAME>` to test the example module. |
| 94 | + |
| 95 | +1. Run `kitchen_do destroy <EXAMPLE_NAME>` to destroy the example module |
| 96 | + state. |
| 97 | + |
| 98 | +## Linting and Formatting |
| 99 | + |
| 100 | +Many of the files in the repository can be linted or formatted to |
| 101 | +maintain a standard of quality. |
| 102 | + |
| 103 | +### Execution |
| 104 | + |
| 105 | +Run `make docker_test_lint`. |
| 106 | + |
| 107 | +## Releasing New Versions |
| 108 | + |
| 109 | +New versions can be released by pushing tags to this repository's origin on |
| 110 | +GitHub. There is a Make target to facilitate the process: |
| 111 | + |
| 112 | +``` |
| 113 | +make release-new-version |
| 114 | +``` |
| 115 | + |
| 116 | +The new version must be documented in [CHANGELOG.md](CHANGELOG.md) for the |
| 117 | +target to work. |
| 118 | + |
| 119 | +See the Terraform documentation for more info on [releasing new |
| 120 | +versions][release-new-version]. |
| 121 | + |
| 122 | +[release-new-version]: https://www.terraform.io/docs/registry/modules/publish.html#releasing-new-versions |
| 123 | +[docker-engine]: https://www.docker.com/products/docker-engine |
| 124 | +[flake8]: http://flake8.pycqa.org/en/latest/ |
| 125 | +[gofmt]: https://golang.org/cmd/gofmt/ |
| 126 | +[google-cloud-sdk]: https://cloud.google.com/sdk/install |
| 127 | +[hadolint]: https://github.com/hadolint/hadolint |
| 128 | +[inspec]: https://inspec.io/ |
| 129 | +[kitchen-terraform]: https://github.com/newcontext-oss/kitchen-terraform |
| 130 | +[kitchen]: https://kitchen.ci/ |
| 131 | +[make]: https://en.wikipedia.org/wiki/Make_(software) |
| 132 | +[shellcheck]: https://www.shellcheck.net/ |
| 133 | +[terraform-docs]: https://github.com/segmentio/terraform-docs |
| 134 | +[terraform]: https://terraform.io/ |
| 135 | + |
| 136 | +--------------------------------------------------------------------------------------------------- |
| 137 | + |
| 138 | +Two test-kitchen instances are defined: |
| 139 | + |
| 140 | +- `full-local` - Test coverage for all project-factory features. |
| 141 | +- `full-minimal` - Test coverage for a minimal set of project-factory features. |
| 142 | + |
| 143 | +#### Setup |
| 144 | + |
| 145 | +1. Configure the [test fixtures](#test-configuration). |
| 146 | +2. Download a Service Account key with the necessary [permissions](#permissions) |
| 147 | + and put it in the module's root directory with the name `credentials.json`. |
| 148 | +3. Add appropriate variables to your environment |
| 149 | + |
| 150 | + ``` |
| 151 | + export BILLING_ACCOUNT_ID="YOUR_BILLUNG_ACCOUNT" |
| 152 | + export DOMAIN="YOUR_DOMAIN" |
| 153 | + export FOLDER_ID="YOUR_FOLDER_ID" |
| 154 | + export GROUP_NAME="YOUR_GROUP_NAME" |
| 155 | + export ADMIN_ACCOUNT_EMAIL="YOUR_ADMIN_ACCOUNT_EMAIL" |
| 156 | + export ORG_ID="YOUR_ORG_ID" |
| 157 | + export PROJECT_ID="YOUR_PROJECT_ID" |
| 158 | + CREDENTIALS_FILE="credentials.json" |
| 159 | + export SERVICE_ACCOUNT_JSON=`cat ${CREDENTIALS_FILE}` |
| 160 | + ``` |
| 161 | + |
| 162 | +4. Run the testing container in interactive mode. |
| 163 | + ``` |
| 164 | + make docker_run |
| 165 | + ``` |
| 166 | +
|
| 167 | + The module root directory will be loaded into the Docker container at `/cft/workdir/`. |
| 168 | +5. Run kitchen-terraform to test the infrastructure. |
| 169 | +
|
| 170 | + 1. `kitchen create` creates Terraform state. |
| 171 | + 2. `kitchen converge` creates the underlying resources. You can run `kitchen converge minimal` to only create the minimal fixture. |
| 172 | + 3. `kitchen verify` tests the created infrastructure. Run `kitchen verify minimal` to run the smaller test suite. |
| 173 | + 4. `kitchen destroy` removes the created infrastructure. Run `kitchen destroy minimal` to remove the smaller test suite. |
| 174 | +
|
| 175 | +Alternatively, you can simply run `make test_integration_docker` to run all the |
| 176 | +test steps non-interactively. |
| 177 | +
|
| 178 | +#### Test configuration |
| 179 | +
|
| 180 | +Each test-kitchen instance is configured with a `terraform.tfvars` file in the |
| 181 | +test fixture directory. For convenience, these are symlinked to a single shared file: |
| 182 | +
|
| 183 | +```sh |
| 184 | +cp "test/fixtures/shared/terraform.tfvars.example" \ |
| 185 | + "test/fixtures/shared/terraform.tfvars" |
| 186 | +$EDITOR "test/fixtures/shared/terraform.tfvars" |
| 187 | +done |
| 188 | +``` |
| 189 | + |
| 190 | +Integration tests can be run within a pre-configured docker container. Tests can |
| 191 | +be run without user interaction for quick validation, or with user interaction |
| 192 | +during development. |
0 commit comments