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

feat: create Cloudbuild Source submodule #167

Merged
merged 18 commits into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
24 changes: 24 additions & 0 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,28 @@ 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-tfcore
waitFor:
- prepare
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildCoreSimple --stage init --verbose']
- id: apply-tfcore
waitFor:
- init-tfcore
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildCoreSimple --stage apply --verbose']
- id: verify-tfcore
waitFor:
- apply-tfcore
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildCoreSimple --stage verify --verbose']
- id: teardown-tfcore
waitFor:
- verify-tfcore
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildCoreSimple --stage teardown --verbose']

- id: init-tfbuilder
waitFor:
- prepare
Expand All @@ -93,6 +115,7 @@ steps:
- 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']

- id: init-tfworkspace
waitFor:
- prepare
Expand All @@ -113,6 +136,7 @@ steps:
- verify-tfworkspace
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildWorkspaceSimple --stage teardown --verbose']

tags:
- 'ci'
- 'integration'
Expand Down
24 changes: 24 additions & 0 deletions examples/tf_cloudbuild_core_simple/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Overview

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

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| billing\_account | The ID of the billing account to associate projects with. | `string` | n/a | yes |
| group\_org\_admins | Google Group for GCP Organization Administrators | `string` | n/a | yes |
| org\_id | GCP Organization ID | `string` | n/a | yes |
| parent\_folder | The bootstrap parent folder | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| cloudbuild\_project\_id | Project where CloudBuild configuration and terraform container image will reside. |
| csr\_repos | List of Cloud Source Repos created by the module. |
| gcs\_bucket\_cloudbuild\_artifacts | Bucket used to store Cloud/Build artifacts in CloudBuild project. |
| gcs\_cloudbuild\_default\_bucket | Bucket used to store temporary files in CloudBuild project. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
29 changes: 29 additions & 0 deletions examples/tf_cloudbuild_core_simple/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* 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 "tf_core" {
source = "../../modules/tf_cloudbuild_core"

org_id = var.org_id
folder_id = var.parent_folder
billing_account = var.billing_account
group_org_admins = var.group_org_admins
project_prefix = "cft-test-core"
buckets_force_destroy = true
}



daniel-cit marked this conversation as resolved.
Show resolved Hide resolved
35 changes: 35 additions & 0 deletions examples/tf_cloudbuild_core_simple/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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 "cloudbuild_project_id" {
description = "Project where CloudBuild configuration and terraform container image will reside."
value = module.tf_core.cloudbuild_project_id
}

output "gcs_bucket_cloudbuild_artifacts" {
description = "Bucket used to store Cloud/Build artifacts in CloudBuild project."
value = module.tf_core.gcs_bucket_cloudbuild_artifacts
}

output "csr_repos" {
description = "List of Cloud Source Repos created by the module."
value = module.tf_core.csr_repos
}

output "gcs_cloudbuild_default_bucket" {
description = "Bucket used to store temporary files in CloudBuild project."
value = module.tf_core.gcs_cloudbuild_default_bucket
}
35 changes: 35 additions & 0 deletions examples/tf_cloudbuild_core_simple/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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 "org_id" {
description = "GCP Organization ID"
type = string
}

variable "parent_folder" {
description = "The bootstrap parent folder"
type = string
}

variable "billing_account" {
description = "The ID of the billing account to associate projects with."
type = string
}

variable "group_org_admins" {
description = "Google Group for GCP Organization Administrators"
type = string
}
75 changes: 75 additions & 0 deletions modules/tf_cloudbuild_core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## Overview

## Usage

Basic usage of this module is as follows:

```hcl
module "tf-cloudbuild-core" {
daniel-cit marked this conversation as resolved.
Show resolved Hide resolved
source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_core"
version = "~> 6.1"

org_id = var.org_id
billing_account = var.billing_account
group_org_admins = var.group_org_admins
}
```

Functional examples are included in the [examples](../../examples/) directory.

## Resources created

This module creates:

- Project for Cloud Build.
- Default Cloud Build bucket.
- Bucket for Cloud Build artifacts.
- Set of Cloud Source Repos.

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| activate\_apis | List of APIs to enable in the Cloudbuild project. | `list(string)` | <pre>[<br> "serviceusage.googleapis.com",<br> "servicenetworking.googleapis.com",<br> "compute.googleapis.com",<br> "logging.googleapis.com",<br> "bigquery.googleapis.com",<br> "cloudresourcemanager.googleapis.com",<br> "cloudbilling.googleapis.com",<br> "iam.googleapis.com",<br> "admin.googleapis.com",<br> "appengine.googleapis.com",<br> "storage-api.googleapis.com"<br>]</pre> | no |
| billing\_account | The ID of the billing account to associate projects with. | `string` | n/a | yes |
| buckets\_force\_destroy | When deleting CloudBuild buckets, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no |
| cloud\_source\_repos | List of Cloud Source Repos to create with CloudBuild triggers. | `list(string)` | <pre>[<br> "gcp-policies",<br> "gcp-org",<br> "gcp-envs",<br> "gcp-networks",<br> "gcp-projects"<br>]</pre> | no |
| create\_cloud\_source\_repos | If shared Cloud Source Repos should be created. | `bool` | `true` | no |
| folder\_id | The ID of a folder to host this project | `string` | `""` | no |
| group\_org\_admins | Google Group for GCP Organization Administrators | `string` | n/a | yes |
| location | Location for build artifacts bucket | `string` | `"us-central1"` | no |
| org\_id | GCP Organization ID | `string` | n/a | yes |
| project\_id | Custom project ID to use for project created. | `string` | `""` | no |
| project\_labels | Labels to apply to the project. | `map(string)` | `{}` | no |
| project\_prefix | Name prefix to use for projects created. | `string` | `"cft"` | no |
| storage\_bucket\_labels | Labels to apply to the storage bucket. | `map(string)` | `{}` | no |
| use\_random\_suffix | Appends a 4 character random suffix to project ID. | `bool` | `true` | no |

## Outputs

| Name | Description |
|------|-------------|
| cloudbuild\_project\_id | Project where CloudBuild configuration and terraform container image will reside. |
| csr\_repos | List of Cloud Source Repos created by the module. |
| gcs\_bucket\_cloudbuild\_artifacts | Bucket used to store Cloud/Build artifacts in CloudBuild project. |
| gcs\_cloudbuild\_default\_bucket | Bucket used to store temporary files in CloudBuild project. |

<!-- 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/resourcemanager.projectCreator`
- `roles/billing.user`

## Contributing

Refer to the [contribution guidelines](../../CONTRIBUTING.md) for
information on contributing to this module.
108 changes: 108 additions & 0 deletions modules/tf_cloudbuild_core/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* 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.
*/

locals {
cloudbuild_project_id = var.project_id != "" ? var.project_id : format("%s-%s", var.project_prefix, "cloudbuild")

cloudbuild_apis = [
"cloudbuild.googleapis.com",
"sourcerepo.googleapis.com",
"storage-api.googleapis.com",
"iam.googleapis.com",
"cloudresourcemanager.googleapis.com",
"cloudbilling.googleapis.com"
]

activate_apis = distinct(concat(var.activate_apis, local.cloudbuild_apis))
}

resource "random_id" "suffix" {
byte_length = 2
}

module "cloudbuild_project" {
source = "terraform-google-modules/project-factory/google"
version = "~> 13.0"

name = local.cloudbuild_project_id
random_project_id = var.use_random_suffix
disable_services_on_destroy = false
folder_id = var.folder_id
org_id = var.org_id
billing_account = var.billing_account
activate_apis = local.activate_apis
labels = var.project_labels
}

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

name = "${module.cloudbuild_project.project_id}_cloudbuild"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we use this bucket for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the default cloud build bucket, the one used for source staging.

if not created here it will be created in the fist time a build is run and it will be always created in the "US" location, independent of where the bootstrap infrastructure is been created.

same as terraform-google-modules/terraform-example-foundation#666

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, lets add a comment here with any upstream docs if any.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added an explanation
@bharathkkb could you PTAL?

project_id = module.cloudbuild_project.project_id
location = var.location
labels = var.storage_bucket_labels
force_destroy = var.buckets_force_destroy
}

module "cloudbuild_artifacts" {
daniel-cit marked this conversation as resolved.
Show resolved Hide resolved
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "~> 3.2"

name = "${var.project_prefix}-cloudbuild-artifacts-${random_id.suffix.hex}"
project_id = module.cloudbuild_project.project_id
location = var.location
labels = var.storage_bucket_labels
force_destroy = var.buckets_force_destroy
}

resource "google_sourcerepo_repository" "gcp_repo" {
for_each = var.create_cloud_source_repos ? toset(var.cloud_source_repos) : []

project = module.cloudbuild_project.project_id
name = each.value
}

resource "google_project_iam_member" "org_admins_cloudbuild_editor" {
project = module.cloudbuild_project.project_id
role = "roles/cloudbuild.builds.editor"
member = "group:${var.group_org_admins}"
}

resource "google_project_iam_member" "org_admins_cloudbuild_viewer" {
project = module.cloudbuild_project.project_id
role = "roles/viewer"
member = "group:${var.group_org_admins}"
}

resource "google_project_iam_member" "org_admins_source_repo_admin" {
count = var.create_cloud_source_repos ? 1 : 0
project = module.cloudbuild_project.project_id
role = "roles/source.admin"
member = "group:${var.group_org_admins}"
}

resource "google_storage_bucket_iam_member" "cloudbuild_artifacts_iam" {
bucket = module.cloudbuild_artifacts.bucket.name
role = "roles/storage.admin"
member = "serviceAccount:${module.cloudbuild_project.project_number}@cloudbuild.gserviceaccount.com"
}

resource "google_storage_bucket_iam_member" "cloudbuild_iam" {
bucket = module.cloudbuild_bucket.bucket.name
role = "roles/storage.admin"
member = "serviceAccount:${module.cloudbuild_project.project_number}@cloudbuild.gserviceaccount.com"
}
Loading