Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build Network Fixtures and Run Tests with Kitchen-Terraform #33

Merged
merged 39 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1f88f47
Fix Docker build
Jberlinsky Nov 13, 2018
45618e7
Specify cluster versions in examples
Jberlinsky Nov 17, 2018
47189ea
Set up examples to run in test fixture networks
Jberlinsky Nov 19, 2018
98eb6d1
Add network fixtures
Jberlinsky Nov 19, 2018
5ec503a
Create fixtures as part of the integration test process, and share co…
Jberlinsky Nov 19, 2018
76b3498
Clean up botched merge
Jberlinsky Nov 20, 2018
a0b4fd3
Extract common outputs to fixture file, and consolidate fixture insta…
Jberlinsky Nov 20, 2018
2c399b0
Remove reference to kitchen-inspec
aaron-lane Nov 27, 2018
a7c2e5d
Pin Ruby to 2.5
aaron-lane Nov 27, 2018
d384655
Pin rest-client to v2
aaron-lane Nov 27, 2018
a8c5ace
Pin kubeclient to v4
aaron-lane Nov 27, 2018
42da44e
Pin kitchen-terraform to v4
aaron-lane Nov 27, 2018
98145c1
Add missing SA roles to Read Me
aaron-lane Nov 27, 2018
4cd24bd
Increase platform support for base64 command
aaron-lane Nov 27, 2018
f3fda19
Only move variables.tf during install if it exists
aaron-lane Nov 27, 2018
bb0e0dd
Pin Ruby to v2.5 in Makefile
aaron-lane Nov 27, 2018
a6045dc
Update go to v1.10.5-r0 in Dockerfile
aaron-lane Nov 27, 2018
a75e252
Update curl, git in Dockerfile
aaron-lane Nov 27, 2018
8208f86
Update packages in kitchen_terraform/Dockerfile
aaron-lane Nov 27, 2018
486c90d
Refactor example cases with mutliple assertions
Jberlinsky Nov 29, 2018
72899fa
Reduce attributes passed into test-kitchen examples to simplify syste…
Jberlinsky Nov 29, 2018
ae7b5da
Switch to using `includes` matchers instead of filtering for specific…
Jberlinsky Nov 30, 2018
9f8f58e
Enable project-factory support by allowing arbitrary service accounts…
Jberlinsky Dec 13, 2018
d3d4436
Call examples as modules from test fixtures
Jberlinsky Dec 13, 2018
9bb3963
Bump tested GKE versions
Jberlinsky Dec 13, 2018
176ad6f
Wait for GKE cluster to not be in RECONCILING status before completin…
Jberlinsky Dec 13, 2018
0f3fcc1
Fix linter error
Jberlinsky Dec 13, 2018
1c9754c
Pin Ruby to 2.5.1
Jberlinsky Dec 13, 2018
1a84f32
Update testing documentation
Jberlinsky Dec 13, 2018
73afe8b
Add line breaks
Jberlinsky Dec 13, 2018
614c24e
Bump ruby version to 2.5.3
Jberlinsky Dec 13, 2018
be970a4
Run `terraform fmt` as part of linting
Jberlinsky Dec 13, 2018
8d46662
Fix Go version in tests.
morgante Dec 19, 2018
b017249
Actually symlink terraform.tfvars
morgante Dec 19, 2018
cf5c27a
Missed one tfvars symlink
morgante Dec 19, 2018
4eeaaa3
Add descriptions to test environment variables
Jberlinsky Dec 19, 2018
a4a3f71
`terraform fmt`
Jberlinsky Dec 19, 2018
90a122e
Bring back shared_vpc example and simple test fixture
Jberlinsky Dec 19, 2018
4a32e01
Only .gitignore actual terraform variables, not symlinks
Jberlinsky Dec 19, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,9 @@ crash.log
**/.kitchen.local.yml
**/Gemfile.lock

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
**/terraform.tfvars
test/fixtures/shared/terraform.tfvars

test/integration/gcloud/config.sh
test/integration/tmp

credentials.json
98 changes: 98 additions & 0 deletions .kitchen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
driver:
name: "terraform"
command_timeout: 1800

provisioner:
name: "terraform"

platforms:
- name: local

suites:
- name: "deploy_service"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/deploy_service
verifier:
name: terraform
systems:
- name: deploy_service
backend: local
provisioner:
name: terraform
- name: "node_pool"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/node_pool
verifier:
name: terraform
systems:
- name: node_pool
backend: local
provisioner:
name: terraform
- name: "shared_vpc"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/shared_vpc
verifier:
name: terraform
systems:
- name: shared_vpc
backend: local
provisioner:
name: terraform
- name: "simple_regional"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/simple_regional
verifier:
name: terraform
systems:
- name: simple_regional
backend: local
provisioner:
name: terraform
- name: "simple_zonal"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/simple_zonal
verifier:
name: terraform
systems:
- name: simple_zonal
backend: local
provisioner:
name: terraform
- name: "stub_domains"
driver:
name: "terraform"
command_timeout: 1800
root_module_directory: test/fixtures/stub_domains
verifier:
name: terraform
systems:
- name: stub_domains
backend: local
provisioner:
name: terraform
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.5.3
9 changes: 4 additions & 5 deletions test/integration/gcloud/Gemfile → Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

ruby '2.4.2'
ruby "~> 2.5"

source 'https://rubygems.org/' do
gem 'googleauth'
gem 'google-api-client'
gem 'kitchen-terraform', '~> 3.3'
gem 'kitchen-inspec', :git => 'https://github.com/inspec/kitchen-inspec.git', :ref => '0590f1b'
gem "kitchen-terraform", "~> 4.0"
gem "kubeclient", "~> 4.0"
gem "rest-client", "~> 2.0"
end
97 changes: 84 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
# Make will use bash instead of sh
SHELL := /usr/bin/env bash

# Docker build config variables
morgante marked this conversation as resolved.
Show resolved Hide resolved
BUILD_TERRAFORM_VERSION ?= 0.11.10
BUILD_CLOUD_SDK_VERSION ?= 216.0.0
BUILD_PROVIDER_GOOGLE_VERSION ?= 1.17.1
BUILD_PROVIDER_GSUITE_VERSION ?= 0.1.8
DOCKER_IMAGE_TERRAFORM := cftk/terraform
DOCKER_TAG_TERRAFORM ?= ${BUILD_TERRAFORM_VERSION}_${BUILD_CLOUD_SDK_VERSION}_${BUILD_PROVIDER_GOOGLE_VERSION}_${BUILD_PROVIDER_GSUITE_VERSION}
BUILD_RUBY_VERSION := 2.5.3
DOCKER_IMAGE_KITCHEN_TERRAFORM := cftk/kitchen_terraform
DOCKER_TAG_KITCHEN_TERRAFORM ?= ${BUILD_TERRAFORM_VERSION}_${BUILD_CLOUD_SDK_VERSION}_${BUILD_PROVIDER_GOOGLE_VERSION}_${BUILD_PROVIDER_GSUITE_VERSION}

# All is the first target in the file so it will get picked up when you just run 'make' on its own
all: check_shell check_python check_golang check_terraform check_docker check_base_files test_check_headers check_headers check_trailing_whitespace generate_docs

Expand Down Expand Up @@ -63,20 +74,80 @@ check_headers:
@echo "Checking file headers"
@python test/verify_boilerplate.py

# Integration tests
.PHONY: test_integration
test_integration:
bundle install
bundle exec kitchen create
bundle exec kitchen converge
bundle exec kitchen converge
bundle exec kitchen verify
bundle exec kitchen destroy

.PHONY: generate_docs
generate_docs:
@source test/make.sh && generate_docs

# Integration tests

.PHONY: regional_test_integration
regional_test_integration:
./test/integration/gcloud/run.sh regional

.PHONY: zonal_test_integration
zonal_test_integration:
./test/integration/gcloud/run.sh zonal

.PHONY: test_integration
test_integration: regional_test_integration zonal_test_integration
@echo "Running tests for regional and zonal clusters"
# Versioning
.PHONY: version
version:
@source helpers/version-repo.sh

# Build Docker
.PHONY: docker_build_terraform
docker_build_terraform:
docker build -f build/docker/terraform/Dockerfile \
--build-arg BUILD_TERRAFORM_VERSION=${BUILD_TERRAFORM_VERSION} \
--build-arg BUILD_CLOUD_SDK_VERSION=${BUILD_CLOUD_SDK_VERSION} \
--build-arg BUILD_PROVIDER_GOOGLE_VERSION=${BUILD_PROVIDER_GOOGLE_VERSION} \
--build-arg BUILD_PROVIDER_GSUITE_VERSION=${BUILD_PROVIDER_GSUITE_VERSION} \
--build-arg CREDENTIALS_FILE=${CREDENTIALS_FILE} \
-t ${DOCKER_IMAGE_TERRAFORM}:${DOCKER_TAG_TERRAFORM} .

.PHONY: docker_build_kitchen_terraform
docker_build_kitchen_terraform:
docker build -f build/docker/kitchen_terraform/Dockerfile \
--build-arg BUILD_TERRAFORM_IMAGE="${DOCKER_IMAGE_TERRAFORM}:${DOCKER_TAG_TERRAFORM}" \
--build-arg BUILD_RUBY_VERSION="${BUILD_RUBY_VERSION}" \
--build-arg CREDENTIALS_FILE="${CREDENTIALS_FILE}" \
-t ${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} .

# Run docker
.PHONY: docker_run
docker_run:
docker run --rm -it \
-v $(CURDIR):/cftk/workdir \
${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} \
/bin/bash

.PHONY: docker_create
docker_create: docker_build_terraform docker_build_kitchen_terraform
docker run --rm -it \
-v $(CURDIR):/cftk/workdir \
${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} \
/bin/bash -c "kitchen create"

.PHONY: docker_converge
docker_converge:
docker run --rm -it \
-v $(CURDIR):/cftk/workdir \
${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} \
/bin/bash -c "kitchen converge && kitchen converge"

.PHONY: docker_verify
docker_verify:
docker run --rm -it \
-v $(CURDIR):/cftk/workdir \
${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} \
/bin/bash -c "kitchen verify"

.PHONY: docker_destroy
docker_destroy:
docker run --rm -it \
-v $(CURDIR):/cftk/workdir \
${DOCKER_IMAGE_KITCHEN_TERRAFORM}:${DOCKER_TAG_KITCHEN_TERRAFORM} \
/bin/bash -c "kitchen destroy"

.PHONY: test_integration_docker
test_integration_docker: docker_create docker_converge docker_verify docker_destroy
@echo "Running test-kitchen tests in docker"
90 changes: 61 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Then perform the following commands on the root folder:
| ip_range_pods | The secondary ip range to use for pods | string | - | yes |
| ip_range_services | The secondary ip range to use for pods | string | - | yes |
| kubernetes_dashboard | Enable kubernetes dashboard addon | string | `false` | no |
| kubernetes_version | The Kubernetes version of the masters. If set to 'latest' it will pull latest available version in the selected region. | string | `1.10.6-gke.2` | no |
| kubernetes_version | The Kubernetes version of the masters. If set to 'latest' it will pull latest available version in the selected region. | string | `latest` | no |
| logging_service | The logging service that the cluster should write logs to. Available options include logging.googleapis.com, logging.googleapis.com/kubernetes (beta), and none | string | `logging.googleapis.com` | no |
| maintenance_start_time | Time window specified for daily maintenance operations in RFC3339 format | string | `05:00` | no |
| master_authorized_networks_config | The desired configuration options for master authorized networks. Omit the nested cidr_blocks attribute to disallow external access (except the cluster node IPs, which GKE automatically whitelists)<br><br> ### example format ### master_authorized_networks_config = [{ cidr_blocks = [{ cidr_block = "10.0.0.0/8" display_name = "example_network" }], }] | list | `<list>` | no |
Expand All @@ -115,6 +115,7 @@ Then perform the following commands on the root folder:
| project_id | The project ID to host the cluster in (required) | string | - | yes |
| region | The region to host the cluster in (required) | string | - | yes |
| regional | Whether is a regional cluster (zonal cluster if set false. WARNING: changing this after cluster creation is destructive!) | string | `true` | no |
| service_account | The service account to default running nodes as if not overridden in `node_pools`. Defaults to the compute engine default service account | string | `` | no |
| stub_domains | Map of stub domains and their resolvers to forward DNS queries for a certain domain to an external DNS server | map | `<map>` | no |
| subnetwork | The subnetwork to host the cluster in (required) | string | - | yes |
| zones | The zones to host the cluster in (optional if regional cluster / required if zonal) | list | `<list>` | no |
Expand Down Expand Up @@ -163,12 +164,12 @@ The [project factory](https://github.com/terraform-google-modules/terraform-goog
- [terraform-provider-google](https://github.com/terraform-providers/terraform-provider-google) plugin v1.8.0

### Configure a Service Account
In order to execute this module you must have a Service Account with the following:

#### IAM Roles
The service account with the following roles:
- roles/compute.viewer on the project
- roles/container.clusterAdmin on the project
In order to execute this module you must have a Service Account with the
following project roles:
- roles/compute.viewer
- roles/container.clusterAdmin
- roles/container.developer
- roles/iam.serviceAccountUser

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:
Expand Down Expand Up @@ -199,7 +200,6 @@ The project has the following folders and files:
### Requirements
- [bundler](https://github.com/bundler/bundler)
- [gcloud](https://cloud.google.com/sdk/install)
- [jq](https://stedolan.github.io/jq/) 1.5
- [terraform-docs](https://github.com/segmentio/terraform-docs/releases) 0.3.0

### Autogeneration of documentation from .tf files
Expand All @@ -209,27 +209,59 @@ make generate_docs
```

### Integration test
#### Terraform integration tests
The integration tests for this module leverage [kitchen-terraform](https://github.com/newcontext-oss/kitchen-terraform) and [kitchen-inspec](https://github.com/inspec/kitchen-inspec).

The tests will do the following:
- Perform `bundle install` command
- Installs `kitchen-terraform` and `kitchen-inspec` gems
- Perform `kitchen create` command
- Performs a `terraform init`
- Perform `kitchen converge` command
- Performs a `terraform apply -auto-approve`
- Perform `kitchen validate` command
- Performs inspec tests.
- Shell out to `gcloud` to validate expected resources in GCP.
- Shell out to `kubectl` to validate expected resource in Kubernetes.
- Shell out to `terraform` to validate outputs.
- Permos `kitchen destroy` command
- Performs a `terraform destroy -force`

You can use the following command to run the integration test in the root folder

`make test_integration`

Integration tests are run though [test-kitchen](https://github.com/test-kitchen/test-kitchen), [kitchen-terraform](https://github.com/newcontext-oss/kitchen-terraform), and [InSpec](https://github.com/inspec/inspec).

Six test-kitchen instances are defined:

- `deploy_service`
- `node_pool`
- `shared_vpc`
- `simple_regional`
- `simple_zonal`
- `stub_domains`

The test-kitchen instances in `test/fixtures/` wrap identically-named examples in the `examples/` directory.

#### Setup

1. Configure the [test fixtures](#test-configuration)
2. Download a Service Account key with the necessary permissions and put it in the module's root directory with the name `credentials.json`.
3. Build the Docker containers for testing:

```
CREDENTIALS_FILE="credentials.json" make docker_build_terraform
CREDENTIALS_FILE="credentials.json" make docker_build_kitchen_terraform
```
4. Run the testing container in interactive mode:

```
make docker_run
```

The module root directory will be loaded into the Docker container at `/cftk/workdir/`.
5. Run kitchen-terraform to test the infrastructure:

1. `kitchen create` creates Terraform state and downloads modules, if applicable.
2. `kitchen converge` creates the underlying resources. Run `kitchen converge <INSTANCE_NAME>` to create resources for a specific test case.
3. `kitchen verify` tests the created infrastructure. Run `kitchen verify <INSTANCE_NAME>` to run a specific test case.
4. `kitchen destroy` tears down the underlying resources created by `kitchen converge`. Run `kitchen destroy <INSTANCE_NAME>` to tear down resources for a specific test case.

Alternatively, you can simply run `CREDENTIALS_FILE="credentials.json" make test_integration_docker` to run all the test steps non-interactively.

#### Test configuration

Each test-kitchen instance is configured with a `variables.tfvars` file in the test fixture directory, e.g. `test/fixtures/node_pool/terraform.tfvars`.
For convenience, since all of the variables are project-specific, these files have been symlinked to `test/fixtures/shared/terraform.tfvars`.
morgante marked this conversation as resolved.
Show resolved Hide resolved
Similarly, each test fixture has a `variables.tf` to define these variables, and an `outputs.tf` to facilitate providing necessary information for `inspec` to locate and query against created resources.

Each test-kitchen instance creates a GCP Network and Subnetwork fixture to house resources, and may create any other necessary fixture data as needed.

### Autogeneration of documentation from .tf files
Run
```
make generate_docs
```

### Linting
The makefile in this project will lint or sometimes just format any shell,
Expand Down
Loading