Skip to content

Commit

Permalink
feat: add TF cloudbuilder blueprint (#154)
Browse files Browse the repository at this point in the history
* feat: add TF cloudbuilder blueprint

* add example

* add tests

* fix img

* fmt

* rel arch path

* more fmt

* ci

* bump devtools

* retry during e2e test
  • Loading branch information
bharathkkb authored May 27, 2022
1 parent 6a7463b commit 34120e5
Show file tree
Hide file tree
Showing 24 changed files with 1,692 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Make will use bash instead of sh
SHELL := /usr/bin/env bash

DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.0
DOCKER_TAG_VERSION_DEVELOPER_TOOLS := 1.4
DOCKER_IMAGE_DEVELOPER_TOOLS := cft/developer-tools
REGISTRY_URL := gcr.io/cloud-foundation-cicd

Expand Down
22 changes: 21 additions & 1 deletion build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,29 @@ steps:
- id: destroy-simple-folder
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'source /usr/local/bin/task_helper_functions.sh && kitchen_do destroy simple-folder-default']
- id: init-tfbuilder
waitFor:
- prepare
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilder --stage init --verbose']
- id: apply-tfbuilder
waitFor:
- init-tfbuilder
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilder --stage apply --verbose']
- id: verify-tfbuilder
waitFor:
- apply-tfbuilder
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilder --stage verify --verbose']
- id: teardown-tfbuilder
waitFor:
- verify-tfbuilder
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilder --stage teardown --verbose']
tags:
- 'ci'
- 'integration'
substitutions:
_DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools'
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.0'
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.4'
2 changes: 1 addition & 1 deletion build/lint.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ tags:
- 'lint'
substitutions:
_DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools'
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.0'
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.4'
39 changes: 39 additions & 0 deletions examples/tf_cloudbuild_builder_simple/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2022 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
#
# https://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.

FROM gcr.io/cloud-builders/gcloud-slim

# Use ARG so that values can be overriden by user/cloudbuild
ARG TERRAFORM_VERSION=1.1.0

ENV ENV_TERRAFORM_VERSION=$TERRAFORM_VERSION

RUN apt-get update && \
/builder/google-cloud-sdk/bin/gcloud -q components install alpha beta && \
apt-get -y install curl jq unzip git ca-certificates gnupg && \
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip --output terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip && \
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_SHA256SUMS.sig --output terraform_SHA256SUMS.sig && \
curl https://releases.hashicorp.com/terraform/${ENV_TERRAFORM_VERSION}/terraform_${ENV_TERRAFORM_VERSION}_SHA256SUMS --output terraform_SHA256SUMS && \
curl https://keybase.io/hashicorp/pgp_keys.asc --output pgp_keys.asc && \
gpg --import pgp_keys.asc && \
gpg --verify terraform_SHA256SUMS.sig terraform_SHA256SUMS && \
grep terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip terraform_SHA256SUMS | shasum --algorithm 256 --check && \
unzip terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip -d /builder/terraform && \
rm -f terraform_${ENV_TERRAFORM_VERSION}_linux_amd64.zip terraform_SHA256SUMS && \
apt-get --purge -y autoremove && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

ENV PATH=/builder/terraform/:$PATH
ENTRYPOINT ["terraform"]
23 changes: 23 additions & 0 deletions examples/tf_cloudbuild_builder_simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Overview

This example demonstrates the simplest usage of the [tf_cloudbuild_builder](../../modules/tf_cloudbuild_builder/) module.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| project\_id | n/a | `string` | `"test-builder-workflow-4"` | no |

## Outputs

| Name | Description |
|------|-------------|
| artifact\_repo | GAR Repo created to store TF Cloud Builder images |
| cloudbuild\_trigger\_id | Trigger used for building new TF Builder |
| csr\_repo\_url | CSR repo for storing cloudbuilder Dockerfile |
| project\_id | n/a |
| scheduler\_id | Scheduler ID for periodically triggering TF Builder build Workflow |
| workflow\_id | Workflow ID for triggering new TF Builder build |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
33 changes: 33 additions & 0 deletions examples/tf_cloudbuild_builder_simple/apis.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2022 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.
*/

module "enabled_google_apis" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 11.3"

project_id = var.project_id
disable_services_on_destroy = false

activate_apis = [
"iam.googleapis.com",
"compute.googleapis.com",
"sourcerepo.googleapis.com",
"workflows.googleapis.com",
"artifactregistry.googleapis.com",
"cloudbuild.googleapis.com",
"cloudscheduler.googleapis.com"
]
}
40 changes: 40 additions & 0 deletions examples/tf_cloudbuild_builder_simple/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright 2022 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.
*/

module "cloudbuilder" {
source = "../../modules/tf_cloudbuild_builder"

project_id = module.enabled_google_apis.project_id
dockerfile_repo_uri = google_sourcerepo_repository.builder_dockerfile_repo.url
# allow logs bucket to be destroyed
cb_logs_bucket_force_destroy = true
}

# CSR for storing Dockerfile
resource "google_sourcerepo_repository" "builder_dockerfile_repo" {
project = module.enabled_google_apis.project_id
name = "tf-cloudbuilder"
}

# Bootstrap CSR with Dockerfile
module "bootstrap_csr_repo" {
source = "terraform-google-modules/gcloud/google"
version = "~> 3.1.0"
upgrade = false

create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh"
create_cmd_body = "${module.enabled_google_apis.project_id} ${split("/", google_sourcerepo_repository.builder_dockerfile_repo.id)[3]} ${path.module}/Dockerfile"
}
44 changes: 44 additions & 0 deletions examples/tf_cloudbuild_builder_simple/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright 2022 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.
*/

output "artifact_repo" {
description = "GAR Repo created to store TF Cloud Builder images"
value = module.cloudbuilder.artifact_repo
}

output "workflow_id" {
description = "Workflow ID for triggering new TF Builder build"
value = module.cloudbuilder.workflow_id
}

output "scheduler_id" {
description = "Scheduler ID for periodically triggering TF Builder build Workflow"
value = module.cloudbuilder.scheduler_id
}

output "cloudbuild_trigger_id" {
description = "Trigger used for building new TF Builder"
value = module.cloudbuilder.cloudbuild_trigger_id
}

output "csr_repo_url" {
description = "CSR repo for storing cloudbuilder Dockerfile"
value = google_sourcerepo_repository.builder_dockerfile_repo.url
}

output "project_id" {
value = var.project_id
}
42 changes: 42 additions & 0 deletions examples/tf_cloudbuild_builder_simple/scripts/push-to-repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Copyright 2022 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.


set -ex

if [ "$#" -lt 3 ]; then
>&2 echo "Not all expected arguments set."
exit 1
fi

CSR_PROJECT_ID=$1
CSR_NAME=$2
DOCKERFILE_PATH=$3

# create temp dir, cleanup at exit
tmp_dir=$(mktemp -d)
# # shellcheck disable=SC2064
# trap "rm -rf $tmp_dir" EXIT
gcloud source repos clone "${CSR_NAME}" "${tmp_dir}" --project "${CSR_PROJECT_ID}"
cp "${DOCKERFILE_PATH}" "${tmp_dir}"
pushd "${tmp_dir}"
git config credential.helper gcloud.sh
git config init.defaultBranch main
git config user.email "[email protected]"
git config user.name "TF Robot"
git checkout main || git checkout -b main
git add Dockerfile
git commit -m "init tf dockerfile"
git push origin main -f
19 changes: 19 additions & 0 deletions examples/tf_cloudbuild_builder_simple/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright 2022 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.
*/

variable "project_id" {
default = "test-builder-workflow-4"
}
99 changes: 99 additions & 0 deletions modules/tf_cloudbuild_builder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
## Overview

TF Cloud Builder blueprint automates the creation and management of Terraform [Cloud Build Builder/Runner](https://cloud.google.com/build/docs/cloud-builders) images. These images are used in the context of build steps for automating Terraform deployments using Cloud Build.

## Usage

Basic usage of this module is as follows:

```hcl
module "tfbuilder" {
source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_builder"
version = "~> 5.0"
project_id = module.enabled_google_apis.project_id
dockerfile_repo_uri = "https://github.com/org/repo"
}
```

Sample Dockerfile and functional examples are included in the [examples](../../examples/) directory.

## Resources created

This module creates:
- Cloud Workflow for querying upstream Terraform releases, existing TF Builder images and triggering a Cloud Build build if an image does not exist for the latest Terraform release
- Cloud Build trigger with an inline build configuration for building and pushing a Dockerfile to an Artifact repository
- Artifact Registry Repository for storing TF Builder images
- Cloud Scheduler job for periodically triggering the Workflow

![](./assets/arch.png)

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| cb\_logs\_bucket\_force\_destroy | When deleting the bucket for storing CloudBuild logs, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no |
| cloudbuild\_sa | Custom SA email to be used by the CloudBuild trigger. Defaults to being created if empty. | `string` | `""` | no |
| dockerfile\_repo\_dir | The directory inside the repo where the Dockerfile is located. If empty defaults to repo root. | `string` | `""` | no |
| dockerfile\_repo\_ref | The branch or tag to use. Use refs/heads/branchname for branches or refs/tags/tagname for tags. | `string` | `"refs/heads/main"` | no |
| dockerfile\_repo\_type | Type of repo | `string` | `"CLOUD_SOURCE_REPOSITORIES"` | no |
| dockerfile\_repo\_uri | The URI of the repo where the Dockerfile for Terraform builder is stored | `string` | n/a | yes |
| gar\_repo\_location | Name of the location for the Google Artifact Repository. | `string` | `"us"` | no |
| gar\_repo\_name | Name of the Google Artifact Repository where the Terraform builder images are stored. | `string` | `"tf-runners"` | no |
| image\_name | Name of the image for the Terraform builder. | `string` | `"terraform"` | no |
| project\_id | GCP project for Cloud Build trigger,workflow and scheduler. | `string` | n/a | yes |
| trigger\_name | Name of the Cloud Build trigger building the Terraform builder. | `string` | `"tf-cloud-builder-build"` | no |
| workflow\_name | Name of the workflow managing builds. | `string` | `"terraform-runner-workflow"` | no |
| workflow\_region | The region of the workflow. | `string` | `"us-central1"` | no |
| workflow\_sa | Custom SA email to be used by the workflow. Defaults to being created if empty. | `string` | `""` | no |
| workflow\_schedule | The workflow frequency, in cron syntax | `string` | `"0 8 * * *"` | no |

## Outputs

| Name | Description |
|------|-------------|
| artifact\_repo | GAR Repo created to store TF Cloud Builder images |
| cloudbuild\_sa | SA used by Cloud Build trigger |
| cloudbuild\_trigger\_id | Trigger used for building new TF Builder |
| scheduler\_id | Scheduler ID for periodically triggering TF Builder build Workflow |
| workflow\_id | Workflow ID for triggering new TF Builder build |
| workflow\_sa | SA used by Workflow for triggering new TF Builder build |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## Requirements

### Software

- [Terraform](https://www.terraform.io/downloads.html) >= 0.13.0
- [terraform-provider-google] plugin >= 3.50.x

### Permissions

- `roles/artifactregistry.admin`
- `roles/cloudscheduler.admin`
- `roles/cloudbuild.builds.editor`
- `roles/workflows.admin`
- `roles/iam.serviceAccountAdmin`
- `roles/iam.securityAdmin`

### APIs

A project with the following APIs enabled must be used to host the
resources of this module:

```hcl
"iam.googleapis.com",
"compute.googleapis.com",
"sourcerepo.googleapis.com",
"workflows.googleapis.com",
"artifactregistry.googleapis.com",
"cloudbuild.googleapis.com",
"cloudscheduler.googleapis.com"
```

## Contributing

Refer to the [contribution guidelines](../../CONTRIBUTING.md) for
information on contributing to this module.
Binary file added modules/tf_cloudbuild_builder/assets/arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 34120e5

Please sign in to comment.