Skip to content

Commit

Permalink
feat: add artifacts bucket to tf workspace module (#170)
Browse files Browse the repository at this point in the history
* add artifacts bucket to tf workspace

* fix test for artifacts location
  • Loading branch information
daniel-cit committed Jul 14, 2022
1 parent 45830b7 commit fceee53
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 13 deletions.
3 changes: 2 additions & 1 deletion examples/tf_cloudbuild_workspace_simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ This example demonstrates the simplest usage of the [tf_cloudbuild_workspace](..

| Name | Description |
|------|-------------|
| artifacts\_bucket | Bucket for storing TF plans |
| cloudbuild\_apply\_trigger\_id | Trigger used for running TF apply |
| cloudbuild\_plan\_trigger\_id | Trigger used for running TF plan |
| cloudbuild\_sa | SA used by Cloud Build triggers |
| csr\_repo\_url | CSR repo for storing TF configs |
| logs\_bucket | Bucket for storing TF logs/plans |
| logs\_bucket | Bucket for storing TF logs |
| project\_id | n/a |
| state\_bucket | Bucket for storing TF state |

Expand Down
7 changes: 6 additions & 1 deletion examples/tf_cloudbuild_workspace_simple/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,15 @@ output "state_bucket" {
}

output "logs_bucket" {
description = "Bucket for storing TF logs/plans"
description = "Bucket for storing TF logs"
value = module.tf_workspace.logs_bucket
}

output "artifacts_bucket" {
description = "Bucket for storing TF plans"
value = module.tf_workspace.artifacts_bucket
}

output "csr_repo_url" {
description = "CSR repo for storing TF configs"
value = google_sourcerepo_repository.tf_config_repo.url
Expand Down
5 changes: 3 additions & 2 deletions modules/tf_cloudbuild_workspace/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Functional examples are included in the [examples](../../examples/) directory.
This module creates:
- Two Cloud Build triggers with an inline build configuration for planning and applying Terraform configuration. Optionally custom in repo build configs can be specified.
- Optional custom Service Account and roles for that SA used by Cloud Build triggers.
- GCS buckets for storing Terraform state, logs and plans.
- GCS buckets for storing Terraform state, logs, and plans.

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

Expand Down Expand Up @@ -61,10 +61,11 @@ This module creates:

| Name | Description |
|------|-------------|
| artifacts\_bucket | Bucket for storing TF plans |
| cloudbuild\_apply\_trigger\_id | Trigger used for running TF apply |
| cloudbuild\_plan\_trigger\_id | Trigger used for running TF plan |
| cloudbuild\_sa | SA used by Cloud Build triggers |
| logs\_bucket | Bucket for storing TF logs/plans |
| logs\_bucket | Bucket for storing TF logs |
| state\_bucket | Bucket for storing TF state |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand Down
18 changes: 18 additions & 0 deletions modules/tf_cloudbuild_workspace/buckets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ locals {
state_bucket_self_link = var.create_state_bucket ? module.state_bucket[0].bucket.self_link : var.state_bucket_self_link
state_bucket_name = split("/", local.state_bucket_self_link)[length(split("/", local.state_bucket_self_link)) - 1]
log_bucket_name = split("/", module.log_bucket.bucket.self_link)[length(split("/", module.log_bucket.bucket.self_link)) - 1]
artifacts_bucket_name = split("/", module.artifacts_bucket.bucket.self_link)[length(split("/", module.artifacts_bucket.bucket.self_link)) - 1]
}


module "artifacts_bucket" {
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "~> 3.2"

name = "${local.default_prefix}-build-artifacts-${var.project_id}"
project_id = var.project_id
location = var.location
force_destroy = var.buckets_force_destroy
}

resource "google_storage_bucket_iam_member" "artifacts_admin" {
bucket = module.artifacts_bucket.bucket.self_link
role = "roles/storage.admin"
member = "serviceAccount:${local.cloudbuild_sa_email}"
}

module "log_bucket" {
Expand Down
9 changes: 5 additions & 4 deletions modules/tf_cloudbuild_workspace/cb.tf
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ locals {

# default substitutions
default_subst = {
"_TF_SA_EMAIL" = local.cloudbuild_sa_email,
"_STATE_BUCKET_NAME" = local.state_bucket_name,
"_LOG_BUCKET_NAME" = local.log_bucket_name,
"_TF_SA_EMAIL" = local.cloudbuild_sa_email,
"_STATE_BUCKET_NAME" = local.state_bucket_name,
"_LOG_BUCKET_NAME" = local.log_bucket_name,
"_ARTIFACT_BUCKET_NAME" = local.artifacts_bucket_name,
}
}

Expand Down Expand Up @@ -118,7 +119,7 @@ resource "google_cloudbuild_trigger" "triggers" {
# upload tfplan artifacts per build
artifacts {
objects {
location = join("/", [module.log_bucket.bucket.url, each.key, "$BUILD_ID"])
location = join("/", [module.artifacts_bucket.bucket.url, each.key, "$BUILD_ID"])
paths = [join("/", compact([var.tf_repo_dir, "*.tfplan"]))]
}
}
Expand Down
7 changes: 6 additions & 1 deletion modules/tf_cloudbuild_workspace/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ output "state_bucket" {
}

output "logs_bucket" {
description = "Bucket for storing TF logs/plans"
description = "Bucket for storing TF logs"
value = module.log_bucket.bucket.self_link
}

output "artifacts_bucket" {
description = "Bucket for storing TF plans"
value = module.artifacts_bucket.bucket.self_link
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ func TestTFCloudBuildWorkspaceSimple(t *testing.T) {
assert.Equal(fmt.Sprintf("projects/%s/serviceAccounts/tf-cb-tf-configs@%s.iam.gserviceaccount.com", projectID, projectID), cloudBuildOP.Get("serviceAccount").String(), "uses expected SA")
}

// state and log buckets
// artifacts, state and log buckets
logsBucket := lastElem(bpt.GetStringOutput("logs_bucket"), "/")
stateBucket := lastElem(bpt.GetStringOutput("state_bucket"), "/")
buckets := []string{logsBucket, stateBucket}
artifactsBucket := lastElem(bpt.GetStringOutput("artifacts_bucket"), "/")
buckets := []string{artifactsBucket, logsBucket, stateBucket}
for _, bucket := range buckets {
// we can't use runf since we need to override --format json with --json for alpha storage
bucketOP := gcloud.Run(t, fmt.Sprintf("alpha storage ls --buckets gs://%s", bucket), gcloud.WithCommonArgs([]string{"--project", projectID, "--json"})).Array()
Expand Down Expand Up @@ -113,10 +114,10 @@ func TestTFCloudBuildWorkspaceSimple(t *testing.T) {
switch branch {
case "plan":
assert.Equal(planTrigger, build.Get("buildTriggerId").String(), "was triggered by plan trigger")
assert.Contains(build.Get("artifacts.objects.location").String(), path.Join(logsBucket, "plan"), "artifacts were uploaded to the correct location")
assert.Contains(build.Get("artifacts.objects.location").String(), path.Join(artifactsBucket, "plan"), "artifacts were uploaded to the correct location")
case "main":
assert.Equal(applyTrigger, build.Get("buildTriggerId").String(), "was triggered by apply trigger")
assert.Contains(build.Get("artifacts.objects.location").String(), path.Join(logsBucket, "apply"), "artifacts were uploaded to the correct location")
assert.Contains(build.Get("artifacts.objects.location").String(), path.Join(artifactsBucket, "apply"), "artifacts were uploaded to the correct location")
}
}
})
Expand Down

0 comments on commit fceee53

Please sign in to comment.