diff --git a/build/int.cloudbuild.yaml b/build/int.cloudbuild.yaml index f587eb6..63c73ab 100644 --- a/build/int.cloudbuild.yaml +++ b/build/int.cloudbuild.yaml @@ -21,9 +21,166 @@ steps: - 'TF_VAR_org_id=$_ORG_ID' - 'TF_VAR_folder_id=$_FOLDER_ID' - 'TF_VAR_billing_account=$_BILLING_ACCOUNT' + secretEnv: ['TFE_TOKEN'] +- id: sleep + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'sleep 120'] + waitFor: + - "prepare" +- id: docker-push + name: "gcr.io/cloud-builders/docker" + script: | + #!/usr/bin/env bash + source test/setup/outputs.env + docker build -t us-central1-docker.pkg.dev/$_SETUP_PROJECT_ID/hashicorp/tfc-agent:latest -f examples/tfc-agent-gke-custom/Dockerfile examples/tfc-agent-gke-custom + docker push us-central1-docker.pkg.dev/$_SETUP_PROJECT_ID/hashicorp/tfc-agent:latest + waitFor: + - "sleep" +- id: packer-init + name: 'hashicorp/packer:1.9.1' + script: | + #!/usr/bin/env bash + source test/setup/outputs.env + packer init -var project_id=$_SETUP_PROJECT_ID examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl + waitFor: + - "sleep" + env: + - 'TFC_AGENT_VERSION=$_TFC_AGENT_VERSION' +- id: packer-build + name: 'hashicorp/packer:1.9.1' + script: | + #!/usr/bin/env bash + source test/setup/outputs.env + packer build -force -var project_id=$_SETUP_PROJECT_ID examples/tfc-agent-mig-vm-packer/packer + env: + - 'TFC_AGENT_VERSION=$_TFC_AGENT_VERSION' + waitFor: + - "packer-init" +- id: init-all + waitFor: + - "sleep" + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose'] +- id: apply-oidc + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestOidcSimple --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" +- id: verify-oidc + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestOidcSimple --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-oidc" +- id: destroy-oidc + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestOidcSimple --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-oidc" +- id: apply-gke-custom + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeCustom --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" + - "docker-push" +- id: verify-gke-custom + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeCustom --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-gke-custom" +- id: destroy-gke-custom + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeCustom --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-gke-custom" +- id: apply-gke-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeSimple --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" +- id: verify-gke-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeSimple --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-gke-simple" +- id: destroy-gke-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentGkeSimple --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-gke-simple" +- id: apply-mig-con-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigContainerVmSimple --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" +- id: verify-mig-con-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigContainerVmSimple --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-mig-con-simple" +- id: destroy-mig-con-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigContainerVmSimple --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-mig-con-simple" +- id: apply-mig-packer + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmPacker --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" + - "packer-build" +- id: verify-mig-packer + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmPacker --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-mig-packer" +- id: destroy-mig-packer + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmPacker --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-mig-packer" +- id: apply-mig-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmSimple --stage apply --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "init-all" +- id: verify-mig-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmSimple --stage verify --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "apply-mig-simple" +- id: destroy-mig-simple + name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS' + args: ['/bin/bash', '-c', 'cft test run TestTfcAgentMigVmSimple --stage destroy --verbose'] + secretEnv: ['TFE_TOKEN'] + waitFor: + - "verify-mig-simple" tags: - 'ci' - 'integration' substitutions: _DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools' - _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1' + _DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.14' + _TFC_AGENT_VERSION: '1.12.0' +availableSecrets: + secretManager: + - versionName: $_TFE_TOKEN_SECRET_ID/versions/latest + env: 'TFE_TOKEN' +options: + machineType: 'E2_HIGHCPU_32' diff --git a/examples/oidc-simple/README.md b/examples/oidc-simple/README.md index acc6310..3ba0a42 100644 --- a/examples/oidc-simple/README.md +++ b/examples/oidc-simple/README.md @@ -20,6 +20,7 @@ This example showcases how to configure [Workload Identity Federation](https://c | Name | Description | |------|-------------| | pool\_name | Pool name | +| project\_id | The project id to create Workload Identity Federation pool and example Service Account | | provider\_name | Provider name | | sa\_email | Example SA email | diff --git a/examples/oidc-simple/main.tf b/examples/oidc-simple/main.tf index ea7dc72..0424f57 100644 --- a/examples/oidc-simple/main.tf +++ b/examples/oidc-simple/main.tf @@ -19,6 +19,11 @@ data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" +} + # Random ID for the workload_identity_pool_id # will avoid errors due to GCP's 30-day hold on deleted pools resource "random_string" "suffix" { @@ -29,13 +34,13 @@ resource "random_string" "suffix" { # Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } # Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id } diff --git a/examples/oidc-simple/outputs.tf b/examples/oidc-simple/outputs.tf index 19bdeca..f3cd942 100644 --- a/examples/oidc-simple/outputs.tf +++ b/examples/oidc-simple/outputs.tf @@ -14,6 +14,11 @@ * limitations under the License. */ +output "project_id" { + description = "The project id to create Workload Identity Federation pool and example Service Account" + value = var.project_id +} + output "pool_name" { description = "Pool name" value = module.oidc.pool_name diff --git a/examples/tfc-agent-gke-custom/README.md b/examples/tfc-agent-gke-custom/README.md index 8c033ce..ab65005 100644 --- a/examples/tfc-agent-gke-custom/README.md +++ b/examples/tfc-agent-gke-custom/README.md @@ -79,7 +79,7 @@ If running from your own system, you will need: | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-gke-custom-pool"` | no | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-gke-custom-pool-token"` | no | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | -| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents GKE"` | no | +| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents GKE custom"` | no | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-gke-custom"` | no | ## Outputs @@ -87,11 +87,11 @@ If running from your own system, you will need: | Name | Description | |------|-------------| | ca\_certificate | The cluster CA certificate (base64 encoded) | -| client\_token | The bearer token for auth | | cluster\_name | GKE cluster name | | kubernetes\_endpoint | The cluster endpoint | | location | GKE cluster location | | network\_name | Name of the VPC | +| project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | | service\_account | The default service account used for TFC agent nodes | | subnet\_name | Name of the subnet in the VPC | diff --git a/examples/tfc-agent-gke-custom/main.tf b/examples/tfc-agent-gke-custom/main.tf index 888e771..c8ac361 100644 --- a/examples/tfc-agent-gke-custom/main.tf +++ b/examples/tfc-agent-gke-custom/main.tf @@ -22,15 +22,28 @@ data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" + tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" + network_name = "tfc-gke-custom-${random_string.suffix.result}" +} + +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + # Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } # Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id agent_pool_id = tfe_agent_pool.tfc_agent_pool.id @@ -39,7 +52,7 @@ resource "tfe_workspace" "tfc_workspace" { # Create a new agent pool in organization resource "tfe_agent_pool" "tfc_agent_pool" { - name = var.tfc_agent_pool_name + name = local.tfc_agent_pool organization = data.tfe_organization.tfc_org.name } @@ -49,24 +62,36 @@ resource "tfe_agent_token" "tfc_agent_token" { description = var.tfc_agent_pool_token_description } -# Allow GKE to pull images from Google Artifact Registry +# Allow GKE to view storage objects resource "google_project_iam_member" "gar_viewer" { project = var.project_id role = "roles/storage.objectViewer" - member = "serviceAccount:${module.tfc_agent_gke.service_account}" + member = "serviceAccount:${google_service_account.tfc_agent_service_account.email}" } +# Allow GKE to pull images from Google Artifact Registry resource "google_project_iam_member" "gar_reader" { project = var.project_id role = "roles/artifactregistry.reader" - member = "serviceAccount:${module.tfc_agent_gke.service_account}" + member = "serviceAccount:${google_service_account.tfc_agent_service_account.email}" +} + +# Create a new service account for the GKE cluster +resource "google_service_account" "tfc_agent_service_account" { + project = var.project_id + account_id = "tfc-agent-gke-custom" + display_name = "Terraform Cloud agent GKE Service Account" } # Create the infrastructure for the agent to run module "tfc_agent_gke" { - source = "../../modules/tfc-agent-gke" - create_network = true - project_id = var.project_id - tfc_agent_image = var.tfc_agent_image - tfc_agent_token = tfe_agent_token.tfc_agent_token.token + source = "../../modules/tfc-agent-gke" + create_network = true + network_name = local.network_name + subnet_name = local.network_name + project_id = var.project_id + tfc_agent_image = var.tfc_agent_image + tfc_agent_token = tfe_agent_token.tfc_agent_token.token + create_service_account = false + service_account_email = google_service_account.tfc_agent_service_account.email } diff --git a/examples/tfc-agent-gke-custom/outputs.tf b/examples/tfc-agent-gke-custom/outputs.tf index 9c30072..5a18ce9 100644 --- a/examples/tfc-agent-gke-custom/outputs.tf +++ b/examples/tfc-agent-gke-custom/outputs.tf @@ -14,18 +14,17 @@ * limitations under the License. */ +output "project_id" { + description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" + value = var.project_id +} + output "kubernetes_endpoint" { description = "The cluster endpoint" sensitive = true value = module.tfc_agent_gke.kubernetes_endpoint } -output "client_token" { - description = "The bearer token for auth" - sensitive = true - value = module.tfc_agent_gke.client_token -} - output "ca_certificate" { description = "The cluster CA certificate (base64 encoded)" sensitive = true diff --git a/examples/tfc-agent-gke-custom/variables.tf b/examples/tfc-agent-gke-custom/variables.tf index 37fb65c..405cb7c 100644 --- a/examples/tfc-agent-gke-custom/variables.tf +++ b/examples/tfc-agent-gke-custom/variables.tf @@ -27,7 +27,7 @@ variable "tfc_org_name" { variable "tfc_project_name" { type = string description = "Terraform Cloud project name to be created" - default = "GCP agents GKE" + default = "GCP agents GKE custom" } variable "tfc_workspace_name" { diff --git a/examples/tfc-agent-gke-simple/README.md b/examples/tfc-agent-gke-simple/README.md index 4a11f66..b9e1168 100644 --- a/examples/tfc-agent-gke-simple/README.md +++ b/examples/tfc-agent-gke-simple/README.md @@ -44,9 +44,9 @@ If running from your own system, you will need: |------|-------------|------|---------|:--------:| | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | `string` | n/a | yes | | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-gke-simple-pool"` | no | -| tfc\_agent\_pool\_token\_description\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-gke-simple-pool-token"` | no | +| tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-gke-simple-pool-token"` | no | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | -| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents GKE"` | no | +| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents GKE simple"` | no | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-gke-simple"` | no | ## Outputs @@ -54,11 +54,11 @@ If running from your own system, you will need: | Name | Description | |------|-------------| | ca\_certificate | The cluster CA certificate (base64 encoded) | -| client\_token | The bearer token for auth | | cluster\_name | GKE cluster name | | kubernetes\_endpoint | The GKE cluster endpoint | | location | GKE cluster location | | network\_name | Name of the VPC | +| project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | | service\_account | The default service account used for TFC agent nodes | | subnet\_name | Name of the subnet in the VPC | diff --git a/examples/tfc-agent-gke-simple/main.tf b/examples/tfc-agent-gke-simple/main.tf index 023492c..f3899b0 100644 --- a/examples/tfc-agent-gke-simple/main.tf +++ b/examples/tfc-agent-gke-simple/main.tf @@ -22,15 +22,28 @@ data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" + tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" + network_name = "tfc-gke-simple-${random_string.suffix.result}" +} + +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + # Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } # Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id agent_pool_id = tfe_agent_pool.tfc_agent_pool.id @@ -39,20 +52,31 @@ resource "tfe_workspace" "tfc_workspace" { # Create a new agent pool in organization resource "tfe_agent_pool" "tfc_agent_pool" { - name = var.tfc_agent_pool_name + name = local.tfc_agent_pool organization = data.tfe_organization.tfc_org.name } # Create a new token for the agent pool resource "tfe_agent_token" "tfc_agent_token" { agent_pool_id = tfe_agent_pool.tfc_agent_pool.id - description = var.tfc_agent_pool_token_description_description + description = var.tfc_agent_pool_token_description +} + +# Create a new service account for the GKE cluster +resource "google_service_account" "tfc_agent_service_account" { + project = var.project_id + account_id = "tfc-agent-gke-simple" + display_name = "Terraform Cloud agent GKE Service Account" } # Create the infrastructure for the agent to run module "tfc_agent_gke" { - source = "../../modules/tfc-agent-gke" - create_network = true - project_id = var.project_id - tfc_agent_token = tfe_agent_token.tfc_agent_token.token + source = "../../modules/tfc-agent-gke" + create_network = true + network_name = local.network_name + subnet_name = local.network_name + project_id = var.project_id + tfc_agent_token = tfe_agent_token.tfc_agent_token.token + create_service_account = false + service_account_email = google_service_account.tfc_agent_service_account.email } diff --git a/examples/tfc-agent-gke-simple/outputs.tf b/examples/tfc-agent-gke-simple/outputs.tf index b2c6df3..e7afe48 100644 --- a/examples/tfc-agent-gke-simple/outputs.tf +++ b/examples/tfc-agent-gke-simple/outputs.tf @@ -14,18 +14,17 @@ * limitations under the License. */ +output "project_id" { + description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster" + value = var.project_id +} + output "kubernetes_endpoint" { description = "The GKE cluster endpoint" sensitive = true value = module.tfc_agent_gke.kubernetes_endpoint } -output "client_token" { - description = "The bearer token for auth" - sensitive = true - value = module.tfc_agent_gke.client_token -} - output "ca_certificate" { description = "The cluster CA certificate (base64 encoded)" sensitive = true diff --git a/examples/tfc-agent-gke-simple/variables.tf b/examples/tfc-agent-gke-simple/variables.tf index 34e594c..288e6ea 100644 --- a/examples/tfc-agent-gke-simple/variables.tf +++ b/examples/tfc-agent-gke-simple/variables.tf @@ -27,7 +27,7 @@ variable "tfc_org_name" { variable "tfc_project_name" { type = string description = "Terraform Cloud project name to be created" - default = "GCP agents GKE" + default = "GCP agents GKE simple" } variable "tfc_workspace_name" { @@ -42,7 +42,7 @@ variable "tfc_agent_pool_name" { default = "tfc-agent-gke-simple-pool" } -variable "tfc_agent_pool_token_description_description" { +variable "tfc_agent_pool_token_description" { type = string description = "Terraform Cloud agent pool token description" default = "tfc-agent-gke-simple-pool-token" diff --git a/examples/tfc-agent-mig-container-vm-simple/README.md b/examples/tfc-agent-mig-container-vm-simple/README.md index bda0d5b..47cd5ff 100644 --- a/examples/tfc-agent-mig-container-vm-simple/README.md +++ b/examples/tfc-agent-mig-container-vm-simple/README.md @@ -48,6 +48,7 @@ It creates the Terraform Cloud agent pool, registers the agent to that pool and | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | -| service\_account | Service account email used with the MIG template | +| project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | +| service\_account\_email | Service account email used with the MIG template | diff --git a/examples/tfc-agent-mig-container-vm-simple/main.tf b/examples/tfc-agent-mig-container-vm-simple/main.tf index 0af20d8..0f8cc93 100644 --- a/examples/tfc-agent-mig-container-vm-simple/main.tf +++ b/examples/tfc-agent-mig-container-vm-simple/main.tf @@ -18,24 +18,41 @@ data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" + tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" + network_name = "tfc-containter-vm-${random_string.suffix.result}" +} + +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + +# Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } +# Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id agent_pool_id = tfe_agent_pool.tfc_agent_pool.id execution_mode = "agent" } +# Create a new agent pool in organization resource "tfe_agent_pool" "tfc_agent_pool" { - name = var.tfc_agent_pool_name + name = local.tfc_agent_pool organization = data.tfe_organization.tfc_org.name } +# Create a new token for the agent pool resource "tfe_agent_token" "tfc_agent_token" { agent_pool_id = tfe_agent_pool.tfc_agent_pool.id description = var.tfc_agent_pool_token_description @@ -44,6 +61,8 @@ resource "tfe_agent_token" "tfc_agent_token" { module "tfc_agent_mig" { source = "../../modules/tfc-agent-mig-container-vm" create_network = true + network_name = local.network_name + subnet_name = local.network_name project_id = var.project_id tfc_agent_token = tfe_agent_token.tfc_agent_token.token } diff --git a/examples/tfc-agent-mig-container-vm-simple/outputs.tf b/examples/tfc-agent-mig-container-vm-simple/outputs.tf index 696d095..049fcb7 100644 --- a/examples/tfc-agent-mig-container-vm-simple/outputs.tf +++ b/examples/tfc-agent-mig-container-vm-simple/outputs.tf @@ -14,6 +14,11 @@ * limitations under the License. */ +output "project_id" { + description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" + value = var.project_id +} + output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.tfc_agent_mig.mig_instance_group @@ -24,9 +29,9 @@ output "mig_name" { value = module.tfc_agent_mig.mig_name } -output "service_account" { +output "service_account_email" { description = "Service account email used with the MIG template" - value = module.tfc_agent_mig.service_account + value = module.tfc_agent_mig.service_account_email } output "mig_instance_template" { diff --git a/examples/tfc-agent-mig-vm-packer/README.md b/examples/tfc-agent-mig-vm-packer/README.md index 4ed486d..0c8d38b 100644 --- a/examples/tfc-agent-mig-vm-packer/README.md +++ b/examples/tfc-agent-mig-vm-packer/README.md @@ -20,7 +20,7 @@ In this example, Packer creates a VM image that has the following: ```sh # Export required variables export PROJECT_ID="your_gcp_project_id" - export TFC_AGENT_VERSION="1.10.1" + export TFC_AGENT_VERSION="1.12.0" # GCP commands to enable services gcloud config set project $PROJECT_ID @@ -73,7 +73,7 @@ In this example, Packer creates a VM image that has the following: | tfc\_agent\_pool\_name | Terraform Cloud agent pool name to be created | `string` | `"tfc-agent-mig-vm-packer-pool"` | no | | tfc\_agent\_pool\_token\_description | Terraform Cloud agent pool token description | `string` | `"tfc-agent-mig-vm-packer-pool-token"` | no | | tfc\_org\_name | Terraform Cloud org name where the agent pool will be created | `string` | n/a | yes | -| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents custom VM"` | no | +| tfc\_project\_name | Terraform Cloud project name to be created | `string` | `"GCP agents Packer"` | no | | tfc\_workspace\_name | Terraform Cloud workspace name to be created | `string` | `"tfc-agent-mig-vm-packer"` | no | ## Outputs @@ -83,6 +83,7 @@ In this example, Packer creates a VM image that has the following: | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | -| service\_account | Service account email for GCE used with the MIG template | +| project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | +| service\_account\_email | Service account email for GCE used with the MIG template | diff --git a/examples/tfc-agent-mig-vm-packer/cloudbuild.yaml b/examples/tfc-agent-mig-vm-packer/cloudbuild.yaml index 6d3ba6b..71c773f 100644 --- a/examples/tfc-agent-mig-vm-packer/cloudbuild.yaml +++ b/examples/tfc-agent-mig-vm-packer/cloudbuild.yaml @@ -24,6 +24,7 @@ steps: - name: 'hashicorp/packer:1.9.1' args: - build + - --force - -var - project_id=$PROJECT_ID - -var diff --git a/examples/tfc-agent-mig-vm-packer/main.tf b/examples/tfc-agent-mig-vm-packer/main.tf index ace0159..fd6b38a 100644 --- a/examples/tfc-agent-mig-vm-packer/main.tf +++ b/examples/tfc-agent-mig-vm-packer/main.tf @@ -18,35 +18,64 @@ data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" + tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" + network_name = "tfc-vm-packer-${random_string.suffix.result}" +} + +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + +# Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } +# Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id agent_pool_id = tfe_agent_pool.tfc_agent_pool.id execution_mode = "agent" } +# Create a new agent pool in organization resource "tfe_agent_pool" "tfc_agent_pool" { - name = var.tfc_agent_pool_name + name = local.tfc_agent_pool organization = data.tfe_organization.tfc_org.name } +# Create a new token for the agent pool resource "tfe_agent_token" "tfc_agent_token" { agent_pool_id = tfe_agent_pool.tfc_agent_pool.id description = var.tfc_agent_pool_token_description } +# Create a new service account +resource "google_service_account" "tfc_agent_service_account" { + project = var.project_id + account_id = "tfc-agent-mig-vm-psa" + display_name = "Terraform Cloud agent VM packer Service Account" +} + +# Create the infrastructure for the agent to run module "tfc_agent_mig" { - source = "../../modules/tfc-agent-mig-vm" - create_network = true - project_id = var.project_id - source_image = var.source_image - source_image_project = var.source_image_project != null ? var.source_image_project : var.project_id - startup_script = file("${path.cwd}/startup.sh") - tfc_agent_token = tfe_agent_token.tfc_agent_token.token + source = "../../modules/tfc-agent-mig-vm" + create_network = true + network_name = local.network_name + subnet_name = local.network_name + project_id = var.project_id + source_image = var.source_image + source_image_project = var.source_image_project != null ? var.source_image_project : var.project_id + startup_script = file("${path.cwd}/startup.sh") + tfc_agent_token = tfe_agent_token.tfc_agent_token.token + create_service_account = false + service_account_email = google_service_account.tfc_agent_service_account.email } diff --git a/examples/tfc-agent-mig-vm-packer/outputs.tf b/examples/tfc-agent-mig-vm-packer/outputs.tf index 036b510..ad448d9 100644 --- a/examples/tfc-agent-mig-vm-packer/outputs.tf +++ b/examples/tfc-agent-mig-vm-packer/outputs.tf @@ -14,6 +14,11 @@ * limitations under the License. */ +output "project_id" { + description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" + value = var.project_id +} + output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.tfc_agent_mig.mig_instance_group @@ -24,9 +29,9 @@ output "mig_name" { value = module.tfc_agent_mig.mig_name } -output "service_account" { +output "service_account_email" { description = "Service account email for GCE used with the MIG template" - value = module.tfc_agent_mig.service_account + value = module.tfc_agent_mig.service_account_email } output "mig_instance_template" { diff --git a/examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl b/examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl index 1af9bb0..07c066a 100644 --- a/examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl +++ b/examples/tfc-agent-mig-vm-packer/packer/packer.pkr.hcl @@ -77,6 +77,12 @@ variable "ssh_username" { default = "ubuntu" } +variable "tfc_agent_image" { + type = string + description = "The name of the Terraform Cloud image to use" + default = "tfc-agent-image" +} + variable "tfc_agent_version" { type = string description = "Version of the Terraform Cloud agent to install in the image" @@ -89,11 +95,6 @@ variable "zone" { default = "us-central1-a" } -locals { - timestamp = regex_replace(timestamp(), "[- TZ:]", "") - image_name = "tfc-agent-image-${local.timestamp}" -} - source "googlecompute" "agent" { project_id = var.project_id source_image_family = var.source_image_family @@ -103,9 +104,8 @@ source "googlecompute" "agent" { disk_size = var.disk_size disk_type = var.disk_type ssh_username = var.ssh_username - image_name = local.image_name + image_name = var.tfc_agent_image image_family = var.image_family - use_os_login = true disable_default_service_account = false } @@ -120,32 +120,10 @@ build { "apt-get update", "apt-get dist-upgrade -q -y", "apt-get update", - "apt-get install -q -y apt-transport-https ca-certificates curl unzip tar jq build-essential gnupg2 software-properties-common", - "install -m 0755 -d /etc/apt/keyrings", - "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg", - "chmod a+r /etc/apt/keyrings/docker.gpg", - "echo \"deb [arch=\"$(dpkg --print-architecture)\" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \"$(. /etc/os-release && echo \"$VERSION_CODENAME\")\" stable\" | tee /etc/apt/sources.list.d/docker.list > /dev/null", - "apt-get update", - "apt-get install -y docker-ce", - "usermod -aG docker ubuntu" - ] - } - - provisioner "shell" { - environment_vars = ["DEBIAN_FRONTEND=noninteractive"] - execute_command = "sudo -S sh -c '{{ .Vars }} {{ .Path }}'" - inline = [ + "apt-get install -q -y apt-transport-https ca-certificates curl unzip", "curl -s -O https://releases.hashicorp.com/tfc-agent/${var.tfc_agent_version}/tfc-agent_${var.tfc_agent_version}_linux_amd64.zip", - "curl -s -O https://releases.hashicorp.com/tfc-agent/${var.tfc_agent_version}/tfc-agent_${var.tfc_agent_version}_SHA256SUMS", - "curl -s -O https://releases.hashicorp.com/tfc-agent/${var.tfc_agent_version}/tfc-agent_${var.tfc_agent_version}_SHA256SUMS.sig", - "curl -s -o hashicorp.asc https://www.hashicorp.com/.well-known/pgp-key.txt", - "gpg --import hashicorp.asc", - "gpg --verify tfc-agent_${var.tfc_agent_version}_SHA256SUMS.sig tfc-agent_${var.tfc_agent_version}_SHA256SUMS", - "shasum -a 256 -c tfc-agent_${var.tfc_agent_version}_SHA256SUMS", "mkdir /agent", "unzip tfc-agent_${var.tfc_agent_version}_linux_amd64.zip -d /agent", - "rm tfc-agent_${var.tfc_agent_version}_SHA256SUMS", - "rm tfc-agent_${var.tfc_agent_version}_SHA256SUMS.sig", "rm -f tfc-agent_${var.tfc_agent_version}_linux_amd64.zip" ] } diff --git a/examples/tfc-agent-mig-vm-packer/variables.tf b/examples/tfc-agent-mig-vm-packer/variables.tf index 7820be5..0cb8473 100644 --- a/examples/tfc-agent-mig-vm-packer/variables.tf +++ b/examples/tfc-agent-mig-vm-packer/variables.tf @@ -27,7 +27,7 @@ variable "tfc_org_name" { variable "tfc_project_name" { type = string description = "Terraform Cloud project name to be created" - default = "GCP agents custom VM" + default = "GCP agents Packer" } variable "tfc_workspace_name" { diff --git a/examples/tfc-agent-mig-vm-simple/README.md b/examples/tfc-agent-mig-vm-simple/README.md index c30f3e6..db498ab 100644 --- a/examples/tfc-agent-mig-vm-simple/README.md +++ b/examples/tfc-agent-mig-vm-simple/README.md @@ -46,6 +46,7 @@ It creates the Terraform Cloud agent pool, registers the agent to that pool and | mig\_instance\_group | The instance group url of the created MIG | | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | -| service\_account | Service account email used with the MIG template | +| project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG | +| service\_account\_email | Service account email used with the MIG template | diff --git a/examples/tfc-agent-mig-vm-simple/main.tf b/examples/tfc-agent-mig-vm-simple/main.tf index 1b0c9e5..7f99e6f 100644 --- a/examples/tfc-agent-mig-vm-simple/main.tf +++ b/examples/tfc-agent-mig-vm-simple/main.tf @@ -14,36 +14,66 @@ * limitations under the License. */ +# Get the Terraform Cloud organization data "tfe_organization" "tfc_org" { name = var.tfc_org_name } +locals { + tfc_project = "${var.tfc_project_name} ${random_string.suffix.result}" + tfc_workspace = "${var.tfc_workspace_name}-${random_string.suffix.result}" + tfc_agent_pool = "${var.tfc_agent_pool_name}-${random_string.suffix.result}" + network_name = "tfc-vm-simple-${random_string.suffix.result}" +} + +resource "random_string" "suffix" { + length = 4 + special = false + upper = false +} + +# Create a new project in Terraform Cloud resource "tfe_project" "tfc_project" { + name = local.tfc_project organization = data.tfe_organization.tfc_org.name - name = var.tfc_project_name } +# Create a new workspace which uses the agent to run Terraform resource "tfe_workspace" "tfc_workspace" { - name = var.tfc_workspace_name + name = local.tfc_workspace organization = data.tfe_organization.tfc_org.name project_id = tfe_project.tfc_project.id agent_pool_id = tfe_agent_pool.tfc_agent_pool.id execution_mode = "agent" } +# Create a new agent pool in organization resource "tfe_agent_pool" "tfc_agent_pool" { - name = var.tfc_agent_pool_name + name = local.tfc_agent_pool organization = data.tfe_organization.tfc_org.name } +# Create a new token for the agent pool resource "tfe_agent_token" "tfc_agent_token" { agent_pool_id = tfe_agent_pool.tfc_agent_pool.id description = var.tfc_agent_pool_token_description } +# Create a new service account +resource "google_service_account" "tfc_agent_service_account" { + project = var.project_id + account_id = "tfc-agent-mig-vm-sa" + display_name = "Terraform Cloud agent VM simple Service Account" +} + +# Create the infrastructure for the agent to run module "tfc_agent_mig" { - source = "../../modules/tfc-agent-mig-vm" - create_network = true - project_id = var.project_id - tfc_agent_token = tfe_agent_token.tfc_agent_token.token + source = "../../modules/tfc-agent-mig-vm" + project_id = var.project_id + create_network = true + network_name = local.network_name + subnet_name = local.network_name + tfc_agent_token = tfe_agent_token.tfc_agent_token.token + create_service_account = false + service_account_email = google_service_account.tfc_agent_service_account.email } diff --git a/examples/tfc-agent-mig-vm-simple/outputs.tf b/examples/tfc-agent-mig-vm-simple/outputs.tf index 696d095..049fcb7 100644 --- a/examples/tfc-agent-mig-vm-simple/outputs.tf +++ b/examples/tfc-agent-mig-vm-simple/outputs.tf @@ -14,6 +14,11 @@ * limitations under the License. */ +output "project_id" { + description = "The Google Cloud Platform project ID to deploy Terraform Cloud agent MIG" + value = var.project_id +} + output "mig_instance_group" { description = "The instance group url of the created MIG" value = module.tfc_agent_mig.mig_instance_group @@ -24,9 +29,9 @@ output "mig_name" { value = module.tfc_agent_mig.mig_name } -output "service_account" { +output "service_account_email" { description = "Service account email used with the MIG template" - value = module.tfc_agent_mig.service_account + value = module.tfc_agent_mig.service_account_email } output "mig_instance_template" { diff --git a/modules/tfc-agent-gke/README.md b/modules/tfc-agent-gke/README.md index e7ea091..2910bc7 100644 --- a/modules/tfc-agent-gke/README.md +++ b/modules/tfc-agent-gke/README.md @@ -25,6 +25,7 @@ This example shows how to deploy a custom Terraform Cloud agent image with GKE. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | create\_network | When set to true, VPC will be auto created | `bool` | `true` | no | +| create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | | ip\_range\_pods\_cidr | The secondary IP range CIDR to use for pods | `string` | `"192.168.0.0/18"` | no | | ip\_range\_pods\_name | The secondary IP range to use for pods | `string` | `"ip-range-pods"` | no | | ip\_range\_services\_cider | The secondary IP range CIDR to use for services | `string` | `"192.168.64.0/18"` | no | @@ -36,7 +37,7 @@ This example shows how to deploy a custom Terraform Cloud agent image with GKE. | network\_project\_id | The project ID of the shared VPCs host (for shared vpc support).
If not provided, the project\_id is used | `string` | `""` | no | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent cluster | `string` | n/a | yes | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | -| service\_account | Optional Service Account for the GKE nodes | `string` | `""` | no | +| service\_account\_email | Optional Service Account for the GKE nodes, required if create\_service\_account is set to false | `string` | `""` | no | | subnet\_ip | IP range for the subnet | `string` | `"10.0.0.0/17"` | no | | subnet\_name | Name for the subnet | `string` | `"tfc-agent-subnet"` | no | | tfc\_agent\_address | The HTTP or HTTPS address of the Terraform Cloud/Enterprise API | `string` | `"https://app.terraform.io"` | no | @@ -46,7 +47,7 @@ This example shows how to deploy a custom Terraform Cloud agent image with GKE. | tfc\_agent\_k8s\_secrets | Name for the k8s secret required to configure TFC agent on GKE | `string` | `"tfc-agent-k8s-secrets"` | no | | tfc\_agent\_max\_replicas | Maximum replicas for the Terraform Cloud Agent pod autoscaler | `string` | `"10"` | no | | tfc\_agent\_memory\_request | Memory request for the Terraform Cloud agent container | `string` | `"2Gi"` | no | -| tfc\_agent\_min\_replicas | Minimum replicas for the Terraform Cloud Agent pod autoscaler | `string` | `"2"` | no | +| tfc\_agent\_min\_replicas | Minimum replicas for the Terraform Cloud Agent pod autoscaler | `string` | `"1"` | no | | tfc\_agent\_name\_prefix | This name may be used in the Terraform Cloud user interface to help easily identify the agent | `string` | `"tfc-agent-k8s"` | no | | tfc\_agent\_single | Enable single mode. This causes the agent to handle at most one job and
immediately exit thereafter. Useful for running agents as ephemeral
containers, VMs, or other isolated contexts with a higher-level scheduler
or process supervisor. | `bool` | `false` | no | | tfc\_agent\_token | Terraform Cloud agent token. (Organization Settings >> Agents) | `string` | n/a | yes | diff --git a/modules/tfc-agent-gke/main.tf b/modules/tfc-agent-gke/main.tf index fde48b0..527fcbb 100644 --- a/modules/tfc-agent-gke/main.tf +++ b/modules/tfc-agent-gke/main.tf @@ -15,10 +15,10 @@ */ locals { - network_name = var.create_network ? google_compute_network.tfc_agent_network[0].name : var.network_name - subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].name : var.subnet_name - service_account = var.service_account == "" ? "create" : var.service_account - tfc_agent_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" + network_name = var.create_network ? google_compute_network.tfc_agent_network[0].name : var.network_name + subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].name : var.subnet_name + service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email + tfc_agent_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" } resource "random_string" "suffix" { @@ -56,6 +56,17 @@ resource "google_compute_subnetwork" "tfc_agent_subnetwork" { ] } +/***************************************** + IAM Bindings GKE + *****************************************/ + +resource "google_service_account" "tfc_agent_service_account" { + count = var.create_service_account ? 1 : 0 + project = var.project_id + account_id = "tfc-agent-gke" + display_name = "Terraform Cloud agent GKE Service Account" +} + /***************************************** TFC agent GKE *****************************************/ @@ -69,7 +80,7 @@ module "tfc_agent_cluster" { network = local.network_name name = local.tfc_agent_name subnetwork = local.subnet_name - service_account = local.service_account + service_account = local.service_account_email network_project_id = var.network_project_id != "" ? var.network_project_id : var.project_id ip_range_pods = var.ip_range_pods_name ip_range_services = var.ip_range_services_name @@ -77,6 +88,7 @@ module "tfc_agent_cluster" { monitoring_service = "monitoring.googleapis.com/kubernetes" remove_default_node_pool = true regional = false + gce_pd_csi_driver = true node_pools = [ { name = "tfc-agent-pool" diff --git a/modules/tfc-agent-gke/variables.tf b/modules/tfc-agent-gke/variables.tf index 44789bf..104ea33 100644 --- a/modules/tfc-agent-gke/variables.tf +++ b/modules/tfc-agent-gke/variables.tf @@ -106,9 +106,15 @@ variable "min_node_count" { default = 2 } -variable "service_account" { +variable "create_service_account" { + description = "Set to true to create a new service account, false to use an existing one" + type = bool + default = true +} + +variable "service_account_email" { type = string - description = "Optional Service Account for the GKE nodes" + description = "Optional Service Account for the GKE nodes, required if create_service_account is set to false" default = "" } @@ -174,7 +180,7 @@ variable "tfc_agent_token" { variable "tfc_agent_min_replicas" { type = string description = "Minimum replicas for the Terraform Cloud Agent pod autoscaler" - default = "2" + default = "1" } variable "tfc_agent_max_replicas" { diff --git a/modules/tfc-agent-gke/versions.tf b/modules/tfc-agent-gke/versions.tf index 6243c6b..f74325d 100644 --- a/modules/tfc-agent-gke/versions.tf +++ b/modules/tfc-agent-gke/versions.tf @@ -38,3 +38,11 @@ terraform { module_name = "blueprints/terraform/terraform-google-tf-cloud-agents:tfc-agent-gke/v0.0.1" } } + +provider "kubernetes" { + host = "https://${module.tfc_agent_cluster.endpoint}" + token = data.google_client_config.default.access_token + cluster_ca_certificate = base64decode( + module.tfc_agent_cluster.ca_certificate + ) +} diff --git a/modules/tfc-agent-mig-container-vm/README.md b/modules/tfc-agent-mig-container-vm/README.md index e14e8f5..b463a96 100644 --- a/modules/tfc-agent-mig-container-vm/README.md +++ b/modules/tfc-agent-mig-container-vm/README.md @@ -25,13 +25,14 @@ This example shows how to deploy a self hosted Terraform Cloud agent on MIG Cont | additional\_metadata | Additional metadata to attach to the instance | `map(any)` | `{}` | no | | cooldown\_period | The number of seconds that the autoscaler should wait before it
starts collecting information from a new instance. | `number` | `60` | no | | create\_network | When set to true, VPC, router and NAT will be auto created | `bool` | `true` | no | +| create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | | dind | Flag to determine whether to expose dockersock | `bool` | `false` | no | | image | The Terraform Cloud agent image | `string` | `"hashicorp/tfc-agent:latest"` | no | | network\_name | Name for the VPC network | `string` | `"tfc-agent-network"` | no | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent | `string` | n/a | yes | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | | restart\_policy | The desired Docker restart policy for the agent image | `string` | `"Always"` | no | -| service\_account | Service account email address to assign roles and attach to MIG templates | `string` | `""` | no | +| service\_account\_email | Service account email address to use with the MIG template, required if create\_service\_account is set to false | `string` | `""` | no | | startup\_script | User startup script to run when instances spin up | `string` | `""` | no | | subnet\_ip | IP range for the subnet | `string` | `"10.10.10.0/24"` | no | | subnet\_name | Name for the subnet | `string` | `"tfc-agent-subnet"` | no | @@ -51,7 +52,7 @@ This example shows how to deploy a self hosted Terraform Cloud agent on MIG Cont | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | network\_name | Name of the VPC | -| service\_account | Service account email attached to MIG templates for GCE | +| service\_account\_email | Service account email attached to MIG templates for GCE | | subnet\_name | Name of the subnet in the VPC | diff --git a/modules/tfc-agent-mig-container-vm/main.tf b/modules/tfc-agent-mig-container-vm/main.tf index 586dbb5..29f8244 100644 --- a/modules/tfc-agent-mig-container-vm/main.tf +++ b/modules/tfc-agent-mig-container-vm/main.tf @@ -28,10 +28,10 @@ locals { path = "/var/run/docker.sock" } }] : [] - network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : var.network_name - subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].self_link : var.subnet_name - service_account = var.service_account == "" ? google_service_account.tfc_agent_service_account[0].email : var.service_account - instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" + network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : var.network_name + subnet_name = var.create_network ? google_compute_subnetwork.tfc_agent_subnetwork[0].self_link : var.subnet_name + service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email + instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" } resource "random_string" "suffix" { @@ -83,20 +83,18 @@ resource "google_compute_router_nat" "nat" { *****************************************/ resource "google_service_account" "tfc_agent_service_account" { - count = var.service_account == "" ? 1 : 0 + count = var.create_service_account ? 1 : 0 project = var.project_id account_id = "tfc-agent-mig-container-vm-sa" display_name = "Terrform agent GCE Service Account" } # allow GCE to pull images from GCR -resource "google_project_iam_binding" "gce" { - count = var.service_account == "" ? 1 : 0 +resource "google_project_iam_member" "gce" { + count = var.create_service_account ? 1 : 0 project = var.project_id role = "roles/storage.objectViewer" - members = [ - "serviceAccount:${local.service_account}", - ] + member = "serviceAccount:${local.service_account_email}" } /***************************************** @@ -165,7 +163,7 @@ module "mig_template" { subnetwork = local.subnet_name subnetwork_project = var.subnetwork_project != "" ? var.subnetwork_project : var.project_id service_account = { - email = local.service_account + email = local.service_account_email scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] diff --git a/modules/tfc-agent-mig-container-vm/outputs.tf b/modules/tfc-agent-mig-container-vm/outputs.tf index e3b5973..cf0c3a5 100644 --- a/modules/tfc-agent-mig-container-vm/outputs.tf +++ b/modules/tfc-agent-mig-container-vm/outputs.tf @@ -39,7 +39,7 @@ output "subnet_name" { value = local.subnet_name } -output "service_account" { +output "service_account_email" { description = "Service account email attached to MIG templates for GCE" - value = local.service_account + value = local.service_account_email } diff --git a/modules/tfc-agent-mig-container-vm/variables.tf b/modules/tfc-agent-mig-container-vm/variables.tf index 7c4993c..3354971 100644 --- a/modules/tfc-agent-mig-container-vm/variables.tf +++ b/modules/tfc-agent-mig-container-vm/variables.tf @@ -76,9 +76,15 @@ variable "target_size" { default = 2 } -variable "service_account" { +variable "create_service_account" { + description = "Set to true to create a new service account, false to use an existing one" + type = bool + default = true +} + +variable "service_account_email" { type = string - description = "Service account email address to assign roles and attach to MIG templates" + description = "Service account email address to use with the MIG template, required if create_service_account is set to false" default = "" } variable "additional_metadata" { diff --git a/modules/tfc-agent-mig-vm/README.md b/modules/tfc-agent-mig-vm/README.md index 279a184..9362372 100644 --- a/modules/tfc-agent-mig-vm/README.md +++ b/modules/tfc-agent-mig-vm/README.md @@ -26,6 +26,7 @@ This example shows how to deploy a MIG self hosted Terraform Cloud agent bootstr |------|-------------|------|---------|:--------:| | cooldown\_period | The number of seconds that the autoscaler should wait before it
starts collecting information from a new instance | `number` | `60` | no | | create\_network | When set to true, VPC, router and NAT will be auto created | `bool` | `true` | no | +| create\_service\_account | Set to true to create a new service account, false to use an existing one | `bool` | `true` | no | | custom\_metadata | User provided custom metadata | `map(any)` | `{}` | no | | machine\_type | The GCP machine type to deploy | `string` | `"n1-standard-1"` | no | | max\_replicas | Maximum number of Terraform agent instances | `number` | `10` | no | @@ -34,7 +35,7 @@ This example shows how to deploy a MIG self hosted Terraform Cloud agent bootstr | network\_project | The project ID of the shared VPCs host (for shared vpc support).
If not provided, the project\_id is used | `string` | `""` | no | | project\_id | The Google Cloud Platform project ID to deploy Terraform Cloud agent | `string` | n/a | yes | | region | The GCP region to use when deploying resources | `string` | `"us-central1"` | no | -| service\_account | Service account email address to use with the MIG template | `string` | `""` | no | +| service\_account\_email | Service account email address to use with the MIG template, required if create\_service\_account is set to false | `string` | `""` | no | | source\_image | Source disk image. If neither source\_image nor source\_image\_family is specified,
defaults to the latest public CentOS image | `string` | `""` | no | | source\_image\_family | Source image family. If neither source\_image nor source\_image\_family
is specified, defaults to the latest public Ubuntu image | `string` | `"ubuntu-2204-lts"` | no | | source\_image\_project | Project where the source image originates | `string` | `"ubuntu-os-cloud"` | no | @@ -45,9 +46,10 @@ This example shows how to deploy a MIG self hosted Terraform Cloud agent bootstr | tfc\_agent\_auto\_update | Controls automatic core updates behavior.
Acceptable values include disabled, patch, and minor | `string` | `"minor"` | no | | tfc\_agent\_labels | Terraform Cloud agent labels to attach to the VMs | `set(string)` | `[]` | no | | tfc\_agent\_name\_prefix | This name may be used in the Terraform Cloud user interface to help
easily identify the agent | `string` | `"tfc-agent-mig-vm"` | no | +| tfc\_agent\_secret | The secret id for storing the Terraform Cloud agent secret | `string` | `"tfc-agent"` | no | | tfc\_agent\_single | Enable single mode. This causes the agent to handle at most one job and
immediately exit thereafter. Useful for running agents as ephemeral
containers, VMs, or other isolated contexts with a higher-level scheduler
or process supervisor | `bool` | `false` | no | | tfc\_agent\_token | Terraform Cloud agent token. (Organization Settings >> Agents) | `string` | n/a | yes | -| tfc\_agent\_version | Terraform Cloud Agent version to install | `string` | `"1.10.1"` | no | +| tfc\_agent\_version | Terraform Cloud Agent version to install | `string` | `"1.12.0"` | no | ## Outputs @@ -57,7 +59,7 @@ This example shows how to deploy a MIG self hosted Terraform Cloud agent bootstr | mig\_instance\_template | The name of the MIG Instance Template | | mig\_name | The name of the MIG | | network\_name | Name of the VPC | -| service\_account | Service account email used with the MIG template | +| service\_account\_email | Service account email used with the MIG template | diff --git a/modules/tfc-agent-mig-vm/main.tf b/modules/tfc-agent-mig-vm/main.tf index 88323d4..6ed5cd0 100644 --- a/modules/tfc-agent-mig-vm/main.tf +++ b/modules/tfc-agent-mig-vm/main.tf @@ -15,10 +15,11 @@ */ locals { - network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : var.network_name - service_account = var.service_account == "" ? google_service_account.tfc_agent_service_account[0].email : var.service_account - startup_script = var.startup_script == "" ? file("${path.module}/scripts/startup.sh") : var.startup_script - instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" + network_name = var.create_network ? google_compute_network.tfc_agent_network[0].self_link : var.network_name + service_account_email = var.create_service_account ? google_service_account.tfc_agent_service_account[0].email : var.service_account_email + startup_script = var.startup_script == "" ? file("${path.module}/scripts/startup.sh") : var.startup_script + instance_name = "${var.tfc_agent_name_prefix}-${random_string.suffix.result}" + tfc_agent_secret = "${var.tfc_agent_secret}-${random_string.suffix.result}" } resource "random_string" "suffix" { @@ -70,7 +71,7 @@ resource "google_compute_router_nat" "tfc_agent_nat" { *****************************************/ resource "google_service_account" "tfc_agent_service_account" { - count = var.service_account == "" ? 1 : 0 + count = var.create_service_account ? 1 : 0 project = var.project_id account_id = "tfc-agent-mig-vm-sa" display_name = "Terraform Cloud agent GCE Service Account" @@ -83,10 +84,10 @@ resource "google_service_account" "tfc_agent_service_account" { resource "google_secret_manager_secret" "tfc_agent_secret" { provider = google-beta project = var.project_id - secret_id = "tfc-agent" + secret_id = local.tfc_agent_secret labels = { - label = "tfc-agent" + label = local.tfc_agent_secret } replication { @@ -117,7 +118,7 @@ resource "google_secret_manager_secret_iam_member" "tfc_agent_secret_member" { project = var.project_id secret_id = google_secret_manager_secret.tfc_agent_secret.id role = "roles/secretmanager.secretAccessor" - member = "serviceAccount:${local.service_account}" + member = "serviceAccount:${local.service_account_email}" } /***************************************** @@ -134,7 +135,7 @@ module "mig_template" { region = var.region subnetwork_project = var.network_project != "" ? var.network_project : var.project_id service_account = { - email = local.service_account + email = local.service_account_email scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] @@ -153,6 +154,11 @@ module "mig_template" { tags = [ local.instance_name ] + + depends_on = [ + google_compute_network.tfc_agent_network, + google_compute_subnetwork.tfc_agent_subnetwork, + ] } /***************************************** diff --git a/modules/tfc-agent-mig-vm/outputs.tf b/modules/tfc-agent-mig-vm/outputs.tf index fa796f1..7655a50 100644 --- a/modules/tfc-agent-mig-vm/outputs.tf +++ b/modules/tfc-agent-mig-vm/outputs.tf @@ -34,7 +34,7 @@ output "network_name" { value = local.network_name } -output "service_account" { +output "service_account_email" { description = "Service account email used with the MIG template" - value = local.service_account + value = local.service_account_email } diff --git a/modules/tfc-agent-mig-vm/variables.tf b/modules/tfc-agent-mig-vm/variables.tf index 002a922..8ee1e46 100644 --- a/modules/tfc-agent-mig-vm/variables.tf +++ b/modules/tfc-agent-mig-vm/variables.tf @@ -70,9 +70,15 @@ variable "max_replicas" { default = 10 } -variable "service_account" { +variable "create_service_account" { + description = "Set to true to create a new service account, false to use an existing one" + type = bool + default = true +} + +variable "service_account_email" { type = string - description = "Service account email address to use with the MIG template" + description = "Service account email address to use with the MIG template, required if create_service_account is set to false" default = "" } @@ -127,6 +133,12 @@ variable "cooldown_period" { default = 60 } +variable "tfc_agent_secret" { + type = string + description = "The secret id for storing the Terraform Cloud agent secret" + default = "tfc-agent" +} + variable "tfc_agent_address" { type = string description = "The HTTP or HTTPS address of the Terraform Cloud/Enterprise API" @@ -171,7 +183,7 @@ variable "tfc_agent_labels" { variable "tfc_agent_version" { type = string description = "Terraform Cloud Agent version to install" - default = "1.10.1" + default = "1.12.0" } variable "tfc_agent_token" { diff --git a/test/integration/oidc-simple/oidc_simple_test.go b/test/integration/oidc-simple/oidc_simple_test.go new file mode 100755 index 0000000..2cb5c29 --- /dev/null +++ b/test/integration/oidc-simple/oidc_simple_test.go @@ -0,0 +1,57 @@ +/** + * Copyright 2023 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. + */ + +package oidc_simple + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestOidcSimple(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + poolName := bpt.GetStringOutput("pool_name") + providerName := bpt.GetStringOutput("provider_name") + saEmail := bpt.GetStringOutput("sa_email") + + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("iam workload-identity-pools describe %s --location=global", poolName), gcloudArgs) + + assert.Equal(op.Get("name").String(), poolName, "Workload Identity Poo should have the right name") + assert.Equal(op.Get("description").String(), "Workload Identity Pool managed by Terraform", "Description should match to show WIP managed by Terraform") + assert.Equal(op.Get("state").String(), "ACTIVE", "Workload Identity Pool status should be ACTIVE") + + op = gcloud.Run(t, fmt.Sprintf("iam workload-identity-pools providers describe %s --workload-identity-pool=%s --location=global",providerName, poolName), gcloudArgs) + assert.Equal(op.Get("name").String(), providerName, "Workload Identity Poo should have the right name") + assert.Equal(op.Get("oidc.issuerUri").String(), "https://app.terraform.io", "OIDC issuer should match with Terraform Cloud's endpoint") + assert.Equal(op.Get("state").String(), "ACTIVE", "Workload Identity Pool status should be ACTIVE") + + op = gcloud.Run(t, fmt.Sprintf("iam service-accounts get-iam-policy %s",saEmail), gcloudArgs) + assert.Equal(op.Get("bindings.0.role").String(), "roles/iam.workloadIdentityUser", "Service Account should have workloadIdentityUser role") + }) + + bpt.Test() +} diff --git a/test/integration/tfc-agent-gke-custom/tfc_agent_gke_custom_test.go b/test/integration/tfc-agent-gke-custom/tfc_agent_gke_custom_test.go new file mode 100755 index 0000000..62341e2 --- /dev/null +++ b/test/integration/tfc-agent-gke-custom/tfc_agent_gke_custom_test.go @@ -0,0 +1,53 @@ +/** + * Copyright 2023 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. + */ + +package tfc_agent_gke_custom + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestTfcAgentGkeCustom(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + clusterName := bpt.GetStringOutput("cluster_name") + clusterCaCertificate := bpt.GetStringOutput("ca_certificate") + location := bpt.GetStringOutput("location") + serviceAccount := bpt.GetStringOutput("service_account") + + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--region", location, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("container clusters describe %s", clusterName), gcloudArgs) + + assert.Equal(op.Get("status").String(), "RUNNING", "GKE cluster should be up and running") + assert.Equal(op.Get("masterAuth.clusterCaCertificate").String(), clusterCaCertificate, "GKE cluster should be up and running") + assert.Equal(op.Get("nodeConfig.serviceAccount").String(), serviceAccount, "GKE cluster should have the right Service Account attached") + assert.Equal(op.Get("nodePools.0.status").String(), "RUNNING", "Node pools should have RUNNING status") + assert.Equal(op.Get("nodePools.0.config.metadata.cluster_name").String(), clusterName, "Node pools should be attached to the right cluster") + assert.Equal(op.Get("nodePools.0.config.serviceAccount").String(), serviceAccount, "Node pools should be attached to the right Service Account attached") + }) + + bpt.Test() +} diff --git a/test/integration/tfc-agent-gke-simple/tfc_agent_gke_simple_test.go b/test/integration/tfc-agent-gke-simple/tfc_agent_gke_simple_test.go new file mode 100755 index 0000000..6356bea --- /dev/null +++ b/test/integration/tfc-agent-gke-simple/tfc_agent_gke_simple_test.go @@ -0,0 +1,53 @@ +/** + * Copyright 2023 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. + */ + +package tfc_agent_gke_simple + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestTfcAgentGkeSimple(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + clusterName := bpt.GetStringOutput("cluster_name") + clusterCaCertificate := bpt.GetStringOutput("ca_certificate") + location := bpt.GetStringOutput("location") + serviceAccount := bpt.GetStringOutput("service_account") + + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--region", location, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("container clusters describe %s", clusterName), gcloudArgs) + + assert.Equal(op.Get("status").String(),"RUNNING", "GKE cluster should be up and running") + assert.Equal(op.Get("masterAuth.clusterCaCertificate").String(), clusterCaCertificate, "GKE cluster should be up and running") + assert.Equal(op.Get("nodeConfig.serviceAccount").String(), serviceAccount, "GKE cluster should have the right Service Account attached") + assert.Equal(op.Get("nodePools.0.status").String(),"RUNNING", "Node pools should have RUNNING status") + assert.Equal(op.Get("nodePools.0.config.metadata.cluster_name").String(), clusterName, "Node pools should be attached to the right cluster") + assert.Equal(op.Get("nodePools.0.config.serviceAccount").String(), serviceAccount, "Node pools should be attached to the right Service Account attached") + }) + + bpt.Test() +} diff --git a/test/integration/tfc-agent-mig-container-vm-simple/tfc_agent_mig_container_vm_simple_test.go b/test/integration/tfc-agent-mig-container-vm-simple/tfc_agent_mig_container_vm_simple_test.go new file mode 100755 index 0000000..3cb3797 --- /dev/null +++ b/test/integration/tfc-agent-mig-container-vm-simple/tfc_agent_mig_container_vm_simple_test.go @@ -0,0 +1,50 @@ +/** + * Copyright 2023 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. + */ + +package tfc_agent_mig_container_vm_simple + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestTfcAgentMigContainerVmSimple(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + region := "us-central1" + migName := bpt.GetStringOutput("mig_name") + migInstanceGroup := bpt.GetStringOutput("mig_instance_group") + + time.Sleep(120 * time.Second) + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--region", region, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("compute instance-groups managed describe %s-mig", migName), gcloudArgs) + + assert.Equal(op.Get("autoscaler.status").String(), "ACTIVE", "Autoscaler should have ACTIVE status") + assert.Equal(op.Get("status.isStable").String(), "true", "Instance group stability flag should be true") + assert.Equal(op.Get("instanceGroup").String(), migInstanceGroup, "Instance group URL should match") + }) + + bpt.Test() +} diff --git a/test/integration/tfc-agent-mig-vm-packer/tfc_agent_mig_vm_packer_test.go b/test/integration/tfc-agent-mig-vm-packer/tfc_agent_mig_vm_packer_test.go new file mode 100755 index 0000000..ab6a2e9 --- /dev/null +++ b/test/integration/tfc-agent-mig-vm-packer/tfc_agent_mig_vm_packer_test.go @@ -0,0 +1,50 @@ +/** + * Copyright 2023 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. + */ + +package tfc_agent_mig_vm_packer + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestTfcAgentMigVmPacker(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + region := "us-central1" + migName := bpt.GetStringOutput("mig_name") + migInstanceGroup := bpt.GetStringOutput("mig_instance_group") + + time.Sleep(120 * time.Second) + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--region", region, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("compute instance-groups managed describe %s-mig", migName), gcloudArgs) + + assert.Equal(op.Get("autoscaler.status").String(), "ACTIVE", "Autoscaler should have ACTIVE status") + assert.Equal(op.Get("status.isStable").String(), "true", "Instance group stability flag should be true") + assert.Equal(op.Get("instanceGroup").String(), migInstanceGroup, "Instance group URL should match") + }) + + bpt.Test() +} diff --git a/test/integration/tfc-agent-mig-vm-simple/tfc_agent_mig_vm_simple_test.go b/test/integration/tfc-agent-mig-vm-simple/tfc_agent_mig_vm_simple_test.go new file mode 100755 index 0000000..5c45240 --- /dev/null +++ b/test/integration/tfc-agent-mig-vm-simple/tfc_agent_mig_vm_simple_test.go @@ -0,0 +1,50 @@ +/** + * Copyright 2023 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. + */ + +package tfc_agent_mig_vm_simple + +import ( + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud" + "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft" + "github.com/stretchr/testify/assert" +) + +func TestTfcAgentMigVmSimple(t *testing.T) { + bpt := tft.NewTFBlueprintTest(t, tft.WithRetryableTerraformErrors(tft.CommonRetryableErrors, 2, 3*time.Second)) + + bpt.DefineVerify(func(assert *assert.Assertions) { + bpt.DefaultVerify(assert) + + projectId := bpt.GetStringOutput("project_id") + region := "us-central1" + migName := bpt.GetStringOutput("mig_name") + migInstanceGroup := bpt.GetStringOutput("mig_instance_group") + + time.Sleep(120 * time.Second) + gcloudArgs := gcloud.WithCommonArgs([]string{"--project", projectId, "--region", region, "--format=json"}) + op := gcloud.Run(t, fmt.Sprintf("compute instance-groups managed describe %s-mig", migName), gcloudArgs) + + assert.Equal(op.Get("autoscaler.status").String(), "ACTIVE", "Autoscaler should have ACTIVE status") + assert.Equal(op.Get("status.isStable").String(), "true", "Instance group stability flag should be true") + assert.Equal(op.Get("instanceGroup").String(), migInstanceGroup, "Instance group URL should match") + }) + + bpt.Test() +} diff --git a/test/setup/.gitignore b/test/setup/.gitignore index 0e515f8..445d650 100644 --- a/test/setup/.gitignore +++ b/test/setup/.gitignore @@ -1,2 +1,3 @@ terraform.tfvars source.sh +outputs.env diff --git a/test/setup/iam.tf b/test/setup/iam.tf index fe77edf..44eb00d 100644 --- a/test/setup/iam.tf +++ b/test/setup/iam.tf @@ -16,7 +16,8 @@ locals { int_required_roles = [ - "roles/owner" + "roles/owner", + "roles/artifactregistry.admin" ] } diff --git a/test/setup/main.tf b/test/setup/main.tf index 42e3d78..7fac001 100644 --- a/test/setup/main.tf +++ b/test/setup/main.tf @@ -18,15 +18,40 @@ module "project" { source = "terraform-google-modules/project-factory/google" version = "~> 14.0" - name = "ci-tf-cloud-agents" - random_project_id = "true" - org_id = var.org_id - folder_id = var.folder_id - billing_account = var.billing_account + name = "ci-tf-cloud-agents" + random_project_id = "true" + org_id = var.org_id + folder_id = var.folder_id + billing_account = var.billing_account + auto_create_network = true activate_apis = [ + "artifactregistry.googleapis.com", "cloudresourcemanager.googleapis.com", + "compute.googleapis.com", + "container.googleapis.com", + "iam.googleapis.com", + "serviceusage.googleapis.com", + "secretmanager.googleapis.com", "storage-api.googleapis.com", - "serviceusage.googleapis.com" ] } + +data "tfe_organization" "tfc_org" { + name = var.tfc_org_name +} + +resource "google_artifact_registry_repository" "hashicorp" { + project = module.project.project_id + location = "us-central1" + repository_id = "hashicorp" + description = "HashiCorp Docker repository" + format = "DOCKER" +} + +resource "local_file" "env_file" { + filename = "${path.module}/outputs.env" + content = <