Skip to content

Commit 9615afe

Browse files
committed
WIP: Add ensure-integration-network job and terraform for GCP integration subnet
Introduces a manually-triggered Concourse job, ensure-integration-network, that idempotently creates the per-branch GCP subnetwork consumed by the test-stemcells-ipv4 and bats jobs (deploy-director, cleanup-bats-vms, prepare-bats) under the bosh-concourse VPC. Why --- The test-stemcells-ipv4 and bats jobs in ci/pipelines/builder.yml assume a subnetwork named stemcell-builder-integration-<subnet_int> exists in the projects/cloud-foundry-310819/global/networks/bosh-concourse VPC, with a /24 at 10.100.<subnet_int>.0/24, gateway .1, private Google access, and IPV4_ONLY stack type. Until now this subnet had to be created and maintained out of band; this change captures it as code so it can be recreated reproducibly per branch (subnet_int is set per branch in ci/pipelines/vars.yml). What ---- * ci/tasks/ensure-integration-network/{input,network,output}.tf - hashicorp/google ~> 5.0 - google_compute_subnetwork "integration": name = stemcell-builder-integration-<subnet_int> ip_cidr_range = 10.100.<subnet_int>.0/24 region = europe-north2 (matches GCP_ZONE europe-north2-a in deploy-director) network = bosh-concourse (configurable) private_ip_google_access = true purpose = PRIVATE stack_type = IPV4_ONLY - subnet_int is taken as input so the same module produces the appropriate subnet for any branch. * ci/pipelines/builder.yml - New `infrastructure` group containing the new job. - New resource_type `terraform_type` (ljfranklin/terraform-resource). - New resource `integration-network-environment` (GCS backend). The bucket is referenced via the Concourse credential ((integration_network_terraform_state_bucket)); pick a bucket name and add the credential before flying. A TODO comment marks this. - New job `ensure-integration-network`: * serial: true, manual trigger only (no `trigger: true` on get). * Puts to integration-network-environment with env_name = stemcell-builder-integration-<subnet_int>, so the state file is deterministically named and re-discovered on subsequent runs (no recreate-on-rerun). * Apply only — never destroyed by this job, since the subnet is long-lived shared infrastructure. * No `passed:` constraint on the existing test/bats jobs to avoid coupling; the job is intended to be run on demand when the subnet needs to be created or reconciled. Verification ------------ * `ytt -f ci/pipelines/builder.yml -f ci/pipelines/vars.yml` renders successfully. * `fly validate-pipeline -c <rendered>` reports "looks good". Follow-ups ---------- * Create the GCS bucket that will hold terraform state and set the ((integration_network_terraform_state_bucket)) Concourse credential. * If the existing subnetwork in cloud-foundry-310819 is to be adopted rather than recreated, run `terraform import` once before flying the job (or delete the existing subnet first).
1 parent ed23b8a commit 9615afe

4 files changed

Lines changed: 122 additions & 0 deletions

File tree

ci/pipelines/builder.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ groups:
4444
- name: docker
4545
jobs:
4646
- build-os-image-stemcell-builder
47+
- name: infrastructure
48+
jobs:
49+
- ensure-integration-network
4750

4851
#@yaml/text-templated-strings
4952
jobs:
@@ -89,6 +92,23 @@ jobs:
8992
get_params:
9093
skip_download: true
9194

95+
#! Manually triggered job that idempotently creates (or updates) the GCP
96+
#! subnetwork consumed by deploy-director / cleanup-bats-vms / prepare-bats
97+
#! in the test-stemcells-ipv4 and bats jobs below. The terraform state lives
98+
#! in GCS, keyed by env_name = stemcell-builder-integration-<subnet_int>, so
99+
#! the same subnetwork is reused across pipeline runs and is never destroyed
100+
#! by this job.
101+
- name: ensure-integration-network
102+
serial: true
103+
plan:
104+
- get: bosh-stemcells-ci
105+
- put: integration-network-environment
106+
params:
107+
env_name: stemcell-builder-integration-(@= data.values.stemcell_details.subnet_int @)
108+
terraform_source: bosh-stemcells-ci/ci/tasks/ensure-integration-network/
109+
vars:
110+
subnet_int: (@= data.values.stemcell_details.subnet_int @)
111+
92112
- name: process-high-critical-cves
93113
serial_groups: [log-cves]
94114
plan:
@@ -885,6 +905,10 @@ resource_types:
885905
type: registry-image
886906
source:
887907
repository: frodenas/gcs-resource
908+
- name: terraform_type
909+
type: registry-image
910+
source:
911+
repository: ljfranklin/terraform-resource
888912

889913
#@yaml/text-templated-strings
890914
resources:
@@ -1193,3 +1217,23 @@ resources:
11931217
source:
11941218
regexp: azure-storage-cli-(.*)-linux-amd64
11951219
bucket: bosh-azure-storage-cli-artifacts
1220+
1221+
#! Terraform state for the per-branch GCP subnetwork used by the
1222+
#! test-stemcells-ipv4 and bats jobs. The env_name passed to `put` is derived
1223+
#! from data.values.stemcell_details.subnet_int so the state file is
1224+
#! deterministically named (e.g. stemcell-builder-integration-22) and is
1225+
#! re-discovered on subsequent runs without recreating the subnetwork.
1226+
#!
1227+
#! TODO: replace ((integration_network_terraform_state_bucket)) with the
1228+
#! agreed-upon GCS bucket name (the bucket itself must be created out of band).
1229+
- name: integration-network-environment
1230+
type: terraform_type
1231+
source:
1232+
backend_type: gcs
1233+
backend_config:
1234+
credentials: ((gcp_json_key))
1235+
bucket: ((integration_network_terraform_state_bucket))
1236+
prefix: stemcell-builder-integration-network/
1237+
vars:
1238+
gce_credentials_json: ((gcp_json_key))
1239+
gce_project_id: ((gcp_project_id))
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
variable "gce_project_id" {
2+
type = string
3+
description = "GCP project that owns the bosh-concourse VPC."
4+
}
5+
6+
variable "gce_credentials_json" {
7+
type = string
8+
description = "JSON-encoded service account credentials with Compute Network Admin on the project."
9+
sensitive = true
10+
}
11+
12+
variable "gce_region" {
13+
type = string
14+
description = "Region to create the integration subnetwork in. Must match the region of the GCP_ZONE used by deploy-director."
15+
default = "europe-north2"
16+
}
17+
18+
variable "network_name" {
19+
type = string
20+
description = "Name of the VPC network the subnetwork will be attached to."
21+
default = "bosh-concourse"
22+
}
23+
24+
variable "subnet_int" {
25+
type = string
26+
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."
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
terraform {
2+
required_providers {
3+
google = {
4+
source = "hashicorp/google"
5+
version = "~> 5.0"
6+
}
7+
}
8+
}
9+
10+
provider "google" {
11+
project = var.gce_project_id
12+
region = var.gce_region
13+
credentials = var.gce_credentials_json
14+
}
15+
16+
# Subnetwork used by the test-stemcells-ipv4 and bats jobs in
17+
# ci/pipelines/builder.yml. The reserved ranges in those jobs assume a /24
18+
# starting at 10.100.<subnet_int>.0 with the gateway at .1.
19+
resource "google_compute_subnetwork" "integration" {
20+
name = "stemcell-builder-integration-${var.subnet_int}"
21+
ip_cidr_range = "10.100.${var.subnet_int}.0/24"
22+
region = var.gce_region
23+
network = "projects/${var.gce_project_id}/global/networks/${var.network_name}"
24+
private_ip_google_access = true
25+
purpose = "PRIVATE"
26+
stack_type = "IPV4_ONLY"
27+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
output "subnetwork_name" {
2+
description = "Name of the integration subnetwork. Matches GCP_SUBNET_NAME in deploy-director / cleanup-bats-vms."
3+
value = google_compute_subnetwork.integration.name
4+
}
5+
6+
output "subnetwork_self_link" {
7+
description = "Self link to the integration subnetwork."
8+
value = google_compute_subnetwork.integration.self_link
9+
}
10+
11+
output "ip_cidr_range" {
12+
description = "Primary IPv4 CIDR range allocated to the subnetwork."
13+
value = google_compute_subnetwork.integration.ip_cidr_range
14+
}
15+
16+
output "gateway_address" {
17+
description = "Gateway address of the subnetwork. Matches INTERNAL_GW in deploy-director."
18+
value = google_compute_subnetwork.integration.gateway_address
19+
}
20+
21+
output "region" {
22+
description = "Region the subnetwork lives in."
23+
value = google_compute_subnetwork.integration.region
24+
}

0 commit comments

Comments
 (0)