diff --git a/ci/pipelines/builder.yml b/ci/pipelines/builder.yml index 5a53d52bb..3f2f446d2 100644 --- a/ci/pipelines/builder.yml +++ b/ci/pipelines/builder.yml @@ -44,6 +44,9 @@ groups: - name: docker jobs: - build-os-image-stemcell-builder +- name: infrastructure + jobs: + - ensure-integration-network #@yaml/text-templated-strings jobs: @@ -89,6 +92,23 @@ jobs: get_params: skip_download: true +#! Manually triggered job that idempotently creates (or updates) the GCP +#! subnetwork consumed by deploy-director / cleanup-bats-vms / prepare-bats +#! in the test-stemcells-ipv4 and bats jobs below. The terraform state lives +#! in GCS, keyed by env_name = stemcell-builder-integration-, so +#! the same subnetwork is reused across pipeline runs and is never destroyed +#! by this job. +- name: ensure-integration-network + serial: true + plan: + - get: bosh-stemcells-ci + - put: integration-network-environment + params: + env_name: stemcell-builder-integration-(@= data.values.stemcell_details.subnet_int @) + terraform_source: bosh-stemcells-ci/ci/tasks/ensure-integration-network/ + vars: + subnet_int: (@= data.values.stemcell_details.subnet_int @) + - name: process-high-critical-cves serial_groups: [log-cves] plan: @@ -885,6 +905,10 @@ resource_types: type: registry-image source: repository: frodenas/gcs-resource +- name: terraform_type + type: registry-image + source: + repository: ljfranklin/terraform-resource #@yaml/text-templated-strings resources: @@ -1193,3 +1217,23 @@ resources: source: regexp: azure-storage-cli-(.*)-linux-amd64 bucket: bosh-azure-storage-cli-artifacts + +#! Terraform state for the per-branch GCP subnetwork used by the +#! test-stemcells-ipv4 and bats jobs. The env_name passed to `put` is derived +#! from data.values.stemcell_details.subnet_int so the state file is +#! deterministically named (e.g. stemcell-builder-integration-22) and is +#! re-discovered on subsequent runs without recreating the subnetwork. +#! +#! TODO: replace ((integration_network_terraform_state_bucket)) with the +#! agreed-upon GCS bucket name (the bucket itself must be created out of band). +- name: integration-network-environment + type: terraform_type + source: + backend_type: gcs + backend_config: + credentials: ((gcp_json_key)) + bucket: ((integration_network_terraform_state_bucket)) + prefix: stemcell-builder-integration-network/ + vars: + gce_credentials_json: ((gcp_json_key)) + gce_project_id: ((gcp_project_id)) diff --git a/ci/tasks/ensure-integration-network/input.tf b/ci/tasks/ensure-integration-network/input.tf new file mode 100644 index 000000000..a4634ca7a --- /dev/null +++ b/ci/tasks/ensure-integration-network/input.tf @@ -0,0 +1,27 @@ +variable "gce_project_id" { + type = string + description = "GCP project that owns the bosh-concourse VPC." +} + +variable "gce_credentials_json" { + type = string + description = "JSON-encoded service account credentials with Compute Network Admin on the project." + sensitive = true +} + +variable "gce_region" { + type = string + description = "Region to create the integration subnetwork in. Must match the region of the GCP_ZONE used by deploy-director." + default = "europe-north2" +} + +variable "network_name" { + type = string + description = "Name of the VPC network the subnetwork will be attached to." + default = "bosh-concourse" +} + +variable "subnet_int" { + type = string + description = "Integer (as string) used as both the third octet of the /24 CIDR and the suffix of the subnet name. Matches data.values.stemcell_details.subnet_int in ci/pipelines/vars.yml." +} diff --git a/ci/tasks/ensure-integration-network/network.tf b/ci/tasks/ensure-integration-network/network.tf new file mode 100644 index 000000000..d7904c93d --- /dev/null +++ b/ci/tasks/ensure-integration-network/network.tf @@ -0,0 +1,27 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.0" + } + } +} + +provider "google" { + project = var.gce_project_id + region = var.gce_region + credentials = var.gce_credentials_json +} + +# Subnetwork used by the test-stemcells-ipv4 and bats jobs in +# ci/pipelines/builder.yml. The reserved ranges in those jobs assume a /24 +# starting at 10.100..0 with the gateway at .1. +resource "google_compute_subnetwork" "integration" { + name = "stemcell-builder-integration-${var.subnet_int}" + ip_cidr_range = "10.100.${var.subnet_int}.0/24" + region = var.gce_region + network = "projects/${var.gce_project_id}/global/networks/${var.network_name}" + private_ip_google_access = true + purpose = "PRIVATE" + stack_type = "IPV4_ONLY" +} diff --git a/ci/tasks/ensure-integration-network/output.tf b/ci/tasks/ensure-integration-network/output.tf new file mode 100644 index 000000000..0f18a962d --- /dev/null +++ b/ci/tasks/ensure-integration-network/output.tf @@ -0,0 +1,24 @@ +output "subnetwork_name" { + description = "Name of the integration subnetwork. Matches GCP_SUBNET_NAME in deploy-director / cleanup-bats-vms." + value = google_compute_subnetwork.integration.name +} + +output "subnetwork_self_link" { + description = "Self link to the integration subnetwork." + value = google_compute_subnetwork.integration.self_link +} + +output "ip_cidr_range" { + description = "Primary IPv4 CIDR range allocated to the subnetwork." + value = google_compute_subnetwork.integration.ip_cidr_range +} + +output "gateway_address" { + description = "Gateway address of the subnetwork. Matches INTERNAL_GW in deploy-director." + value = google_compute_subnetwork.integration.gateway_address +} + +output "region" { + description = "Region the subnetwork lives in." + value = google_compute_subnetwork.integration.region +}