diff --git a/README.md b/README.md index 89d5913f..fb303d9a 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ For the cloudbuild submodule, see the README [cloudbuild](./modules/cloudbuild). | org\_id | GCP Organization ID | `string` | n/a | yes | | org\_project\_creators | Additional list of members to have project creator role accross the organization. Prefix of group: user: or serviceAccount: is required. | `list(string)` | `[]` | no | | parent\_folder | GCP parent folder ID in the form folders/{id} | `string` | `""` | no | +| project\_auto\_create\_network | Create the default network for the project created. | `bool` | `false` | no | | project\_deletion\_policy | The deletion policy for the project created. | `string` | `"PREVENT"` | no | | project\_id | Custom project ID to use for project created. If not supplied, the default id is {project\_prefix}-seed-{random suffix}. | `string` | `""` | no | | project\_labels | Labels to apply to the project. | `map(string)` | `{}` | no | diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index 78fba45e..fa558c63 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -113,11 +113,6 @@ steps: - 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'] - id: apply-tfbuilder-github waitFor: @@ -131,12 +126,6 @@ steps: name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilderGitHub --stage verify --verbose'] secretEnv: ['IM_GITHUB_PAT'] -- id: teardown-tfbuilder-github - waitFor: - - verify-tfbuilder-github - name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' - args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilderGitHub --stage teardown --verbose'] - secretEnv: ['IM_GITHUB_PAT'] - id: apply-tfbuilder-gitlab waitFor: @@ -150,8 +139,26 @@ steps: name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilderGitLab --stage verify --verbose'] secretEnv: ['IM_GITLAB_PAT'] + +- id: teardown-tfbuilder + waitFor: + - verify-tfbuilder + - verify-tfbuilder-github + - verify-tfbuilder-gitlab + 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: teardown-tfbuilder-github + waitFor: + - verify-tfbuilder + - verify-tfbuilder-github + - verify-tfbuilder-gitlab + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilderGitHub --stage teardown --verbose'] + secretEnv: ['IM_GITHUB_PAT'] - id: teardown-tfbuilder-gitlab waitFor: + - verify-tfbuilder + - verify-tfbuilder-github - verify-tfbuilder-gitlab name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' args: ['/bin/bash', '-c', 'cft test run TestTFCloudBuildBuilderGitLab --stage teardown --verbose'] diff --git a/examples/cloudbuild_repo_connection_github/README.md b/examples/cloudbuild_repo_connection_github/README.md index 9eb9108d..84df1dbd 100644 --- a/examples/cloudbuild_repo_connection_github/README.md +++ b/examples/cloudbuild_repo_connection_github/README.md @@ -10,6 +10,8 @@ For GitHub connections you will need: - Install the [Cloud Build App](https://github.com/apps/google-cloud-build) on Github. - Create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) on Github with [scopes](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes) `repo` and `read:user` (or if app is installed in a organization use `read:org`). +- Create two [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the Cloud Build App and one for the Personal Access Token. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation for [Connect to a GitHub repository](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen). @@ -19,8 +21,8 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| github\_app\_id | The application ID for the Cloudbuild GitHub app. | `string` | n/a | yes | -| github\_pat | The personal access token for authenticating with GitHub. | `string` | n/a | yes | +| github\_app\_id\_secret\_id | The secret ID for the application ID for the Cloudbuild GitHub app. | `string` | n/a | yes | +| github\_pat\_secret\_id | The secret ID for the personal access token for authenticating with GitHub. | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_name | The name of the test repository. | `string` | n/a | yes | | repository\_url | The HTTPS clone URL of the repository, ending with .git. | `string` | n/a | yes | diff --git a/examples/cloudbuild_repo_connection_github/main.tf b/examples/cloudbuild_repo_connection_github/main.tf index 10eecfe5..0b666478 100644 --- a/examples/cloudbuild_repo_connection_github/main.tf +++ b/examples/cloudbuild_repo_connection_github/main.tf @@ -14,15 +14,15 @@ * limitations under the License. */ -module "github_connection" { +module "git_repo_connection" { source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" - version = "~> 9.0" + version = "~> 8.0" project_id = var.project_id - credential_config = { - credential_type = "GITHUBv2" - github_pat = var.github_pat - github_app_id = var.github_app_id + connection_config = { + connection_type = "GITHUBv2" + github_secret_id = var.github_pat_secret_id + github_app_id_secret_id = var.github_app_id_secret_id } cloud_build_repositories = { diff --git a/examples/cloudbuild_repo_connection_github/outputs.tf b/examples/cloudbuild_repo_connection_github/outputs.tf index 636e38bd..213dbe9c 100644 --- a/examples/cloudbuild_repo_connection_github/outputs.tf +++ b/examples/cloudbuild_repo_connection_github/outputs.tf @@ -16,11 +16,11 @@ output "cloud_build_repositories_2nd_gen_connection" { description = "Cloudbuild connection created." - value = module.github_connection.cloud_build_repositories_2nd_gen_connection + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_connection } output "cloud_build_repositories_2nd_gen_repositories" { description = "Created repositories." - value = module.github_connection.cloud_build_repositories_2nd_gen_repositories + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories } diff --git a/examples/cloudbuild_repo_connection_github/variables.tf b/examples/cloudbuild_repo_connection_github/variables.tf index bdd3bd08..b572d03d 100644 --- a/examples/cloudbuild_repo_connection_github/variables.tf +++ b/examples/cloudbuild_repo_connection_github/variables.tf @@ -19,13 +19,13 @@ variable "project_id" { type = string } -variable "github_pat" { - description = "The personal access token for authenticating with GitHub." +variable "github_pat_secret_id" { + description = "The secret ID for the personal access token for authenticating with GitHub." type = string } -variable "github_app_id" { - description = "The application ID for the Cloudbuild GitHub app." +variable "github_app_id_secret_id" { + description = "The secret ID for the application ID for the Cloudbuild GitHub app." type = string } @@ -38,4 +38,3 @@ variable "repository_name" { description = "The name of the test repository." type = string } - diff --git a/examples/cloudbuild_repo_connection_gitlab/README.md b/examples/cloudbuild_repo_connection_gitlab/README.md index 4a3dc5bf..2aea761e 100644 --- a/examples/cloudbuild_repo_connection_gitlab/README.md +++ b/examples/cloudbuild_repo_connection_gitlab/README.md @@ -4,7 +4,15 @@ The example will create Cloud Build repositories (2nd gen) using a Gitlab connec ## Gitlab Requirements for Cloud Build Connection -When using a Cloud Build repositories (2nd gen) GitLab repository, a Cloud Build connection to your repository provider will be needed. +When using a Cloud Build repositories (2nd gen) GitLab repository, a Cloud Build connection to your repository provider will be created. + +For GitLab connections you will need: + +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `api`. +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `read_api`. +- Create a [webhook](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) +- Create three [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the `api` token, one for the `read_api` token, and one for the `webhook`. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation: - [Connect to a GitLab host](https://cloud.google.com/build/docs/automating-builds/gitlab/connect-host-gitlab) @@ -15,8 +23,9 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| gitlab\_authorizer\_credential | Credential for GitLab authorizer | `string` | n/a | yes | -| gitlab\_read\_authorizer\_credential | Credential for GitLab read authorizer | `string` | n/a | yes | +| gitlab\_authorizer\_secret\_id | The secret ID for the credential for GitLab authorizer | `string` | n/a | yes | +| gitlab\_read\_authorizer\_secret\_id | The secret ID for the credential for GitLab read authorizer | `string` | n/a | yes | +| gitlab\_webhook\_secret\_id | The secret ID for the WebHook for GitLab | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_name | The name of the test repository. | `string` | n/a | yes | | repository\_url | The HTTPS clone URL of the repository, ending with .git. | `string` | n/a | yes | diff --git a/examples/cloudbuild_repo_connection_gitlab/main.tf b/examples/cloudbuild_repo_connection_gitlab/main.tf index 4a0a6bf3..b4871e82 100644 --- a/examples/cloudbuild_repo_connection_gitlab/main.tf +++ b/examples/cloudbuild_repo_connection_gitlab/main.tf @@ -14,14 +14,16 @@ * limitations under the License. */ -module "gitlab_connection" { - source = "../../modules/cloudbuild_repo_connection" +module "git_repo_connection" { + source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" + version = "~> 8.0" project_id = var.project_id - credential_config = { - credential_type = "GITLABv2" - gitlab_authorizer_credential = var.gitlab_authorizer_credential - gitlab_read_authorizer_credential = var.gitlab_read_authorizer_credential + connection_config = { + connection_type = "GITLABv2" + gitlab_authorizer_credential_secret_id = var.gitlab_authorizer_secret_id + gitlab_read_authorizer_credential_secret_id = var.gitlab_read_authorizer_secret_id + gitlab_webhook_secret_id = var.gitlab_webhook_secret_id } cloud_build_repositories = { diff --git a/examples/cloudbuild_repo_connection_gitlab/outputs.tf b/examples/cloudbuild_repo_connection_gitlab/outputs.tf index a1426a2d..2553e467 100644 --- a/examples/cloudbuild_repo_connection_gitlab/outputs.tf +++ b/examples/cloudbuild_repo_connection_gitlab/outputs.tf @@ -16,10 +16,10 @@ output "cloud_build_repositories_2nd_gen_connection" { description = "Cloudbuild connection created." - value = module.gitlab_connection.cloud_build_repositories_2nd_gen_connection + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_connection } output "cloud_build_repositories_2nd_gen_repositories" { description = "Created repositories." - value = module.gitlab_connection.cloud_build_repositories_2nd_gen_repositories + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories } diff --git a/examples/cloudbuild_repo_connection_gitlab/variables.tf b/examples/cloudbuild_repo_connection_gitlab/variables.tf index 01f26b81..ca236237 100644 --- a/examples/cloudbuild_repo_connection_gitlab/variables.tf +++ b/examples/cloudbuild_repo_connection_gitlab/variables.tf @@ -29,13 +29,17 @@ variable "repository_name" { type = string } -variable "gitlab_authorizer_credential" { - description = "Credential for GitLab authorizer" +variable "gitlab_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab authorizer" type = string } -variable "gitlab_read_authorizer_credential" { - description = "Credential for GitLab read authorizer" +variable "gitlab_read_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab read authorizer" type = string } +variable "gitlab_webhook_secret_id" { + description = "The secret ID for the WebHook for GitLab" + type = string +} diff --git a/examples/im_cloudbuild_workspace_github/main.tf b/examples/im_cloudbuild_workspace_github/main.tf index 03937f47..5679e3fe 100644 --- a/examples/im_cloudbuild_workspace_github/main.tf +++ b/examples/im_cloudbuild_workspace_github/main.tf @@ -15,7 +15,8 @@ */ module "im_workspace" { - source = "../../modules/im_cloudbuild_workspace" + source = "terraform-google-modules/bootstrap/google//modules/im_cloudbuild_workspace" + version = "~> 8.0" project_id = var.project_id deployment_id = "im-example-github-deployment" diff --git a/examples/im_cloudbuild_workspace_gitlab/main.tf b/examples/im_cloudbuild_workspace_gitlab/main.tf index f38bde4b..0d980e7e 100644 --- a/examples/im_cloudbuild_workspace_gitlab/main.tf +++ b/examples/im_cloudbuild_workspace_gitlab/main.tf @@ -15,7 +15,8 @@ */ module "im_workspace" { - source = "../../modules/im_cloudbuild_workspace" + source = "terraform-google-modules/bootstrap/google//modules/im_cloudbuild_workspace" + version = "~> 8.0" project_id = var.project_id deployment_id = "im-example-gitlab-deployment" diff --git a/examples/tf_cloudbuild_builder_simple/main.tf b/examples/tf_cloudbuild_builder_simple/main.tf index e4bd9ef5..a881819d 100644 --- a/examples/tf_cloudbuild_builder_simple/main.tf +++ b/examples/tf_cloudbuild_builder_simple/main.tf @@ -22,6 +22,7 @@ module "cloudbuilder" { dockerfile_repo_uri = google_sourcerepo_repository.builder_dockerfile_repo.url trigger_location = "us-central1" gar_repo_location = "us-central1" + build_timeout = "1200s" # allow logs bucket to be destroyed cb_logs_bucket_force_destroy = true } @@ -36,7 +37,9 @@ resource "google_sourcerepo_repository" "builder_dockerfile_repo" { module "bootstrap_csr_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" - upgrade = false + + upgrade = false + module_depends_on = [module.cloudbuilder] 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" diff --git a/examples/tf_cloudbuild_builder_simple_github/README.md b/examples/tf_cloudbuild_builder_simple_github/README.md index 4fafa298..d39adabe 100644 --- a/examples/tf_cloudbuild_builder_simple_github/README.md +++ b/examples/tf_cloudbuild_builder_simple_github/README.md @@ -6,6 +6,8 @@ For GitHub connections you will need: - Install the [Cloud Build App](https://github.com/apps/google-cloud-build) on Github. - Create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) on Github with [scopes](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes) `repo` and `read:user` (or if app is installed in a organization use `read:org`). +- Create two [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the Cloud Build App and one for the Personal Access Token. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation for [Connect to a GitHub repository](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen). @@ -15,7 +17,8 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| github\_pat | GitHub personal access token. | `string` | n/a | yes | +| github\_app\_id\_secret\_id | The secret ID for the application ID for the Cloudbuild GitHub app. | `string` | n/a | yes | +| github\_pat\_secret\_id | The secret ID for the personal access token for authenticating with GitHub. | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_uri | The URI of the GitHub repository where the Terraform configs are stored. | `string` | n/a | yes | diff --git a/examples/tf_cloudbuild_builder_simple_github/main.tf b/examples/tf_cloudbuild_builder_simple_github/main.tf index efc37c78..ea6bdd84 100644 --- a/examples/tf_cloudbuild_builder_simple_github/main.tf +++ b/examples/tf_cloudbuild_builder_simple_github/main.tf @@ -15,10 +15,6 @@ */ locals { - // Found in the URL of your Cloud Build GitHub app configuration settings - // https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen#connecting_a_github_host_programmatically - github_app_installation_id = "47590865" - # GitHub repo url of form "github.com/owner/name" repoURL = endswith(var.repository_uri, ".git") ? var.repository_uri : "${var.repository_uri}.git" repoURLWithoutSuffix = trimsuffix(local.repoURL, ".git") @@ -28,25 +24,17 @@ locals { location = "us-central1" } -data "google_project" "project" { - project_id = var.project_id -} - -// Added to various IDs to prevent potential conflicts for deployments targeting the same repository. -resource "random_id" "resources_random_id" { - byte_length = 4 -} - module "cloudbuilder" { source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_builder" version = "~> 8.0" project_id = module.enabled_google_apis.project_id - dockerfile_repo_uri = google_cloudbuildv2_repository.repository_connection.id + dockerfile_repo_uri = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id dockerfile_repo_type = "GITHUB" use_cloudbuildv2_repository = true trigger_location = local.location gar_repo_location = local.location + build_timeout = "1200s" bucket_name = "tf-cloudbuilder-build-logs-${var.project_id}-gh" gar_repo_name = "tf-runners-gh" workflow_name = "terraform-runner-workflow-gh" @@ -54,65 +42,55 @@ module "cloudbuilder" { # allow logs bucket to be destroyed cb_logs_bucket_force_destroy = true + + depends_on = [time_sleep.propagation] } -// Create a secret containing the personal access token and grant permissions to the Service Agent. -resource "google_secret_manager_secret" "github_token_secret" { - project = var.project_id - secret_id = "builder-gh-${random_id.resources_random_id.dec}-${local.gh_name}" +resource "time_sleep" "propagation" { + create_duration = "30s" - labels = { - label = "builder-gh-${random_id.resources_random_id.dec}" - } + depends_on = [module.git_repo_connection] +} - replication { - auto {} +module "git_repo_connection" { + source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" + version = "~> 8.0" + + project_id = var.project_id + connection_config = { + connection_type = "GITHUBv2" + github_secret_id = var.github_pat_secret_id + github_app_id_secret_id = var.github_app_id_secret_id } -} -// Personal access token from VCS. -resource "google_secret_manager_secret_version" "github_token_secret_version" { - secret = google_secret_manager_secret.github_token_secret.id - secret_data = var.github_pat -} + cloud_build_repositories = { + "test_repo" = { + repository_name = local.gh_name + repository_url = local.repoURL + }, + } -resource "google_secret_manager_secret_iam_member" "github_token_iam_member" { - project = var.project_id - secret_id = google_secret_manager_secret.github_token_secret.id - role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" + depends_on = [time_sleep.propagation_secret_version] } -// See https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen -resource "google_cloudbuildv2_connection" "vcs_connection" { - project = var.project_id - name = "builder-gh-${random_id.resources_random_id.dec}-${var.project_id}" - location = local.location - - github_config { - app_installation_id = local.github_app_installation_id - authorizer_credential { - oauth_token_secret_version = google_secret_manager_secret_version.github_token_secret_version.name - } - } +resource "time_sleep" "propagation_secret_version" { + create_duration = "30s" } -// Create the repository connection. -resource "google_cloudbuildv2_repository" "repository_connection" { - project = var.project_id - name = local.gh_name - location = local.location +data "google_secret_manager_secret_version_access" "github_pat" { + secret = var.github_pat_secret_id - parent_connection = google_cloudbuildv2_connection.vcs_connection.name - remote_uri = local.repoURL + depends_on = [time_sleep.propagation_secret_version] } # Bootstrap GitHub with Dockerfile module "bootstrap_github_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" - upgrade = false + + upgrade = false + module_depends_on = [module.cloudbuilder] create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh" - create_cmd_body = "${var.github_pat} ${var.repository_uri} ${path.module}/Dockerfile" + create_cmd_body = "${data.google_secret_manager_secret_version_access.github_pat.secret_data} ${var.repository_uri} ${path.module}/Dockerfile" } diff --git a/examples/tf_cloudbuild_builder_simple_github/outputs.tf b/examples/tf_cloudbuild_builder_simple_github/outputs.tf index 3cbb32f9..aab255bb 100644 --- a/examples/tf_cloudbuild_builder_simple_github/outputs.tf +++ b/examples/tf_cloudbuild_builder_simple_github/outputs.tf @@ -36,7 +36,7 @@ output "cloudbuild_trigger_id" { output "repository_id" { description = "ID of the Cloud Build repositories (2nd gen) repository" - value = google_cloudbuildv2_repository.repository_connection.id + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id } output "project_id" { diff --git a/examples/tf_cloudbuild_builder_simple_github/variables.tf b/examples/tf_cloudbuild_builder_simple_github/variables.tf index 517c347a..af81948b 100644 --- a/examples/tf_cloudbuild_builder_simple_github/variables.tf +++ b/examples/tf_cloudbuild_builder_simple_github/variables.tf @@ -19,12 +19,17 @@ variable "project_id" { type = string } -variable "github_pat" { - description = "GitHub personal access token." +variable "github_pat_secret_id" { + description = "The secret ID for the personal access token for authenticating with GitHub." type = string - sensitive = true } +variable "github_app_id_secret_id" { + description = "The secret ID for the application ID for the Cloudbuild GitHub app." + type = string +} + + variable "repository_uri" { description = "The URI of the GitHub repository where the Terraform configs are stored." type = string diff --git a/examples/tf_cloudbuild_builder_simple_gitlab/README.md b/examples/tf_cloudbuild_builder_simple_gitlab/README.md index 48f207d2..b6e0bebd 100644 --- a/examples/tf_cloudbuild_builder_simple_gitlab/README.md +++ b/examples/tf_cloudbuild_builder_simple_gitlab/README.md @@ -2,6 +2,14 @@ This example demonstrates the simplest usage of the [tf_cloudbuild_builder](../../modules/tf_cloudbuild_builder/) module with a Cloud Build repositories (2nd gen) GitLab repository. +For GitLab connections you will need: + +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `api`. +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `read_api`. +- Create a [webhook](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) +- Create three [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the `api` token, one for the `read_api` token, and one for the `webhook`. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. + For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation: - [Connect to a GitLab host](https://cloud.google.com/build/docs/automating-builds/gitlab/connect-host-gitlab) - [Connect to a GitLab repository](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen) @@ -11,8 +19,9 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| gitlab\_api\_access\_token | GitLab personal access token with api scope. If provided, creates a secret within Secret Manager. | `string` | n/a | yes | -| gitlab\_read\_api\_access\_token | GitLab personal access token with read\_api scope. If provided, creates a secret within Secret Manager. | `string` | n/a | yes | +| gitlab\_authorizer\_secret\_id | The secret ID for the credential for GitLab authorizer | `string` | n/a | yes | +| gitlab\_read\_authorizer\_secret\_id | The secret ID for the credential for GitLab read authorizer | `string` | n/a | yes | +| gitlab\_webhook\_secret\_id | The secret ID for the WebHook for GitLab | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_uri | The URI of the GitLab repository where the Terraform configs are stored. | `string` | n/a | yes | diff --git a/examples/tf_cloudbuild_builder_simple_gitlab/main.tf b/examples/tf_cloudbuild_builder_simple_gitlab/main.tf index 58206005..164408e4 100644 --- a/examples/tf_cloudbuild_builder_simple_gitlab/main.tf +++ b/examples/tf_cloudbuild_builder_simple_gitlab/main.tf @@ -24,28 +24,17 @@ locals { location = "us-central1" } -data "google_project" "project" { - project_id = var.project_id -} - -// Added to various IDs to prevent potential conflicts for deployments targeting the same repository. -resource "random_id" "gitlab_resources_random_id" { - byte_length = 8 -} - -resource "random_uuid" "random_webhook_secret" { -} - module "cloudbuilder" { source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_builder" version = "~> 8.0" project_id = module.enabled_google_apis.project_id - dockerfile_repo_uri = google_cloudbuildv2_repository.repository_connection.id + dockerfile_repo_uri = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id dockerfile_repo_type = "UNKNOWN" // "GITLAB" is not one of the options available so we need to use "UNKNOWN" use_cloudbuildv2_repository = true - trigger_location = "us-central1" - gar_repo_location = "us-central1" + trigger_location = local.location + gar_repo_location = local.location + build_timeout = "1200s" bucket_name = "tf-cloudbuilder-build-logs-${var.project_id}-gl" gar_repo_name = "tf-runners-gl" workflow_name = "terraform-runner-workflow-gl" @@ -54,109 +43,58 @@ module "cloudbuilder" { # allow logs bucket to be destroyed cb_logs_bucket_force_destroy = true - depends_on = [module.enabled_google_apis] -} - -// Create a secret containing the personal access token and grant permissions to the Service Agent. -resource "google_secret_manager_secret" "gitlab_api_secret" { - project = var.project_id - secret_id = "builder-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-api-access-token" - - labels = { - label = "b-${random_id.gitlab_resources_random_id.dec}" - } - - replication { - auto {} - } + depends_on = [ + time_sleep.propagation, + module.enabled_google_apis, + ] } -// Personal access token from VCS. -resource "google_secret_manager_secret_version" "gitlab_api_secret_version" { - secret = google_secret_manager_secret.gitlab_api_secret.id - secret_data = var.gitlab_api_access_token -} +resource "time_sleep" "propagation" { + create_duration = "30s" -resource "google_secret_manager_secret" "gitlab_read_api_secret" { - project = var.project_id - secret_id = "builder-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-read-api-access-token" - labels = { - label = "b-${random_id.gitlab_resources_random_id.dec}" - } - replication { - auto {} - } + depends_on = [module.git_repo_connection] } -resource "google_secret_manager_secret_version" "gitlab_read_api_secret_version" { - secret = google_secret_manager_secret.gitlab_read_api_secret.id - secret_data = var.gitlab_read_api_access_token -} +module "git_repo_connection" { + source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" + version = "~> 8.0" -resource "google_secret_manager_secret" "gitlab_webhook_secret" { - project = var.project_id - secret_id = "builder-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-webhook-secret" - labels = { - label = "b-${random_id.gitlab_resources_random_id.dec}" - } - replication { - auto {} + project_id = var.project_id + connection_config = { + connection_type = "GITLABv2" + gitlab_authorizer_credential_secret_id = var.gitlab_authorizer_secret_id + gitlab_read_authorizer_credential_secret_id = var.gitlab_read_authorizer_secret_id + gitlab_webhook_secret_id = var.gitlab_webhook_secret_id } -} - -resource "google_secret_manager_secret_version" "gitlab_webhook_secret_version" { - secret = google_secret_manager_secret.gitlab_webhook_secret.id - secret_data = random_uuid.random_webhook_secret.result -} -resource "google_secret_manager_secret_iam_member" "gitlab_token_iam_member" { - for_each = { - "api" = google_secret_manager_secret.gitlab_api_secret.id, - "read_api" = google_secret_manager_secret.gitlab_read_api_secret.id, - "webhook" = google_secret_manager_secret.gitlab_webhook_secret.id + cloud_build_repositories = { + "test_repo" = { + repository_name = local.gl_name + repository_url = var.repository_uri + }, } - project = var.project_id - secret_id = each.value - role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" + depends_on = [time_sleep.propagation_secret_version] } -resource "google_cloudbuildv2_connection" "vcs_connection" { - project = var.project_id - name = "builder-gl-${random_id.gitlab_resources_random_id.dec}-${var.project_id}" - location = local.location - - gitlab_config { - host_uri = null - authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_api_secret_version.name - } - read_authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_read_api_secret_version.name - } - webhook_secret_secret_version = google_secret_manager_secret_version.gitlab_webhook_secret_version.name - } - - depends_on = [google_secret_manager_secret_iam_member.gitlab_token_iam_member] +resource "time_sleep" "propagation_secret_version" { + create_duration = "30s" } -// Create the repository connection. -resource "google_cloudbuildv2_repository" "repository_connection" { - project = var.project_id - name = local.gl_name - location = local.location +data "google_secret_manager_secret_version_access" "gitlab_api_access_token" { + secret = var.gitlab_authorizer_secret_id - parent_connection = google_cloudbuildv2_connection.vcs_connection.name - remote_uri = local.repoURL + depends_on = [time_sleep.propagation_secret_version] } # Bootstrap GitLab with Dockerfile module "bootstrap_gitlab_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" - upgrade = false + + upgrade = false + module_depends_on = [module.cloudbuilder] create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh" - create_cmd_body = "${var.gitlab_api_access_token} ${var.repository_uri} ${path.module}/Dockerfile" + create_cmd_body = "${data.google_secret_manager_secret_version_access.gitlab_api_access_token.secret_data} ${var.repository_uri} ${path.module}/Dockerfile" } diff --git a/examples/tf_cloudbuild_builder_simple_gitlab/outputs.tf b/examples/tf_cloudbuild_builder_simple_gitlab/outputs.tf index 3cbb32f9..aab255bb 100644 --- a/examples/tf_cloudbuild_builder_simple_gitlab/outputs.tf +++ b/examples/tf_cloudbuild_builder_simple_gitlab/outputs.tf @@ -36,7 +36,7 @@ output "cloudbuild_trigger_id" { output "repository_id" { description = "ID of the Cloud Build repositories (2nd gen) repository" - value = google_cloudbuildv2_repository.repository_connection.id + value = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id } output "project_id" { diff --git a/examples/tf_cloudbuild_builder_simple_gitlab/variables.tf b/examples/tf_cloudbuild_builder_simple_gitlab/variables.tf index d3516954..b088f50d 100644 --- a/examples/tf_cloudbuild_builder_simple_gitlab/variables.tf +++ b/examples/tf_cloudbuild_builder_simple_gitlab/variables.tf @@ -19,19 +19,22 @@ variable "project_id" { type = string } -variable "gitlab_api_access_token" { - description = "GitLab personal access token with api scope. If provided, creates a secret within Secret Manager." +variable "repository_uri" { + description = "The URI of the GitLab repository where the Terraform configs are stored." type = string - sensitive = true } -variable "gitlab_read_api_access_token" { - description = "GitLab personal access token with read_api scope. If provided, creates a secret within Secret Manager." +variable "gitlab_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab authorizer" type = string - sensitive = true } -variable "repository_uri" { - description = "The URI of the GitLab repository where the Terraform configs are stored." +variable "gitlab_read_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab read authorizer" + type = string +} + +variable "gitlab_webhook_secret_id" { + description = "The secret ID for the WebHook for GitLab" type = string } diff --git a/examples/tf_cloudbuild_workspace_simple/files/main.tf b/examples/tf_cloudbuild_workspace_simple/files/main.tf index 4fbf40ef..685af448 100644 --- a/examples/tf_cloudbuild_workspace_simple/files/main.tf +++ b/examples/tf_cloudbuild_workspace_simple/files/main.tf @@ -15,8 +15,9 @@ */ module "test-vpc-module" { - source = "terraform-google-modules/network/google" - version = "~> 9.0" + source = "terraform-google-modules/network/google" + version = "~> 9.0" + project_id = var.project_id network_name = "my-custom-mode-network" mtu = 1460 diff --git a/examples/tf_cloudbuild_workspace_simple/main.tf b/examples/tf_cloudbuild_workspace_simple/main.tf index 4f1b1186..a708f582 100644 --- a/examples/tf_cloudbuild_workspace_simple/main.tf +++ b/examples/tf_cloudbuild_workspace_simple/main.tf @@ -42,6 +42,7 @@ resource "google_sourcerepo_repository" "tf_config_repo" { module "bootstrap_csr_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" + upgrade = false create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh" diff --git a/examples/tf_cloudbuild_workspace_simple_github/README.md b/examples/tf_cloudbuild_workspace_simple_github/README.md index d53c1846..62312727 100644 --- a/examples/tf_cloudbuild_workspace_simple_github/README.md +++ b/examples/tf_cloudbuild_workspace_simple_github/README.md @@ -6,6 +6,8 @@ For GitHub connections you will need: - Install the [Cloud Build App](https://github.com/apps/google-cloud-build) on Github. - Create a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) on Github with [scopes](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes) `repo` and `read:user` (or if app is installed in a organization use `read:org`). +- Create two [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the Cloud Build App and one for the Personal Access Token. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation for [Connect to a GitHub repository](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen). @@ -15,7 +17,8 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| github\_pat | GitHub personal access token. | `string` | n/a | yes | +| github\_app\_id\_secret\_id | The secret ID for the application ID for the Cloudbuild GitHub app. | `string` | n/a | yes | +| github\_pat\_secret\_id | The secret ID for the personal access token for authenticating with GitHub. | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_uri | The URI of the GitHub repository where the Terraform configs are stored. | `string` | n/a | yes | diff --git a/examples/tf_cloudbuild_workspace_simple_github/files/main.tf b/examples/tf_cloudbuild_workspace_simple_github/files/main.tf index 8c7cc7c6..6f5b12ef 100644 --- a/examples/tf_cloudbuild_workspace_simple_github/files/main.tf +++ b/examples/tf_cloudbuild_workspace_simple_github/files/main.tf @@ -15,8 +15,9 @@ */ module "test-vpc-module" { - source = "terraform-google-modules/network/google" - version = "~> 9.0" + source = "terraform-google-modules/network/google" + version = "~> 9.0" + project_id = var.project_id network_name = "my-custom-mode-network-gh" mtu = 1460 diff --git a/examples/tf_cloudbuild_workspace_simple_github/main.tf b/examples/tf_cloudbuild_workspace_simple_github/main.tf index 1155997f..92d83b42 100644 --- a/examples/tf_cloudbuild_workspace_simple_github/main.tf +++ b/examples/tf_cloudbuild_workspace_simple_github/main.tf @@ -15,10 +15,6 @@ */ locals { - // Found in the URL of your Cloud Build GitHub app configuration settings - // https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen#connecting_a_github_host_programmatically - github_app_installation_id = "47590865" - # GitHub repo url of form "github.com/owner/name" repoURL = endswith(var.repository_uri, ".git") ? var.repository_uri : "${var.repository_uri}.git" repoURLWithoutSuffix = trimsuffix(local.repoURL, ".git") @@ -28,26 +24,19 @@ locals { location = "us-central1" } -data "google_project" "project" { - project_id = var.project_id -} - -// Added to various IDs to prevent potential conflicts for deployments targeting the same repository. -resource "random_id" "resources_random_id" { - byte_length = 4 -} - module "tf_workspace" { - source = "../../modules/tf_cloudbuild_workspace" - - project_id = module.enabled_google_apis.project_id - tf_repo_type = "CLOUDBUILD_V2_REPOSITORY" - tf_repo_uri = google_cloudbuildv2_repository.repository_connection.id - location = "us-central1" - trigger_location = "us-central1" - artifacts_bucket_name = "tf-configs-build-artifacts-${var.project_id}-gh" - log_bucket_name = "tf-configs-build-logs-${var.project_id}-gh" - create_state_bucket_name = "tf-configs-build-state-${var.project_id}-gh" + source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_workspace" + version = "~> 8.0" + + project_id = module.enabled_google_apis.project_id + tf_repo_type = "CLOUDBUILD_V2_REPOSITORY" + tf_repo_uri = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id + location = "us-central1" + trigger_location = "us-central1" + create_cloudbuild_sa_name = "tf-gh-${lower(local.gh_name)}" + artifacts_bucket_name = "tf-configs-build-artifacts-${var.project_id}-gh" + log_bucket_name = "tf-configs-build-logs-${var.project_id}-gh" + create_state_bucket_name = "tf-configs-build-state-${var.project_id}-gh" # allow log/state buckets to be destroyed buckets_force_destroy = true @@ -58,65 +47,56 @@ module "tf_workspace" { } cloudbuild_env_vars = ["TF_VAR_project_id=${var.project_id}"] - depends_on = [module.enabled_google_apis] + depends_on = [ + module.enabled_google_apis, + time_sleep.propagation, + ] } -// Create a secret containing the personal access token and grant permissions to the Service Agent. -resource "google_secret_manager_secret" "github_token_secret" { - project = var.project_id - secret_id = "cb-github-${random_id.resources_random_id.dec}-${local.gh_name}" +resource "time_sleep" "propagation" { + create_duration = "30s" - labels = { - label = "cb-${random_id.resources_random_id.dec}" - } + depends_on = [module.git_repo_connection] +} - replication { - auto {} +module "git_repo_connection" { + source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" + version = "~> 8.0" + + project_id = var.project_id + connection_config = { + connection_type = "GITHUBv2" + github_secret_id = var.github_pat_secret_id + github_app_id_secret_id = var.github_app_id_secret_id } -} -// Personal access token from VCS. -resource "google_secret_manager_secret_version" "github_token_secret_version" { - secret = google_secret_manager_secret.github_token_secret.id - secret_data = var.github_pat -} + cloud_build_repositories = { + "test_repo" = { + repository_name = local.gh_name + repository_url = local.repoURL + }, + } -resource "google_secret_manager_secret_iam_member" "github_token_iam_member" { - project = var.project_id - secret_id = google_secret_manager_secret.github_token_secret.id - role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" + depends_on = [time_sleep.propagation_secret_version] } -// See https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen -resource "google_cloudbuildv2_connection" "vcs_connection" { - project = var.project_id - name = "cb-${random_id.resources_random_id.dec}-${var.project_id}" - location = local.location - - github_config { - app_installation_id = local.github_app_installation_id - authorizer_credential { - oauth_token_secret_version = google_secret_manager_secret_version.github_token_secret_version.name - } - } +resource "time_sleep" "propagation_secret_version" { + create_duration = "30s" } -// Create the repository connection. -resource "google_cloudbuildv2_repository" "repository_connection" { - project = var.project_id - name = local.gh_name - location = local.location +data "google_secret_manager_secret_version_access" "github_pat" { + secret = var.github_pat_secret_id - parent_connection = google_cloudbuildv2_connection.vcs_connection.name - remote_uri = local.repoURL + depends_on = [time_sleep.propagation_secret_version] } module "bootstrap_github_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" - upgrade = false + + upgrade = false + module_depends_on = [module.tf_workspace] create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh" - create_cmd_body = "${var.github_pat} ${var.repository_uri} ${path.module}/files" + create_cmd_body = "${data.google_secret_manager_secret_version_access.github_pat.secret_data} ${var.repository_uri} ${path.module}/files" } diff --git a/examples/tf_cloudbuild_workspace_simple_github/variables.tf b/examples/tf_cloudbuild_workspace_simple_github/variables.tf index 517c347a..aa045a6a 100644 --- a/examples/tf_cloudbuild_workspace_simple_github/variables.tf +++ b/examples/tf_cloudbuild_workspace_simple_github/variables.tf @@ -19,10 +19,14 @@ variable "project_id" { type = string } -variable "github_pat" { - description = "GitHub personal access token." +variable "github_pat_secret_id" { + description = "The secret ID for the personal access token for authenticating with GitHub." + type = string +} + +variable "github_app_id_secret_id" { + description = "The secret ID for the application ID for the Cloudbuild GitHub app." type = string - sensitive = true } variable "repository_uri" { diff --git a/examples/tf_cloudbuild_workspace_simple_gitlab/README.md b/examples/tf_cloudbuild_workspace_simple_gitlab/README.md index b63182ea..60c999c8 100644 --- a/examples/tf_cloudbuild_workspace_simple_gitlab/README.md +++ b/examples/tf_cloudbuild_workspace_simple_gitlab/README.md @@ -1,6 +1,14 @@ ## Github Requirements for Cloud Build Connection -When using a Cloud Build repositories (2nd gen) GitLab repository, a Cloud Build connection to your repository provider will be needed. +When using a Cloud Build repositories (2nd gen) GitLab repository, a Cloud Build connection to your repository provider will be created. + +For GitLab connections you will need: + +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `api`. +- Create a [Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) on GitLab with [scope](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes) `read_api`. +- Create a [webhook](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html) +- Create three [Google Secret Manager](https://cloud.google.com/secret-manager/docs/overview) secrets, one for the `api` token, one for the `read_api` token, and one for the `webhook`. +- Populate the corresponding [secret versions](https://cloud.google.com/secret-manager/docs/add-secret-version) of each one of the secrets. For more information on this topic refer to the Cloud Build repositories (2nd gen) documentation: - [Connect to a GitLab host](https://cloud.google.com/build/docs/automating-builds/gitlab/connect-host-gitlab) @@ -11,8 +19,9 @@ For more information on this topic refer to the Cloud Build repositories (2nd ge | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| gitlab\_api\_access\_token | GitLab personal access token with api scope. If provided, creates a secret within Secret Manager. | `string` | n/a | yes | -| gitlab\_read\_api\_access\_token | GitLab personal access token with read\_api scope. If provided, creates a secret within Secret Manager. | `string` | n/a | yes | +| gitlab\_authorizer\_secret\_id | The secret ID for the credential for GitLab authorizer | `string` | n/a | yes | +| gitlab\_read\_authorizer\_secret\_id | The secret ID for the credential for GitLab read authorizer | `string` | n/a | yes | +| gitlab\_webhook\_secret\_id | The secret ID for the WebHook for GitLab | `string` | n/a | yes | | project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes | | repository\_uri | The URI of the GitLab repository where the Terraform configs are stored. | `string` | n/a | yes | diff --git a/examples/tf_cloudbuild_workspace_simple_gitlab/files/main.tf b/examples/tf_cloudbuild_workspace_simple_gitlab/files/main.tf index 06d63bfb..dff9594e 100644 --- a/examples/tf_cloudbuild_workspace_simple_gitlab/files/main.tf +++ b/examples/tf_cloudbuild_workspace_simple_gitlab/files/main.tf @@ -15,8 +15,9 @@ */ module "test-vpc-module" { - source = "terraform-google-modules/network/google" - version = "~> 9.0" + source = "terraform-google-modules/network/google" + version = "~> 9.0" + project_id = var.project_id network_name = "my-custom-mode-network-gl" mtu = 1460 diff --git a/examples/tf_cloudbuild_workspace_simple_gitlab/main.tf b/examples/tf_cloudbuild_workspace_simple_gitlab/main.tf index 8d8e0947..6a6a1817 100644 --- a/examples/tf_cloudbuild_workspace_simple_gitlab/main.tf +++ b/examples/tf_cloudbuild_workspace_simple_gitlab/main.tf @@ -24,24 +24,13 @@ locals { location = "us-central1" } -data "google_project" "project" { - project_id = var.project_id -} - -// Added to various IDs to prevent potential conflicts for deployments targeting the same repository. -resource "random_id" "gitlab_resources_random_id" { - byte_length = 8 -} - -resource "random_uuid" "random_webhook_secret" { -} - module "tf_workspace" { - source = "../../modules/tf_cloudbuild_workspace" + source = "terraform-google-modules/bootstrap/google//modules/tf_cloudbuild_workspace" + version = "~> 8.0" project_id = module.enabled_google_apis.project_id tf_repo_type = "CLOUDBUILD_V2_REPOSITORY" - tf_repo_uri = google_cloudbuildv2_repository.repository_connection.id + tf_repo_uri = module.git_repo_connection.cloud_build_repositories_2nd_gen_repositories["test_repo"].id location = "us-central1" trigger_location = "us-central1" artifacts_bucket_name = "tf-configs-build-artifacts-${var.project_id}-gl" @@ -57,108 +46,57 @@ module "tf_workspace" { } cloudbuild_env_vars = ["TF_VAR_project_id=${var.project_id}"] - depends_on = [module.enabled_google_apis] + depends_on = [ + module.enabled_google_apis, + time_sleep.propagation, + ] } -// Create a secret containing the personal access token and grant permissions to the Service Agent. -resource "google_secret_manager_secret" "gitlab_api_secret" { - project = var.project_id - secret_id = "cb-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-api-access-token" - - labels = { - label = "cb-${random_id.gitlab_resources_random_id.dec}" - } - - replication { - auto {} - } -} - -// Personal access token from VCS. -resource "google_secret_manager_secret_version" "gitlab_api_secret_version" { - secret = google_secret_manager_secret.gitlab_api_secret.id - secret_data = var.gitlab_api_access_token -} +resource "time_sleep" "propagation" { + create_duration = "30s" -resource "google_secret_manager_secret" "gitlab_read_api_secret" { - project = var.project_id - secret_id = "cb-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-read-api-access-token" - labels = { - label = "cb-${random_id.gitlab_resources_random_id.dec}" - } - replication { - auto {} - } + depends_on = [module.git_repo_connection] } -resource "google_secret_manager_secret_version" "gitlab_read_api_secret_version" { - secret = google_secret_manager_secret.gitlab_read_api_secret.id - secret_data = var.gitlab_read_api_access_token -} +module "git_repo_connection" { + source = "terraform-google-modules/bootstrap/google//modules/cloudbuild_repo_connection" + version = "~> 8.0" -resource "google_secret_manager_secret" "gitlab_webhook_secret" { - project = var.project_id - secret_id = "cb-gl-${local.gl_name}-${random_id.gitlab_resources_random_id.dec}-webhook-secret" - labels = { - label = "cb-${random_id.gitlab_resources_random_id.dec}" - } - replication { - auto {} + project_id = var.project_id + connection_config = { + connection_type = "GITLABv2" + gitlab_authorizer_credential_secret_id = var.gitlab_authorizer_secret_id + gitlab_read_authorizer_credential_secret_id = var.gitlab_read_authorizer_secret_id + gitlab_webhook_secret_id = var.gitlab_webhook_secret_id } -} - -resource "google_secret_manager_secret_version" "gitlab_webhook_secret_version" { - secret = google_secret_manager_secret.gitlab_webhook_secret.id - secret_data = random_uuid.random_webhook_secret.result -} -resource "google_secret_manager_secret_iam_member" "gitlab_token_iam_member" { - for_each = { - "api" = google_secret_manager_secret.gitlab_api_secret.id, - "read_api" = google_secret_manager_secret.gitlab_read_api_secret.id, - "webhook" = google_secret_manager_secret.gitlab_webhook_secret.id + cloud_build_repositories = { + "test_repo" = { + repository_name = local.gl_name + repository_url = var.repository_uri + }, } - project = var.project_id - secret_id = each.value - role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" + depends_on = [time_sleep.propagation_secret_version] } -resource "google_cloudbuildv2_connection" "vcs_connection" { - project = var.project_id - name = "cb-gl-${random_id.gitlab_resources_random_id.dec}-${var.project_id}" - location = local.location - - gitlab_config { - host_uri = null - authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_api_secret_version.name - } - read_authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_read_api_secret_version.name - } - webhook_secret_secret_version = google_secret_manager_secret_version.gitlab_webhook_secret_version.name - } - - depends_on = [google_secret_manager_secret_iam_member.gitlab_token_iam_member] +resource "time_sleep" "propagation_secret_version" { + create_duration = "30s" } -// Create the repository connection. -resource "google_cloudbuildv2_repository" "repository_connection" { - project = var.project_id - name = local.gl_name - location = local.location +data "google_secret_manager_secret_version_access" "gitlab_api_access_token" { + secret = var.gitlab_authorizer_secret_id - parent_connection = google_cloudbuildv2_connection.vcs_connection.name - remote_uri = local.repoURL + depends_on = [time_sleep.propagation_secret_version] } module "bootstrap_github_repo" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" - upgrade = false + + upgrade = false + module_depends_on = [module.tf_workspace] create_cmd_entrypoint = "${path.module}/scripts/push-to-repo.sh" - create_cmd_body = "${var.gitlab_api_access_token} ${var.repository_uri} ${path.module}/files" + create_cmd_body = "${data.google_secret_manager_secret_version_access.gitlab_api_access_token.secret_data} ${var.repository_uri} ${path.module}/files" } diff --git a/examples/tf_cloudbuild_workspace_simple_gitlab/variables.tf b/examples/tf_cloudbuild_workspace_simple_gitlab/variables.tf index d3516954..306eba11 100644 --- a/examples/tf_cloudbuild_workspace_simple_gitlab/variables.tf +++ b/examples/tf_cloudbuild_workspace_simple_gitlab/variables.tf @@ -19,16 +19,19 @@ variable "project_id" { type = string } -variable "gitlab_api_access_token" { - description = "GitLab personal access token with api scope. If provided, creates a secret within Secret Manager." +variable "gitlab_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab authorizer" type = string - sensitive = true } -variable "gitlab_read_api_access_token" { - description = "GitLab personal access token with read_api scope. If provided, creates a secret within Secret Manager." +variable "gitlab_read_authorizer_secret_id" { + description = "The secret ID for the credential for GitLab read authorizer" + type = string +} + +variable "gitlab_webhook_secret_id" { + description = "The secret ID for the WebHook for GitLab" type = string - sensitive = true } variable "repository_uri" { diff --git a/main.tf b/main.tf index 790c8e31..11535171 100644 --- a/main.tf +++ b/main.tf @@ -71,6 +71,7 @@ module "seed_project" { labels = var.project_labels lien = true deletion_policy = var.project_deletion_policy + auto_create_network = var.project_auto_create_network } module "enable_cross_project_service_account_usage" { diff --git a/modules/cloudbuild/README.md b/modules/cloudbuild/README.md index 4da1356c..2c13e644 100644 --- a/modules/cloudbuild/README.md +++ b/modules/cloudbuild/README.md @@ -65,6 +65,7 @@ Functional examples and sample Cloud Build definitions are included in the [exam | group\_org\_admins | Google Group for GCP Organization Administrators | `string` | n/a | yes | | impersonate\_service\_account | The service account to impersonate while running the gcloud builds submit command. | `string` | `""` | no | | org\_id | GCP Organization ID | `string` | n/a | yes | +| project\_auto\_create\_network | Create the default network for the project created. | `bool` | `false` | no | | project\_deletion\_policy | The deletion policy for the project created. | `string` | `"PREVENT"` | no | | project\_id | Custom project ID to use for project created. | `string` | `""` | no | | project\_labels | Labels to apply to the project. | `map(string)` | `{}` | no | diff --git a/modules/cloudbuild/main.tf b/modules/cloudbuild/main.tf index 2381f1ae..deddd264 100644 --- a/modules/cloudbuild/main.tf +++ b/modules/cloudbuild/main.tf @@ -46,6 +46,7 @@ module "cloudbuild_project" { activate_apis = local.activate_apis labels = var.project_labels deletion_policy = var.project_deletion_policy + auto_create_network = var.project_auto_create_network } /****************************************** diff --git a/modules/cloudbuild/variables.tf b/modules/cloudbuild/variables.tf index 2519e248..25fc6adf 100644 --- a/modules/cloudbuild/variables.tf +++ b/modules/cloudbuild/variables.tf @@ -83,6 +83,12 @@ variable "project_deletion_policy" { default = "PREVENT" } +variable "project_auto_create_network" { + description = "Create the default network for the project created." + type = bool + default = false +} + variable "activate_apis" { description = "List of APIs to enable in the Cloudbuild project." type = list(string) diff --git a/modules/cloudbuild_repo_connection/README.md b/modules/cloudbuild_repo_connection/README.md index a864cc84..7dfb465f 100644 --- a/modules/cloudbuild_repo_connection/README.md +++ b/modules/cloudbuild_repo_connection/README.md @@ -2,9 +2,9 @@ This module is designed to establish the corresponding Cloud Build repositories (2nd gen) based on the `cloud_build_repositories` variable, where users can specify the repository names and URLs from their own version control systems. -Additionally, it will create and manage secret versions, as well as configure the necessary permissions for cloud build service agent when utilizing Cloud Build repositories (2nd gen). +Additionally, it will configure the necessary permissions for cloud build service agent when utilizing Cloud Build repositories (2nd gen). -Users will provide the required secrets through the `credential_config` variable, indicating their chosen Git provider. Currently, the module supports both GitHub and GitLab. +Users will provide the required secrets through the `connection_config` variable, indicating their chosen Git provider. Currently, the module supports both GitHub and GitLab. ## Inputs @@ -13,7 +13,7 @@ Users will provide the required secrets through the `credential_config` variable |------|-------------|------|---------|:--------:| | cloud\_build\_repositories | Cloud Build repositories configuration:
- repository\_name: The name of the repository to be used in Cloud Build.
- repository\_url: The HTTPS clone URL for the repository. This URL must end with '.git' and be a valid HTTPS URL.

Each entry in this map must contain both `repository_name` and `repository_url` to properly integrate with the Cloud Build service. |
map(object({
repository_name = string,
repository_url = string,
}))
| n/a | yes | | cloudbuild\_connection\_name | Cloudbuild Connection Name. | `string` | `"generic-cloudbuild-connection"` | no | -| credential\_config | Credential configuration options:
- credential\_type: Specifies the type of credential being used. Supported types are 'GITHUBv2' and 'GITLABv2'.
- github\_secret\_id: (Optional) The secret ID for GitHub credentials. Default is "cb-github-pat".
- github\_pat: (Optional) The personal access token for GitHub authentication.
- github\_app\_id: (Optional) The application ID for a GitHub App used for authentication. For app installation, follow this link: https://github.com/apps/google-cloud-build
- gitlab\_read\_authorizer\_credential: (Optional) The read authorizer credential for GitLab access.
- gitlab\_read\_authorizer\_credential\_secret\_id: (Optional) The secret ID for the GitLab read authorizer credential. Default is "cb-gitlab-read-api-credential".
- gitlab\_authorizer\_credential: (Optional) The authorizer credential for GitLab access.
- gitlab\_authorizer\_credential\_secret\_id: (Optional) The secret ID for the GitLab authorizer credential. Default is "cb-gitlab-api-credential". |
object({
credential_type = string
github_secret_id = optional(string, "cb-github-pat")
github_pat = optional(string)
github_app_id = optional(string)
gitlab_read_authorizer_credential = optional(string)
gitlab_read_authorizer_credential_secret_id = optional(string, "cb-gitlab-read-api-credential")
gitlab_authorizer_credential = optional(string)
gitlab_authorizer_credential_secret_id = optional(string, "cb-gitlab-api-credential")
})
| n/a | yes | +| connection\_config | Connection configuration options:
- connection\_type: Specifies the type of connection being used. Supported types are 'GITHUBv2' and 'GITLABv2'.
- github\_secret\_id: (Optional) The secret ID for GitHub credentials.
- github\_app\_id\_secret\_id: (Optional) The secret ID for the application ID for a GitHub App used for authentication. For app installation, follow this link: https://github.com/apps/google-cloud-build
- gitlab\_read\_authorizer\_credential\_secret\_id: (Optional) The secret ID for the GitLab read authorizer credential.
- gitlab\_authorizer\_credential\_secret\_id: (Optional) The secret ID for the GitLab authorizer credential.
- gitlab\_webhook\_secret\_id: (Optional) The secret ID for the GitLab WebHook. |
object({
connection_type = string
github_secret_id = optional(string)
github_app_id_secret_id = optional(string)
gitlab_read_authorizer_credential_secret_id = optional(string)
gitlab_authorizer_credential_secret_id = optional(string)
gitlab_webhook_secret_id = optional(string)
})
| n/a | yes | | location | Resources location. | `string` | `"us-central1"` | no | | project\_id | The project id to create the secret and assign cloudbuild service account permissions. | `string` | n/a | yes | diff --git a/modules/cloudbuild_repo_connection/cloudbuild.tf b/modules/cloudbuild_repo_connection/cloudbuild.tf deleted file mode 100644 index dc301b6e..00000000 --- a/modules/cloudbuild_repo_connection/cloudbuild.tf +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright 2024 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. - */ - -resource "google_cloudbuildv2_connection" "connection" { - project = var.project_id - location = var.location - name = "${var.cloudbuild_connection_name}-${random_id.suffix.dec}" - - dynamic "github_config" { - for_each = local.is_github ? [1] : [] - content { - app_installation_id = var.credential_config.github_app_id - authorizer_credential { - oauth_token_secret_version = "${google_secret_manager_secret.github_token[0].id}/versions/latest" - } - } - } - - dynamic "gitlab_config" { - for_each = local.is_gitlab ? [1] : [] - content { - host_uri = null - authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_api_token[0].name - } - read_authorizer_credential { - user_token_secret_version = google_secret_manager_secret_version.gitlab_read_api_token[0].name - } - webhook_secret_secret_version = google_secret_manager_secret_version.gitlab_webhook[0].name - } - } - - depends_on = [time_sleep.secret_iam_permission_propagation] -} - -resource "time_sleep" "secret_iam_permission_propagation" { - create_duration = "30s" - - depends_on = [ - google_secret_manager_secret_iam_member.github_accessor, - google_secret_manager_secret_iam_member.gitlab_token_accessor - ] -} - -resource "google_cloudbuildv2_repository" "repositories" { - for_each = var.cloud_build_repositories - - project = var.project_id - location = var.location - name = each.value.repository_name - remote_uri = each.value.repository_url - parent_connection = google_cloudbuildv2_connection.connection.name -} diff --git a/modules/cloudbuild_repo_connection/main.tf b/modules/cloudbuild_repo_connection/main.tf index 71420876..46bf8351 100644 --- a/modules/cloudbuild_repo_connection/main.tf +++ b/modules/cloudbuild_repo_connection/main.tf @@ -14,116 +14,96 @@ * limitations under the License. */ -data "google_project" "project_id" { - project_id = var.project_id -} - locals { - is_github = var.credential_config.credential_type == "GITHUBv2" - is_gitlab = var.credential_config.credential_type == "GITLABv2" + is_github = var.connection_config.connection_type == "GITHUBv2" + is_gitlab = var.connection_config.connection_type == "GITLABv2" gitlab_secrets_iterator = local.is_gitlab ? { - "api" = google_secret_manager_secret.gitlab_api_token[0].id, - "read_api" = google_secret_manager_secret.gitlab_read_api_token[0].id, - "webhook" = google_secret_manager_secret.gitlab_webhook[0].id + "api" = var.connection_config.gitlab_authorizer_credential_secret_id, + "read_api" = var.connection_config.gitlab_read_authorizer_credential_secret_id, + "webhook" = var.connection_config.gitlab_webhook_secret_id } : {} } +data "google_project" "project_id" { + project_id = var.project_id +} + resource "random_id" "suffix" { byte_length = 4 } -# Github Secret -resource "google_secret_manager_secret" "github_token" { +data "google_secret_manager_secret_version_access" "app_installation_id" { count = local.is_github ? 1 : 0 - project = var.project_id - secret_id = "${var.credential_config.github_secret_id}-${random_id.suffix.dec}" - - replication { - auto { + secret = var.connection_config.github_app_id_secret_id +} +resource "google_cloudbuildv2_connection" "connection" { + project = var.project_id + location = var.location + name = "${var.cloudbuild_connection_name}-${random_id.suffix.dec}" + + dynamic "github_config" { + for_each = local.is_github ? [1] : [] + content { + app_installation_id = data.google_secret_manager_secret_version_access.app_installation_id[0].secret_data + authorizer_credential { + oauth_token_secret_version = "${var.connection_config.github_secret_id}/versions/latest" + } } } -} -resource "google_secret_manager_secret_version" "github_token" { - count = local.is_github ? 1 : 0 + dynamic "gitlab_config" { + for_each = local.is_gitlab ? [1] : [] + content { + host_uri = null + authorizer_credential { + user_token_secret_version = "${var.connection_config.gitlab_authorizer_credential_secret_id}/versions/latest" + } + read_authorizer_credential { + user_token_secret_version = "${var.connection_config.gitlab_read_authorizer_credential_secret_id}/versions/latest" + } + webhook_secret_secret_version = "${var.connection_config.gitlab_webhook_secret_id}/versions/latest" + } + } - secret = google_secret_manager_secret.github_token[0].id - secret_data = var.credential_config.github_pat + depends_on = [time_sleep.secret_iam_permission_propagation] } resource "google_secret_manager_secret_iam_member" "github_accessor" { count = local.is_github ? 1 : 0 - secret_id = google_secret_manager_secret.github_token[0].id + secret_id = var.connection_config.github_secret_id role = "roles/secretmanager.secretAccessor" member = "serviceAccount:service-${data.google_project.project_id.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" } -# Gitlab secret -resource "google_secret_manager_secret" "gitlab_api_token" { - count = local.is_gitlab ? 1 : 0 - - project = var.project_id - secret_id = "${var.credential_config.gitlab_authorizer_credential_secret_id}-${random_id.suffix.dec}" - - replication { - auto {} - } -} - -resource "google_secret_manager_secret_version" "gitlab_api_token" { - count = local.is_gitlab ? 1 : 0 - - secret = google_secret_manager_secret.gitlab_api_token[0].id - secret_data = var.credential_config.gitlab_authorizer_credential -} -resource "google_secret_manager_secret" "gitlab_read_api_token" { - count = local.is_gitlab ? 1 : 0 - - project = var.project_id - secret_id = "${var.credential_config.gitlab_read_authorizer_credential_secret_id}-${random_id.suffix.dec}" - replication { - auto {} - } -} - -resource "google_secret_manager_secret_version" "gitlab_read_api_token" { - count = local.is_gitlab ? 1 : 0 - - secret = google_secret_manager_secret.gitlab_read_api_token[0].id - secret_data = var.credential_config.gitlab_read_authorizer_credential -} - -resource "google_secret_manager_secret" "gitlab_webhook" { - count = local.is_gitlab ? 1 : 0 +resource "google_secret_manager_secret_iam_member" "gitlab_token_accessor" { + for_each = local.gitlab_secrets_iterator project = var.project_id - secret_id = "cb-gitlab-webhook-${random_id.suffix.dec}" - replication { - auto {} - } -} - -resource "random_uuid" "random_webhook_secret" { - count = local.is_gitlab ? 1 : 0 + secret_id = each.value + role = "roles/secretmanager.secretAccessor" + member = "serviceAccount:service-${data.google_project.project_id.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" } -resource "google_secret_manager_secret_version" "gitlab_webhook" { - count = local.is_gitlab ? 1 : 0 +resource "time_sleep" "secret_iam_permission_propagation" { + create_duration = "30s" - secret = google_secret_manager_secret.gitlab_webhook[0].id - secret_data = random_uuid.random_webhook_secret[0].result + depends_on = [ + google_secret_manager_secret_iam_member.github_accessor, + google_secret_manager_secret_iam_member.gitlab_token_accessor + ] } -resource "google_secret_manager_secret_iam_member" "gitlab_token_accessor" { - for_each = local.gitlab_secrets_iterator +resource "google_cloudbuildv2_repository" "repositories" { + for_each = var.cloud_build_repositories - project = var.project_id - secret_id = each.value - role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:service-${data.google_project.project_id.number}@gcp-sa-cloudbuild.iam.gserviceaccount.com" + project = var.project_id + location = var.location + name = each.value.repository_name + remote_uri = each.value.repository_url + parent_connection = google_cloudbuildv2_connection.connection.name } diff --git a/modules/cloudbuild_repo_connection/variables.tf b/modules/cloudbuild_repo_connection/variables.tf index f1f6a4c4..8913a766 100644 --- a/modules/cloudbuild_repo_connection/variables.tf +++ b/modules/cloudbuild_repo_connection/variables.tf @@ -19,50 +19,47 @@ variable "project_id" { type = string } -variable "credential_config" { +variable "connection_config" { description = <<-EOT - Credential configuration options: - - credential_type: Specifies the type of credential being used. Supported types are 'GITHUBv2' and 'GITLABv2'. - - github_secret_id: (Optional) The secret ID for GitHub credentials. Default is "cb-github-pat". - - github_pat: (Optional) The personal access token for GitHub authentication. - - github_app_id: (Optional) The application ID for a GitHub App used for authentication. For app installation, follow this link: https://github.com/apps/google-cloud-build - - gitlab_read_authorizer_credential: (Optional) The read authorizer credential for GitLab access. - - gitlab_read_authorizer_credential_secret_id: (Optional) The secret ID for the GitLab read authorizer credential. Default is "cb-gitlab-read-api-credential". - - gitlab_authorizer_credential: (Optional) The authorizer credential for GitLab access. - - gitlab_authorizer_credential_secret_id: (Optional) The secret ID for the GitLab authorizer credential. Default is "cb-gitlab-api-credential". + Connection configuration options: + - connection_type: Specifies the type of connection being used. Supported types are 'GITHUBv2' and 'GITLABv2'. + - github_secret_id: (Optional) The secret ID for GitHub credentials. + - github_app_id_secret_id: (Optional) The secret ID for the application ID for a GitHub App used for authentication. For app installation, follow this link: https://github.com/apps/google-cloud-build + - gitlab_read_authorizer_credential_secret_id: (Optional) The secret ID for the GitLab read authorizer credential. + - gitlab_authorizer_credential_secret_id: (Optional) The secret ID for the GitLab authorizer credential. + - gitlab_webhook_secret_id: (Optional) The secret ID for the GitLab WebHook. EOT type = object({ - credential_type = string - github_secret_id = optional(string, "cb-github-pat") - github_pat = optional(string) - github_app_id = optional(string) - gitlab_read_authorizer_credential = optional(string) - gitlab_read_authorizer_credential_secret_id = optional(string, "cb-gitlab-read-api-credential") - gitlab_authorizer_credential = optional(string) - gitlab_authorizer_credential_secret_id = optional(string, "cb-gitlab-api-credential") + connection_type = string + github_secret_id = optional(string) + github_app_id_secret_id = optional(string) + gitlab_read_authorizer_credential_secret_id = optional(string) + gitlab_authorizer_credential_secret_id = optional(string) + gitlab_webhook_secret_id = optional(string) }) validation { - condition = var.credential_config.credential_type == "GITLABv2" || var.credential_config.credential_type == "GITHUBv2" - error_message = "Specify one of the valid credential_types: 'GITLABv2' or 'GITHUBv2'." + condition = var.connection_config.connection_type == "GITLABv2" || var.connection_config.connection_type == "GITHUBv2" + error_message = "Specify one of the valid connection_types: 'GITLABv2' or 'GITHUBv2'." } validation { - condition = var.credential_config.credential_type == "GITLABv2" ? ( - var.credential_config.gitlab_read_authorizer_credential != null && - var.credential_config.gitlab_authorizer_credential != null + condition = var.connection_config.connection_type == "GITLABv2" ? ( + var.connection_config.gitlab_read_authorizer_credential_secret_id != null && + var.connection_config.gitlab_authorizer_credential_secret_id != null && + var.connection_config.gitlab_webhook_secret_id != null ) : true - error_message = "For 'GITLABv2', 'gitlab_read_authorizer_credential' and 'gitlab_authorizer_credential' must be defined." + error_message = "For 'GITLABv2', 'gitlab_read_authorizer_credential_secret_id', 'gitlab_authorizer_credential_secret_id', and 'gitlab_webhook_secret_id' must be defined." } validation { - condition = var.credential_config.credential_type == "GITHUBv2" ? ( - var.credential_config.github_pat != null && - var.credential_config.github_app_id != null + condition = var.connection_config.connection_type == "GITHUBv2" ? ( + var.connection_config.github_secret_id != null && + var.connection_config.github_app_id_secret_id != null ) : true - error_message = "For 'GITHUBv2', 'github_pat' and 'github_app_id' must be defined." + error_message = "For 'GITHUBv2', 'github_secret_id' and 'github_app_id_secret_id' must be defined." } } diff --git a/modules/tf_cloudbuild_source/README.md b/modules/tf_cloudbuild_source/README.md index 9a5158bc..69a320bd 100644 --- a/modules/tf_cloudbuild_source/README.md +++ b/modules/tf_cloudbuild_source/README.md @@ -38,6 +38,7 @@ This module creates: | 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\_auto\_create\_network | Create the default network for the project created. | `bool` | `false` | no | | project\_deletion\_policy | The deletion policy for the project created. | `string` | `"PREVENT"` | no | | project\_id | Custom project ID to use for project created. | `string` | `""` | no | | project\_labels | Labels to apply to the project. | `map(string)` | `{}` | no | diff --git a/modules/tf_cloudbuild_source/main.tf b/modules/tf_cloudbuild_source/main.tf index 8454a435..737c31b2 100644 --- a/modules/tf_cloudbuild_source/main.tf +++ b/modules/tf_cloudbuild_source/main.tf @@ -44,6 +44,7 @@ module "cloudbuild_project" { activate_apis = local.activate_apis labels = var.project_labels deletion_policy = var.project_deletion_policy + auto_create_network = var.project_auto_create_network } // On the first run of cloud build submit, a bucket is automaticaly created with name "[PROJECT_ID]_cloudbuild" @@ -88,6 +89,7 @@ resource "google_project_iam_member" "org_admins_source_repo_admin" { member = "group:${var.group_org_admins}" } +//Cloudbuild Service Account resource "google_storage_bucket_iam_member" "cloudbuild_iam" { bucket = module.cloudbuild_bucket.bucket.name role = "roles/storage.admin" diff --git a/modules/tf_cloudbuild_source/variables.tf b/modules/tf_cloudbuild_source/variables.tf index c91ee4ce..86c5c21c 100644 --- a/modules/tf_cloudbuild_source/variables.tf +++ b/modules/tf_cloudbuild_source/variables.tf @@ -37,6 +37,12 @@ variable "project_deletion_policy" { default = "PREVENT" } +variable "project_auto_create_network" { + description = "Create the default network for the project created." + type = bool + default = false +} + variable "project_labels" { description = "Labels to apply to the project." type = map(string) diff --git a/test/fixtures/cloudbuild_repo_connection_github/main.tf b/test/fixtures/cloudbuild_repo_connection_github/main.tf new file mode 100644 index 00000000..343737b7 --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_github/main.tf @@ -0,0 +1,73 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Github Secret +resource "google_secret_manager_secret" "github_token" { + project = var.project_id + secret_id = "cb-github-pat-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_token" { + secret = google_secret_manager_secret.github_token.id + secret_data = var.github_pat +} + +resource "google_secret_manager_secret" "github_app_id" { + project = var.project_id + secret_id = "cb-github-app-id-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_app_id" { + secret = google_secret_manager_secret.github_app_id.id + secret_data = var.github_app_id +} + +resource "time_sleep" "propagation" { + create_duration = "30s" + + depends_on = [ + google_secret_manager_secret_version.github_app_id, + google_secret_manager_secret_version.github_token + ] +} + +module "example" { + source = "../../../examples/cloudbuild_repo_connection_github" + + project_id = var.project_id + github_pat_secret_id = google_secret_manager_secret.github_token.id + github_app_id_secret_id = google_secret_manager_secret.github_app_id.id + repository_name = var.repository_name + repository_url = var.repository_url + + depends_on = [time_sleep.propagation] +} diff --git a/test/fixtures/cloudbuild_repo_connection_github/outputs.tf b/test/fixtures/cloudbuild_repo_connection_github/outputs.tf new file mode 100644 index 00000000..aa1785c3 --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_github/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2024 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 "cloud_build_repositories_2nd_gen_connection" { + description = "Cloudbuild connection created." + value = module.example.cloud_build_repositories_2nd_gen_connection +} + +output "cloud_build_repositories_2nd_gen_repositories" { + description = "Created repositories." + value = module.example.cloud_build_repositories_2nd_gen_repositories +} diff --git a/test/fixtures/cloudbuild_repo_connection_github/variables.tf b/test/fixtures/cloudbuild_repo_connection_github/variables.tf new file mode 100644 index 00000000..171cb024 --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_github/variables.tf @@ -0,0 +1,42 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "github_pat" { + description = "The personal access token for authenticating with GitHub." + type = string + sensitive = true +} + +variable "github_app_id" { + description = "The application ID for the Cloudbuild GitHub app." + type = string + sensitive = true +} + +variable "repository_url" { + description = "The HTTPS clone URL of the repository, ending with .git." + type = string +} + +variable "repository_name" { + description = "The name of the test repository." + type = string +} diff --git a/test/fixtures/cloudbuild_repo_connection_gitlab/main.tf b/test/fixtures/cloudbuild_repo_connection_gitlab/main.tf new file mode 100644 index 00000000..927224fc --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_gitlab/main.tf @@ -0,0 +1,86 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Gitlab secret +resource "google_secret_manager_secret" "gitlab_api_token" { + project = var.project_id + secret_id = "cb-gitlab-api-credential-${random_id.suffix.dec}" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_api_token" { + secret = google_secret_manager_secret.gitlab_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_read_api_token" { + project = var.project_id + secret_id = "cb-gitlab-read-api-credential-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_read_api_token" { + secret = google_secret_manager_secret.gitlab_read_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_webhook" { + project = var.project_id + secret_id = "cb-gitlab-webhook-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "random_uuid" "random_webhook_secret" { +} + +resource "google_secret_manager_secret_version" "gitlab_webhook" { + secret = google_secret_manager_secret.gitlab_webhook.id + secret_data = random_uuid.random_webhook_secret.result +} + +resource "time_sleep" "propagation" { + create_duration = "30s" + + depends_on = [ + google_secret_manager_secret_version.gitlab_api_token, + google_secret_manager_secret_version.gitlab_read_api_token, + google_secret_manager_secret_version.gitlab_webhook, + ] +} + +module "example" { + source = "../../../examples/cloudbuild_repo_connection_gitlab" + + project_id = var.project_id + gitlab_authorizer_secret_id = google_secret_manager_secret.gitlab_api_token.id + gitlab_read_authorizer_secret_id = google_secret_manager_secret.gitlab_read_api_token.id + gitlab_webhook_secret_id = google_secret_manager_secret.gitlab_webhook.id + repository_name = var.repository_name + repository_url = var.repository_url + + depends_on = [time_sleep.propagation] +} diff --git a/test/fixtures/cloudbuild_repo_connection_gitlab/outputs.tf b/test/fixtures/cloudbuild_repo_connection_gitlab/outputs.tf new file mode 100644 index 00000000..aa1785c3 --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_gitlab/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2024 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 "cloud_build_repositories_2nd_gen_connection" { + description = "Cloudbuild connection created." + value = module.example.cloud_build_repositories_2nd_gen_connection +} + +output "cloud_build_repositories_2nd_gen_repositories" { + description = "Created repositories." + value = module.example.cloud_build_repositories_2nd_gen_repositories +} diff --git a/test/fixtures/cloudbuild_repo_connection_gitlab/variables.tf b/test/fixtures/cloudbuild_repo_connection_gitlab/variables.tf new file mode 100644 index 00000000..50648b43 --- /dev/null +++ b/test/fixtures/cloudbuild_repo_connection_gitlab/variables.tf @@ -0,0 +1,42 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "repository_url" { + description = "The HTTPS clone URL of the repository, ending with .git." + type = string +} + +variable "repository_name" { + description = "The name of the test repository." + type = string +} + +variable "gitlab_authorizer_credential" { + description = "Credential for GitLab authorizer" + type = string + sensitive = true +} + +variable "gitlab_read_authorizer_credential" { + description = "Credential for GitLab read authorizer" + type = string + sensitive = true +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_github/main.tf b/test/fixtures/tf_cloudbuild_builder_simple_github/main.tf new file mode 100644 index 00000000..dd9c98f4 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_github/main.tf @@ -0,0 +1,61 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Github Secret +resource "google_secret_manager_secret" "github_token" { + project = var.project_id + secret_id = "builder-gh-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_token" { + secret = google_secret_manager_secret.github_token.id + secret_data = var.github_pat +} + +resource "google_secret_manager_secret" "github_app_id" { + project = var.project_id + secret_id = "builder-gh-app-id-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_app_id" { + secret = google_secret_manager_secret.github_app_id.id + secret_data = var.github_app_id +} + +module "example" { + source = "../../../examples/tf_cloudbuild_builder_simple_github" + + project_id = var.project_id + github_pat_secret_id = google_secret_manager_secret.github_token.id + github_app_id_secret_id = google_secret_manager_secret.github_app_id.id + repository_uri = var.repository_uri +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_github/outputs.tf b/test/fixtures/tf_cloudbuild_builder_simple_github/outputs.tf new file mode 100644 index 00000000..5b07809c --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_github/outputs.tf @@ -0,0 +1,50 @@ +/** + * Copyright 2024 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.example.artifact_repo +} + +output "workflow_id" { + description = "Workflow ID for triggering new TF Builder build" + value = module.example.workflow_id +} + +output "scheduler_id" { + description = "Scheduler ID for periodically triggering TF Builder build Workflow" + value = module.example.scheduler_id +} + +output "cloudbuild_trigger_id" { + description = "Trigger used for building new TF Builder" + value = module.example.cloudbuild_trigger_id +} + +output "repository_id" { + description = "ID of the Cloud Build repositories (2nd gen) repository" + value = module.example.repository_id +} + +output "project_id" { + description = "The ID of the project in which the resources were provisioned" + value = module.example.project_id +} + +output "location" { + description = "The location in which the resources were provisioned" + value = module.example.location +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_github/variables.tf b/test/fixtures/tf_cloudbuild_builder_simple_github/variables.tf new file mode 100644 index 00000000..320292f9 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_github/variables.tf @@ -0,0 +1,37 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "github_pat" { + description = "The personal access token for authenticating with GitHub." + type = string + sensitive = true +} + +variable "github_app_id" { + description = "The application ID for the Cloudbuild GitHub app." + type = string + sensitive = true +} + +variable "repository_uri" { + description = "The URI of the GitHub repository where the Terraform configs are stored." + type = string +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_gitlab/main.tf b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/main.tf new file mode 100644 index 00000000..bfea6184 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/main.tf @@ -0,0 +1,73 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Gitlab secret +resource "google_secret_manager_secret" "gitlab_api_token" { + project = var.project_id + secret_id = "cb-gitlab-api-credential-${random_id.suffix.dec}" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_api_token" { + secret = google_secret_manager_secret.gitlab_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_read_api_token" { + project = var.project_id + secret_id = "cb-gitlab-read-api-credential-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_read_api_token" { + secret = google_secret_manager_secret.gitlab_read_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_webhook" { + project = var.project_id + secret_id = "cb-gitlab-webhook-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "random_uuid" "random_webhook_secret" { +} + +resource "google_secret_manager_secret_version" "gitlab_webhook" { + secret = google_secret_manager_secret.gitlab_webhook.id + secret_data = random_uuid.random_webhook_secret.result +} + +module "example" { + source = "../../../examples/tf_cloudbuild_builder_simple_gitlab" + + project_id = var.project_id + gitlab_authorizer_secret_id = google_secret_manager_secret.gitlab_api_token.id + gitlab_read_authorizer_secret_id = google_secret_manager_secret.gitlab_read_api_token.id + gitlab_webhook_secret_id = google_secret_manager_secret.gitlab_webhook.id + repository_uri = var.repository_uri +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_gitlab/outputs.tf b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/outputs.tf new file mode 100644 index 00000000..5b07809c --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/outputs.tf @@ -0,0 +1,50 @@ +/** + * Copyright 2024 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.example.artifact_repo +} + +output "workflow_id" { + description = "Workflow ID for triggering new TF Builder build" + value = module.example.workflow_id +} + +output "scheduler_id" { + description = "Scheduler ID for periodically triggering TF Builder build Workflow" + value = module.example.scheduler_id +} + +output "cloudbuild_trigger_id" { + description = "Trigger used for building new TF Builder" + value = module.example.cloudbuild_trigger_id +} + +output "repository_id" { + description = "ID of the Cloud Build repositories (2nd gen) repository" + value = module.example.repository_id +} + +output "project_id" { + description = "The ID of the project in which the resources were provisioned" + value = module.example.project_id +} + +output "location" { + description = "The location in which the resources were provisioned" + value = module.example.location +} diff --git a/test/fixtures/tf_cloudbuild_builder_simple_gitlab/variables.tf b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/variables.tf new file mode 100644 index 00000000..a0607a0b --- /dev/null +++ b/test/fixtures/tf_cloudbuild_builder_simple_gitlab/variables.tf @@ -0,0 +1,37 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "repository_uri" { + description = "The HTTPS clone URL of the repository, ending with .git." + type = string +} + +variable "gitlab_authorizer_credential" { + description = "Credential for GitLab authorizer" + type = string + sensitive = true +} + +variable "gitlab_read_authorizer_credential" { + description = "Credential for GitLab read authorizer" + type = string + sensitive = true +} diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_github/main.tf b/test/fixtures/tf_cloudbuild_workspace_simple_github/main.tf new file mode 100644 index 00000000..c5f45f74 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_github/main.tf @@ -0,0 +1,61 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Github Secret +resource "google_secret_manager_secret" "github_token" { + project = var.project_id + secret_id = "cb-gh-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_token" { + secret = google_secret_manager_secret.github_token.id + secret_data = var.github_pat +} + +resource "google_secret_manager_secret" "github_app_id" { + project = var.project_id + secret_id = "cb-gh-app-id-${random_id.suffix.dec}" + + replication { + auto { + + } + } +} + +resource "google_secret_manager_secret_version" "github_app_id" { + secret = google_secret_manager_secret.github_app_id.id + secret_data = var.github_app_id +} + +module "example" { + source = "../../../examples/tf_cloudbuild_workspace_simple_github" + + project_id = var.project_id + github_pat_secret_id = google_secret_manager_secret.github_token.id + github_app_id_secret_id = google_secret_manager_secret.github_app_id.id + repository_uri = var.repository_uri +} diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_github/outputs.tf b/test/fixtures/tf_cloudbuild_workspace_simple_github/outputs.tf new file mode 100644 index 00000000..144abb23 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_github/outputs.tf @@ -0,0 +1,56 @@ +/** + * Copyright 2024 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_plan_trigger_id" { + description = "Trigger used for running TF plan" + value = module.example.cloudbuild_plan_trigger_id +} + +output "cloudbuild_apply_trigger_id" { + description = "Trigger used for running TF apply" + value = module.example.cloudbuild_apply_trigger_id +} + +output "cloudbuild_sa" { + description = "SA used by Cloud Build triggers" + value = module.example.cloudbuild_sa +} + +output "state_bucket" { + description = "Bucket for storing TF state" + value = module.example.state_bucket +} + +output "logs_bucket" { + description = "Bucket for storing TF logs" + value = module.example.logs_bucket +} + +output "artifacts_bucket" { + description = "Bucket for storing TF plans" + value = module.example.artifacts_bucket +} + +output "project_id" { + description = "The ID of the project in which the resources were provisioned" + value = module.example.project_id +} + +output "location" { + description = "The location in which the resources were provisioned" + value = module.example.location +} + diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_github/variables.tf b/test/fixtures/tf_cloudbuild_workspace_simple_github/variables.tf new file mode 100644 index 00000000..507e2526 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_github/variables.tf @@ -0,0 +1,37 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "github_pat" { + description = "The personal access token for authenticating with GitHub." + type = string + sensitive = true +} + +variable "github_app_id" { + description = "The application ID for the Cloudbuild GitHub app." + type = string + sensitive = true +} + +variable "repository_uri" { + description = "The HTTPS clone URL of the repository, ending with .git." + type = string +} diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/main.tf b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/main.tf new file mode 100644 index 00000000..2bb964b3 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/main.tf @@ -0,0 +1,73 @@ +/** + * Copyright 2024 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. + */ + +resource "random_id" "suffix" { + byte_length = 4 +} + +# Gitlab secret +resource "google_secret_manager_secret" "gitlab_api_token" { + project = var.project_id + secret_id = "cb-gl-api-credential-${random_id.suffix.dec}" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_api_token" { + secret = google_secret_manager_secret.gitlab_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_read_api_token" { + project = var.project_id + secret_id = "cb-gl-read-api-credential-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "gitlab_read_api_token" { + secret = google_secret_manager_secret.gitlab_read_api_token.id + secret_data = var.gitlab_authorizer_credential +} + +resource "google_secret_manager_secret" "gitlab_webhook" { + project = var.project_id + secret_id = "cb-gl-webhook-${random_id.suffix.dec}" + replication { + auto {} + } +} + +resource "random_uuid" "random_webhook_secret" { +} + +resource "google_secret_manager_secret_version" "gitlab_webhook" { + secret = google_secret_manager_secret.gitlab_webhook.id + secret_data = random_uuid.random_webhook_secret.result +} + +module "example" { + source = "../../../examples/tf_cloudbuild_workspace_simple_gitlab" + + project_id = var.project_id + gitlab_authorizer_secret_id = google_secret_manager_secret.gitlab_api_token.id + gitlab_read_authorizer_secret_id = google_secret_manager_secret.gitlab_read_api_token.id + gitlab_webhook_secret_id = google_secret_manager_secret.gitlab_webhook.id + repository_uri = var.repository_uri +} diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/outputs.tf b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/outputs.tf new file mode 100644 index 00000000..b4760481 --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/outputs.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2024 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_plan_trigger_id" { + description = "Trigger used for running TF plan" + value = module.example.cloudbuild_plan_trigger_id +} + +output "cloudbuild_apply_trigger_id" { + description = "Trigger used for running TF apply" + value = module.example.cloudbuild_apply_trigger_id +} + +output "cloudbuild_sa" { + description = "SA used by Cloud Build triggers" + value = module.example.cloudbuild_sa +} + +output "state_bucket" { + description = "Bucket for storing TF state" + value = module.example.state_bucket +} + +output "logs_bucket" { + description = "Bucket for storing TF logs" + value = module.example.logs_bucket +} + +output "artifacts_bucket" { + description = "Bucket for storing TF plans" + value = module.example.artifacts_bucket +} + +output "project_id" { + description = "The ID of the project in which the resources were provisioned" + value = module.example.project_id +} + +output "location" { + description = "The location in which the resources were provisioned" + value = module.example.location +} diff --git a/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/variables.tf b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/variables.tf new file mode 100644 index 00000000..a0607a0b --- /dev/null +++ b/test/fixtures/tf_cloudbuild_workspace_simple_gitlab/variables.tf @@ -0,0 +1,37 @@ +/** + * Copyright 2024 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" { + description = "The ID of the project in which to provision resources." + type = string +} + +variable "repository_uri" { + description = "The HTTPS clone URL of the repository, ending with .git." + type = string +} + +variable "gitlab_authorizer_credential" { + description = "Credential for GitLab authorizer" + type = string + sensitive = true +} + +variable "gitlab_read_authorizer_credential" { + description = "Credential for GitLab read authorizer" + type = string + sensitive = true +} diff --git a/test/integration/tf_cloudbuild_builder_simple_github/tf_cloudbuild_builder_simple_github_test.go b/test/integration/tf_cloudbuild_builder_simple_github/tf_cloudbuild_builder_simple_github_test.go index 1f6770df..38693ba7 100644 --- a/test/integration/tf_cloudbuild_builder_simple_github/tf_cloudbuild_builder_simple_github_test.go +++ b/test/integration/tf_cloudbuild_builder_simple_github/tf_cloudbuild_builder_simple_github_test.go @@ -96,8 +96,9 @@ func TestTFCloudBuildBuilderGitHub(t *testing.T) { // Testing the module's feature of appending the ".git" suffix if it's missing repoURL := strings.TrimSuffix(client.repository.GetCloneURL(), ".git") vars := map[string]interface{}{ - "github_pat": githubPAT, - "repository_uri": repoURL, + "github_pat": githubPAT, + "repository_uri": repoURL, + "github_app_id": "47590865", // Found in the URL of your Cloud Build GitHub app configuration settings } bpt := tft.NewTFBlueprintTest(t, tft.WithVars(vars)) diff --git a/test/integration/tf_cloudbuild_builder_simple_gitlab/tf_cloudbuild_builder_simple_gitlab_test.go b/test/integration/tf_cloudbuild_builder_simple_gitlab/tf_cloudbuild_builder_simple_gitlab_test.go index 05632c92..2306326f 100644 --- a/test/integration/tf_cloudbuild_builder_simple_gitlab/tf_cloudbuild_builder_simple_gitlab_test.go +++ b/test/integration/tf_cloudbuild_builder_simple_gitlab/tf_cloudbuild_builder_simple_gitlab_test.go @@ -105,9 +105,9 @@ func TestTFCloudBuildBuilderGitLab(t *testing.T) { // Testing the module's feature of appending the ".git" suffix if it's missing // repoURL := strings.TrimSuffix(client.repository.GetCloneURL(), ".git") vars := map[string]interface{}{ - "gitlab_api_access_token": gitlabPAT, - "gitlab_read_api_access_token": gitlabPAT, - "repository_uri": client.project.HTTPURLToRepo, + "gitlab_authorizer_credential": gitlabPAT, + "gitlab_read_authorizer_credential": gitlabPAT, + "repository_uri": client.project.HTTPURLToRepo, } bpt := tft.NewTFBlueprintTest(t, tft.WithVars(vars)) diff --git a/test/integration/tf_cloudbuild_workspace_simple_github/tf_cloudbuild_workspace_simple_github_test.go b/test/integration/tf_cloudbuild_workspace_simple_github/tf_cloudbuild_workspace_simple_github_test.go index c33ac921..70840671 100644 --- a/test/integration/tf_cloudbuild_workspace_simple_github/tf_cloudbuild_workspace_simple_github_test.go +++ b/test/integration/tf_cloudbuild_workspace_simple_github/tf_cloudbuild_workspace_simple_github_test.go @@ -99,6 +99,7 @@ func TestCloudBuildWorkspaceSimpleGitHub(t *testing.T) { vars := map[string]interface{}{ "github_pat": githubPAT, "repository_uri": repoURL, + "github_app_id": "47590865", // Found in the URL of your Cloud Build GitHub app configuration settings } bpt := tft.NewTFBlueprintTest(t, tft.WithVars(vars)) @@ -121,7 +122,7 @@ func TestCloudBuildWorkspaceSimpleGitHub(t *testing.T) { triggerOP := utils.LastElement(bpt.GetStringOutput(fmt.Sprintf("cloudbuild_%s_trigger_id", trigger)), "/") cloudBuildOP := gcloud.Runf(t, "beta builds triggers describe %s --region %s --project %s", triggerOP, location, projectID) assert.Equal(fmt.Sprintf("%s-%s", repoName, trigger), cloudBuildOP.Get("name").String(), "should have the correct name") - assert.Equal(fmt.Sprintf("projects/%s/serviceAccounts/tf-cb-%s@%s.iam.gserviceaccount.com", projectID, repoName, projectID), cloudBuildOP.Get("serviceAccount").String(), "uses expected SA") + assert.Equal(fmt.Sprintf("projects/%s/serviceAccounts/tf-gh-%s@%s.iam.gserviceaccount.com", projectID, repoName, projectID), cloudBuildOP.Get("serviceAccount").String(), "uses expected SA") } // artifacts, state and log buckets @@ -187,9 +188,6 @@ func TestCloudBuildWorkspaceSimpleGitHub(t *testing.T) { } if latestWorkflowRunStatus == "TIMEOUT" || latestWorkflowRunStatus == "FAILURE" { t.Logf("%v", build[0]) - logs, err := gcloud.RunCmdE(t, fmt.Sprintf("builds log %s --region %s", build[0].Get("id"), location)) - t.Logf("err %v", err) - t.Logf("logs %s", logs) t.Fatalf("workflow %s failed with failureInfo %s", build[0].Get("id"), build[0].Get("failureInfo")) } return true, nil diff --git a/test/integration/tf_cloudbuild_workspace_simple_gitlab/tf_cloudbuild_workspace_simple_gitlab_test.go b/test/integration/tf_cloudbuild_workspace_simple_gitlab/tf_cloudbuild_workspace_simple_gitlab_test.go index b0bccac2..d4bf2037 100644 --- a/test/integration/tf_cloudbuild_workspace_simple_gitlab/tf_cloudbuild_workspace_simple_gitlab_test.go +++ b/test/integration/tf_cloudbuild_workspace_simple_gitlab/tf_cloudbuild_workspace_simple_gitlab_test.go @@ -114,9 +114,9 @@ func TestCloudBuildWorkspaceSimpleGitLab(t *testing.T) { } vars := map[string]interface{}{ - "gitlab_api_access_token": gitlabPAT, - "gitlab_read_api_access_token": gitlabPAT, - "repository_uri": client.project.HTTPURLToRepo, + "gitlab_authorizer_credential": gitlabPAT, + "gitlab_read_authorizer_credential": gitlabPAT, + "repository_uri": client.project.HTTPURLToRepo, } bpt := tft.NewTFBlueprintTest(t, tft.WithVars(vars)) @@ -207,9 +207,6 @@ func TestCloudBuildWorkspaceSimpleGitLab(t *testing.T) { } if latestWorkflowRunStatus == "TIMEOUT" || latestWorkflowRunStatus == "FAILURE" { t.Logf("%v", build[0]) - logs, err := gcloud.RunCmdE(t, fmt.Sprintf("builds log %s --region %s", build[0].Get("id"), location)) - t.Logf("err %v", err) - t.Logf("logs %s", logs) t.Fatalf("workflow %s failed with status %s", build[0].Get("id"), latestWorkflowRunStatus) return false, nil } diff --git a/variables.tf b/variables.tf index cbf2d722..42786152 100644 --- a/variables.tf +++ b/variables.tf @@ -78,6 +78,12 @@ variable "project_deletion_policy" { default = "PREVENT" } +variable "project_auto_create_network" { + description = "Create the default network for the project created." + type = bool + default = false +} + variable "activate_apis" { description = "List of APIs to enable in the seed project." type = list(string)