diff --git a/ci/ca_certs/bosh-ecosystem-openstack-wallaby-ca.pem b/ci/ca_certs/bosh-ecosystem-openstack-wallaby-ca.pem deleted file mode 100644 index 6a502c25e..000000000 --- a/ci/ca_certs/bosh-ecosystem-openstack-wallaby-ca.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUN0hGX4X0rDRs0U/q678RS9qEkaMwDQYJKoZIhvcNAQEL -BQAwPTE7MDkGA1UEAxMyVmF1bHQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkg -KGNoYXJtLXBraS1sb2NhbCkwHhcNMjUwMjEyMDQ0NzUwWhcNMzUwMjEwMDM0ODE5 -WjA9MTswOQYDVQQDEzJWYXVsdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAo -Y2hhcm0tcGtpLWxvY2FsKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALe+TpmVOAHhhDut5EY8F7zFlMl6gmaoDUNVCW8dtnuCtpPtlMbmUSoMJB06ldFT -9FqUosJr7psgwH5UqiPNSG+sbIsU32y+U/bhC1k1EYFPTAPJVfPaktnhDkueTFjO -l/LvdKkP+Oyv74/5+pVoT3bEOHAafvId2A1Ye+ofKNlFel5jUFHTbHATpz9FIHN8 -j/QumPvy7JqaXYH6TrGUlXWMVf4i5qsghy6uutfEGmGMskNdOImuDFNa3+7sF1m7 -MHcP3gZSJvmwz6nXmUKtrBUqNLEGNjbbK5Cx44Igmh+y6lSOctjzj2+wfa4NyADr -sLXPcrC+ZNSVjU3+jKqMzekCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud -EwEB/wQFMAMBAf8wHQYDVR0OBBYEFNTAYEm4BuY5PGJUs8/2oxaPnxV0MB8GA1Ud -IwQYMBaAFNTAYEm4BuY5PGJUs8/2oxaPnxV0MA0GCSqGSIb3DQEBCwUAA4IBAQAx -483kgo7iY7eCWpqjBkkrtqoQJVVAbYHQb/JU4j0ogezqbjY2l/q3r0+QFOqxwte9 -235Zb1zIxJi0M+mtPV1OEv1cD7A6YlbnT3ofb35/Hjsi9HWKJJz9s2bhwbYwVwF6 -ucga3Adsxip545D+jo0Of57FRLtEEG9XroW+HvyUIcTrNE/2KWUzsatFud4PqVk+ -RhL9qe+fq/6WoCQ7quVE15ob6XTjkDQkmtQ14mpfLkFQkA/+JraOFC5P4M2TMsaR -YFcN6bIDSb73l3ldJfjHJQCNHYlCgOuTrs7q2HN1s9vYOrwDM1z1BA4Iq5OAEHTm -Xt1nte+8zO2W0+6/2h3c ------END CERTIFICATE----- diff --git a/ci/configure.sh b/ci/configure.sh index 810afc45c..be88209b2 100755 --- a/ci/configure.sh +++ b/ci/configure.sh @@ -2,5 +2,5 @@ set -eu -fly -t "${CONCOURSE_TARGET:-bosh-ecosystem}" set-pipeline -p "bosh-openstack-cpi" \ +fly -t "${CONCOURSE_TARGET:-bosh}" set-pipeline -p "bosh-openstack-cpi" \ -c ci/pipeline.yml diff --git a/ci/ops_files/timeouts.yml b/ci/ops_files/timeouts.yml index cb722d771..1eb25443f 100644 --- a/ci/ops_files/timeouts.yml +++ b/ci/ops_files/timeouts.yml @@ -12,7 +12,6 @@ connect_timeout: ((openstack_connection_timeout)) read_timeout: ((openstack_read_timeout)) write_timeout: ((openstack_write_timeout)) - ca_cert: ((openstack_ca_cert)) - type: replace path: /cloud_provider/properties/openstack/connection_options? diff --git a/ci/pipeline.yml b/ci/pipeline.yml index 1d1995b02..3c7d22664 100644 --- a/ci/pipeline.yml +++ b/ci/pipeline.yml @@ -13,16 +13,6 @@ jobs: params: build: bosh-openstack-cpi-release/ci/docker/openstack-cpi-release -- name: pipeline-locator - plan: - - get: bosh-openstack-cpi-release - - task: pipeline-location - file: bosh-openstack-cpi-release/ci/tasks/pipeline-locator.yml - params: - PIPELINE_FILENAME: "pipeline.yml" - input_mapping: - pipeline-repo: bosh-openstack-cpi-release - - name: run-specs serial: true plan: @@ -35,197 +25,162 @@ jobs: file: bosh-openstack-cpi-release/ci/tasks/run-unit-specs.yml image: openstack-cpi-release-docker-image -- name: lifecycle +- name: run-devstack-tests serial: true - serial_groups: [ cleanup-lock-lifecycle ] + serial_groups: [ devstack ] plan: - - in_parallel: - - get: bosh-openstack-cpi-release - passed: [ run-specs ] - tags: [openstack] - timeout: *timeouts-long - trigger: true - - get: openstack-lifecycle-stemcell - resource: openstack-ubuntu-jammy-stemcell - tags: [openstack] - timeout: *timeouts-long - - get: terraform-image - tags: [openstack] - - get: openstack-cpi-release-docker-image - tags: [openstack] - - - task: write_ca_file - tags: [openstack] - file: bosh-openstack-cpi-release/ci/tasks/write-ca-file.yml - image: openstack-cpi-release-docker-image - params: - file_content: ((concourse_openstack_auth.openstack_ca_cert)) - - - task: terraform-apply - tags: [openstack] - timeout: *timeouts-long - image: terraform-image - file: bosh-openstack-cpi-release/ci/tasks/terraform-apply-lifecycle.yml - params: &lifecycle-terraform-params - TF_VAR_prefix: "lifecycle-openstack-tests" - TF_VAR_auth_url: ((concourse_openstack_auth.auth_url)) - TF_VAR_cacert_file: ((config-json.tf_ca_file_path)) - TF_VAR_user_name: ((config-json.openstack_username)) - TF_VAR_password: ((config-json.openstack_password)) - TF_VAR_domain_name: ((config-json.lifecycle_openstack_domain)) - TF_VAR_project_name: ((config-json.openstack_project)) - TF_VAR_ext_net_id: ((config-json.tf_external_network_id)) - TF_VAR_ext_net_name: ((config-json.tf_external_network_name)) - TF_VAR_region_name: ((config-json.tf_region_name)) - TF_VAR_openstack_default_key_public_key: ((config-json.tf_default_public_key)) - TF_VAR_dns_nameservers: ((config-json.tf_dns_nameservers)) - TF_VAR_use_lbaas: false - - do: - - task: test - tags: [openstack] - timeout: *timeouts-long - file: bosh-openstack-cpi-release/ci/tasks/run-lifecycle.yml - image: openstack-cpi-release-docker-image + - in_parallel: + - get: bosh-openstack-cpi-release + passed: [ run-specs ] + timeout: *timeouts-long + trigger: true + - get: openstack-lifecycle-stemcell + resource: openstack-ubuntu-jammy-stemcell + timeout: *timeouts-long + - get: terraform-image + - get: openstack-cpi-release-docker-image + - get: stemcell-director + resource: openstack-ubuntu-jammy-stemcell + timeout: *timeouts-long + trigger: true + - get: stemcell + resource: openstack-ubuntu-jammy-stemcell + timeout: *timeouts-long + - get: bosh-release + timeout: *timeouts-long + - get: bats + timeout: *timeouts-long + - get: bosh-deployment + timeout: *timeouts-long + + - put: gcp-devstack params: - BOSH_OPENSTACK_DOMAIN: ((config-json.lifecycle_openstack_domain)) - BOSH_OPENSTACK_PROJECT: ((config-json.openstack_project)) - BOSH_OPENSTACK_USERNAME_V2: ((config-json.openstack_username)) - BOSH_OPENSTACK_AUTH_URL_V3: ((concourse_openstack_auth.auth_url)) - BOSH_OPENSTACK_USERNAME_V3: ((config-json.openstack_username)) - BOSH_OPENSTACK_API_KEY_V3: ((config-json.openstack_password)) - BOSH_CLI_SILENCE_SLOW_LOAD_WARNING: true - BOSH_OPENSTACK_VOLUME_TYPE: ((config-json.lifecycle_openstack_volume_type)) - BOSH_OPENSTACK_CONNECT_TIMEOUT: "600" - BOSH_OPENSTACK_READ_TIMEOUT: "120" - BOSH_OPENSTACK_WRITE_TIMEOUT: "120" - BOSH_OPENSTACK_CA_CERT: ((concourse_openstack_auth.openstack_ca_cert)) - BOSH_OPENSTACK_FLAVOR_WITH_NO_ROOT_DISK: ((config-json.openstack_flavor_with_no_root_disk)) - BOSH_OPENSTACK_AVAILABILITY_ZONE: ((config-json.availability_zone)) - BOSH_OPENSTACK_EXCLUDE_CINDER_V1: true - - put: lifecycle-log - tags: [openstack] - timeout: *timeouts-long + terraform_source: bosh-openstack-cpi-release/ci/terraform/ci/gcp-devstack + - task: wait-for-devstack + image: openstack-cpi-release-docker-image + file: bosh-openstack-cpi-release/ci/tasks/wait-for-devstack.yml params: - file: output/lifecycle.log - ensure: - task: terraform-destroy - tags: [openstack] - timeout: *timeouts-long - image: terraform-image - file: bosh-openstack-cpi-release/ci/tasks/terraform-destroy-lifecycle.yml - params: *lifecycle-terraform-params + AUTH_URL: http://10.100.30.2/identity + OS_USERNAME: ((openstack_ci_user.username)) + OS_PASSWORD: ((openstack_ci_user.password)) + OS_PROJECT: bosh -- name: bats-ubuntu-manual - serial: true - serial_groups: [ cleanup-lock-bats-ubuntu-manual ] - plan: - - in_parallel: - - get: terraform-image - tags: [openstack] - - passed: [ run-specs ] - get: bosh-openstack-cpi-release - timeout: *timeouts-long - tags: [openstack] - trigger: true - - get: bosh-release - timeout: *timeouts-long - tags: [openstack] - - get: stemcell-director - resource: openstack-ubuntu-jammy-stemcell + - task: lifecycle-apply-terraform timeout: *timeouts-long - tags: [openstack] - trigger: true - - get: stemcell - resource: openstack-ubuntu-jammy-stemcell - timeout: *timeouts-long - tags: [openstack] - - get: bats - timeout: *timeouts-long - tags: [openstack] - - get: bosh-deployment - timeout: *timeouts-long - tags: [openstack] - - - task: terraform-apply - tags: [openstack] - timeout: *timeouts-long - image: terraform-image - file: bosh-openstack-cpi-release/ci/tasks/terraform-apply-bats-manual.yml - params: &bats-terraform-vars - TF_VAR_prefix: "bats-ubuntu-manual" - TF_VAR_auth_url: ((concourse_openstack_auth.auth_url)) - TF_VAR_domain_name: ((concourse_openstack_auth.openstack_domain)) - TF_VAR_user_name: ((config-json.openstack_username)) - TF_VAR_password: ((config-json.openstack_password)) - TF_VAR_project_name: ((config-json.openstack_project)) - TF_VAR_cacert_file: ((config-json.tf_ca_file_path)) - TF_VAR_region_name: ((config-json.tf_region_name)) - TF_VAR_primary_net_name: "bats-ubuntu-manual-primary" - TF_VAR_primary_net_cidr: "10.0.4.0/24" - TF_VAR_primary_net_allocation_pool_start: "10.0.4.200" - TF_VAR_primary_net_allocation_pool_end: "10.0.4.254" - TF_VAR_secondary_net_name: "bats-ubuntu-manual-secondary" - TF_VAR_secondary_net_cidr: "10.0.5.0/24" - TF_VAR_secondary_net_allocation_pool_start: "10.0.5.200" - TF_VAR_secondary_net_allocation_pool_end: "10.0.5.254" - TF_VAR_ext_net_name: ((config-json.tf_external_network_name)) - TF_VAR_ext_net_id: ((config-json.tf_external_network_id)) - TF_VAR_ext_net_cidr: ((config-json.tf_ext_net_cidr)) - TF_VAR_dns_nameservers: ((config-json.tf_dns_nameservers)) - TF_VAR_concourse_external_network_cidr: null - TF_VAR_openstack_default_key_public_key: ((config-json.tf_default_public_key)) + image: terraform-image + file: bosh-openstack-cpi-release/ci/tasks/terraform-apply-lifecycle.yml + params: &lifecycle-terraform-params + TF_VAR_prefix: "lifecycle-openstack-tests" + TF_VAR_auth_url: http://10.100.30.2/identity + TF_VAR_user_name: ((openstack_ci_user.username)) + TF_VAR_password: ((openstack_ci_user.password)) + TF_VAR_domain_name: Default + TF_VAR_project_name: bosh + TF_VAR_ext_net_name: public + TF_VAR_region_name: RegionOne + TF_VAR_openstack_default_key_public_key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHspetaTfg96YfZO3/xjKxGcjTnFPlxp7uP1KDisvPjB devstack-ci-openstack + TF_VAR_dns_nameservers: '["8.8.8.8"]' + TF_VAR_use_lbaas: false + + - do: + - task: run-lifecycle + timeout: *timeouts-long + file: bosh-openstack-cpi-release/ci/tasks/run-lifecycle.yml + image: openstack-cpi-release-docker-image + params: + BOSH_OPENSTACK_DOMAIN: Default + BOSH_OPENSTACK_PROJECT: bosh + BOSH_OPENSTACK_USERNAME_V2: ((openstack_ci_user.username)) + BOSH_OPENSTACK_AUTH_URL_V3: http://10.100.30.2/identity + BOSH_OPENSTACK_USERNAME_V3: ((openstack_ci_user.username)) + BOSH_OPENSTACK_API_KEY_V3: ((openstack_ci_user.password)) + BOSH_CLI_SILENCE_SLOW_LOAD_WARNING: true + BOSH_OPENSTACK_VOLUME_TYPE: lvmdriver-1 + BOSH_OPENSTACK_CONNECT_TIMEOUT: "600" + BOSH_OPENSTACK_READ_TIMEOUT: "120" + BOSH_OPENSTACK_WRITE_TIMEOUT: "120" + BOSH_OPENSTACK_FLAVOR_WITH_NO_ROOT_DISK: no-root-disk + BOSH_OPENSTACK_AVAILABILITY_ZONE: nova + BOSH_OPENSTACK_EXCLUDE_CINDER_V1: true + - put: lifecycle-log + timeout: *timeouts-long + params: + file: output/lifecycle.log + ensure: + task: lifecycle-destroy-terraform + timeout: *timeouts-long + image: terraform-image + file: bosh-openstack-cpi-release/ci/tasks/terraform-destroy-lifecycle.yml + params: *lifecycle-terraform-params - - do: - - task: deploy - tags: [openstack] - timeout: *timeouts-long - file: bosh-openstack-cpi-release/ci/tasks/deploy-manual-networking.yml - params: - openstack_flavor: "m1.small" - openstack_connection_timeout: "600" - openstack_read_timeout: "180" - openstack_write_timeout: "180" - openstack_state_timeout: "900" - openstack_auth_url: ((concourse_openstack_auth.auth_url)) - openstack_username: ((config-json.openstack_username)) - openstack_api_key: ((config-json.openstack_password)) - openstack_domain: ((concourse_openstack_auth.openstack_domain)) - distro: "ubuntu" - availability_zone: ((config-json.availability_zone)) - #NOTE: The CA cert path here is currently relative to the 'bosh-director-deployment' directory. - openstack_ca_file_path: ((concourse_openstack_auth.openstack_ca_cert_path)) - DEBUG_BATS: *debug_bats - - - task: test - tags: [openstack] + - task: bats-apply-terraform timeout: *timeouts-long - file: bosh-openstack-cpi-release/ci/tasks/run-manual-networking-bats.yml - params: - stemcell_name: "bosh-openstack-kvm-ubuntu-jammy-go_agent" - openstack_flavor_with_ephemeral_disk: ((config-json.openstack_flavor_with_ephemeral_disk)) - openstack_flavor_with_no_ephemeral_disk: ((config-json.openstack_flavor_with_no_ephemeral_disk)) - availability_zone: ((config-json.availability_zone)) - DEBUG_BATS: *debug_bats - bats_rspec_tags: "--tag ~ssh" - ensure: - task: print-task-errors - tags: [openstack] + image: terraform-image + file: bosh-openstack-cpi-release/ci/tasks/terraform-apply-bats-manual.yml + params: &bats-terraform-vars + TF_VAR_prefix: "bats-ubuntu-manual" + TF_VAR_auth_url: http://10.100.30.2/identity + TF_VAR_domain_name: Default + TF_VAR_user_name: ((openstack_ci_user.username)) + TF_VAR_password: ((openstack_ci_user.password)) + TF_VAR_project_name: bosh + TF_VAR_region_name: RegionOne + TF_VAR_primary_net_name: "bats-ubuntu-manual-primary" + TF_VAR_primary_net_cidr: "10.0.4.0/24" + TF_VAR_primary_net_allocation_pool_start: "10.0.4.200" + TF_VAR_primary_net_allocation_pool_end: "10.0.4.254" + TF_VAR_secondary_net_name: "bats-ubuntu-manual-secondary" + TF_VAR_secondary_net_cidr: "10.0.5.0/24" + TF_VAR_secondary_net_allocation_pool_start: "10.0.5.200" + TF_VAR_secondary_net_allocation_pool_end: "10.0.5.254" + TF_VAR_ext_net_name: public + TF_VAR_ext_net_cidr: 172.24.4.0/24 + TF_VAR_dns_nameservers: '["8.8.8.8"]' + TF_VAR_concourse_external_network_cidr: 0.0.0.0/0 + TF_VAR_openstack_default_key_public_key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHspetaTfg96YfZO3/xjKxGcjTnFPlxp7uP1KDisvPjB devstack-ci-openstack + + - do: + - task: bats-deploy-director timeout: *timeouts-long - file: bosh-openstack-cpi-release/ci/tasks/print_task_errors.yml - ensure: - do: - - task: teardown-director - tags: [openstack] + file: bosh-openstack-cpi-release/ci/tasks/deploy-manual-networking.yml + params: + openstack_flavor: "m1.small" + openstack_connection_timeout: "600" + openstack_read_timeout: "180" + openstack_write_timeout: "180" + openstack_state_timeout: "900" + openstack_auth_url: http://10.100.30.2/identity + openstack_username: ((openstack_ci_user.username)) + openstack_api_key: ((openstack_ci_user.password)) + openstack_domain: Default + distro: "ubuntu" + availability_zone: nova + DEBUG_BATS: *debug_bats + + - task: run-bats timeout: *timeouts-long - file: bosh-openstack-cpi-release/ci/tasks/teardown-director.yml + file: bosh-openstack-cpi-release/ci/tasks/run-manual-networking-bats.yml + params: + stemcell_name: "bosh-openstack-kvm-ubuntu-jammy-go_agent" + openstack_flavor_with_ephemeral_disk: with-ephemeral-disk + openstack_flavor_with_no_ephemeral_disk: without-ephemeral-disk + availability_zone: nova + DEBUG_BATS: *debug_bats + bats_rspec_tags: "--tag ~ssh" ensure: - task: terraform-destroy - tags: [openstack] + task: bats-print-errors timeout: *timeouts-long - image: terraform-image - file: bosh-openstack-cpi-release/ci/tasks/terraform-destroy-bats-manual.yml - params: *bats-terraform-vars + file: bosh-openstack-cpi-release/ci/tasks/print_task_errors.yml + + ensure: + put: destroy-devstack + resource: gcp-devstack + params: + terraform_source: bosh-openstack-cpi-release/ci/terraform/ci/gcp-devstack + action: destroy + get_params: + action: destroy - name: bump-major serial_groups: [ version ] @@ -255,8 +210,7 @@ jobs: - get: bosh-openstack-cpi-release trigger: true passed: - - lifecycle - - bats-ubuntu-manual + - run-devstack-tests - get: bosh-shared-ci - get: version resource: release-version-semver @@ -319,14 +273,12 @@ jobs: - get: bosh-shared-ci - get: bosh-openstack-cpi-release passed: - - lifecycle - - bats-ubuntu-manual + - run-devstack-tests - get: version resource: release-version-semver trigger: true - get: release-notes - task: promote - tags: [openstack] timeout: *timeouts-long file: bosh-shared-ci/tasks/release/create-final-release.yml input_mapping: @@ -339,7 +291,7 @@ jobs: provider: gcs options: credentials_source: static - json_key: '((cloud-foundry-gcp-credentials))' + json_key: '((gcp_json_key))' - put: bosh-openstack-cpi-release timeout: *timeouts-long params: @@ -357,7 +309,31 @@ jobs: params: file: release_metadata/empty-file -- name: bump-deps +- name: bump-go-deps + plan: + - in_parallel: + - get: bosh-openstack-cpi-release + - get: golang-release + - get: openstack-cpi-release-docker-image + - get: weekly + trigger: true + - task: bump-deps + file: golang-release/ci/tasks/shared/bump-deps.yml + input_mapping: + input_repo: bosh-openstack-cpi-release + output_mapping: + output_repo: bosh-openstack-cpi-release + params: + SOURCE_PATH: src/openstack_cpi_golang + - task: run-unit-specs + file: bosh-openstack-cpi-release/ci/tasks/run-unit-specs.yml + image: openstack-cpi-release-docker-image + - put: bosh-openstack-cpi-release + params: + repository: bosh-openstack-cpi-release + rebase: true + +- name: bump-ruby-deps plan: - in_parallel: - get: bosh-openstack-cpi-release @@ -410,7 +386,7 @@ jobs: provider: gcs options: credentials_source: static - json_key: '((cloud-foundry-gcp-credentials))' + json_key: '((gcp_json_key))' - task: bump-ruby-package image: bosh-ecosystem-concourse-image file: ruby-release/ci/tasks/shared/bump-ruby-package.yml @@ -420,7 +396,7 @@ jobs: bosh-release: bosh-openstack-cpi-release params: GIT_USER_NAME: CI Bot - GIT_USER_EMAIL: cf-bosh-eng@pivotal.io + GIT_USER_EMAIL: bots@cloudfoundry.org PACKAGE: ruby-3.1 PACKAGE_PREFIX: "openstack" PRIVATE_YML: | @@ -428,7 +404,7 @@ jobs: provider: gcs options: credentials_source: static - json_key: '((cloud-foundry-gcp-credentials))' + json_key: '((gcp_json_key))' RUBY_VERSION_PATH: src/bosh_openstack_cpi/.ruby-version - task: run-unit-specs file: bosh-openstack-cpi-release/ci/tasks/run-unit-specs.yml @@ -444,31 +420,45 @@ resource_types: check_every: 168h source: &terraform-resource-source-keys repository: ljfranklin/terraform-resource - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: bosh-release type: registry-image check_every: 168h source: repository: dpb587/bosh-release-resource - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: gcs type: registry-image check_every: 168h source: repository: frodenas/gcs-resource - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: semver type: registry-image check_every: 168h source: repository: concourse/semver-resource - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) resources: +- name: gcp-devstack + type: terraform + source: + env_name: openstack-cpi-devstack + backend_type: gcs + backend_config: + bucket: bosh-openstack-cpi-blobs + prefix: terraform/gcp-devstack + credentials: ((gcp_json_key)) + vars: + gcp_credentials_json: ((gcp_json_key)) + os_username: ((openstack_ci_user.username)) + os_password: ((openstack_ci_user.password)) + - name: bosh-shared-ci type: git source: @@ -476,25 +466,25 @@ resources: - name: lifecycle-log type: gcs - tags: [openstack] source: bucket: bosh-openstack-cpi-blobs versioned_file: lifecycle.log - json_key: ((cloud-foundry-gcp-credentials)) + json_key: ((gcp_json_key)) - name: release-notes type: gcs source: bucket: bosh-openstack-cpi-blobs versioned_file: release-notes - json_key: ((cloud-foundry-gcp-credentials)) + json_key: ((gcp_json_key)) - name: bosh-openstack-cpi-release type: git source: - uri: git@github.com:cloudfoundry/bosh-openstack-cpi-release.git + uri: https://github.com/cloudfoundry/bosh-openstack-cpi-release.git branch: master - private_key: ((github_deploy_key_bosh-openstack-cpi-release.private_key)) + username: bosh-admin-bot + password: ((github_public_repo_token)) - name: bosh-openstack-cpi-release-github-release type: github-release @@ -511,8 +501,8 @@ resources: uri: https://github.com/cloudfoundry/bosh-openstack-cpi-release.git branch: release-semver file: VERSION - username: bosh-admin-bot - password: ((github_read_write_token)) + username: ((github_read_write_packages.username)) + password: ((github_read_write_packages.password)) - name: bats type: git @@ -540,24 +530,24 @@ resources: type: docker-image check_every: never source: - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) repository: boshcpi/openstack-cpi-release - name: bosh-ruby-release-registry-image type: registry-image check_every: 168h source: repository: bosh/ruby-release - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: bosh-security-scanner-registry-image type: registry-image check_every: 24h source: repository: bosh/security-scanner - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: golang-release type: git @@ -572,8 +562,8 @@ resources: check_every: 168h source: repository: bosh/bosh-ecosystem-concourse - username: ((docker.username)) - password: ((docker.password)) + username: ((dockerhub_username)) + password: ((dockerhub_password)) - name: weekly type: time source: diff --git a/ci/tasks/deploy-manual-networking.sh b/ci/tasks/deploy-manual-networking.sh index e45348edd..b3dea494b 100755 --- a/ci/tasks/deploy-manual-networking.sh +++ b/ci/tasks/deploy-manual-networking.sh @@ -1,22 +1,23 @@ #!/usr/bin/env bash -set -ex +set -eo pipefail +# shellcheck disable=SC1091 source bosh-openstack-cpi-release/ci/tasks/utils.sh # Variables from pipeline.yml -: ${openstack_flavor:?} -: ${openstack_connection_timeout:?} -: ${openstack_read_timeout:?} -: ${openstack_write_timeout:?} -: ${openstack_state_timeout:?} -: ${openstack_auth_url:?} -: ${openstack_username:?} -: ${openstack_api_key:?} -: ${openstack_domain:?} -: ${openstack_ca_file_path:?} -: ${DEBUG_BATS:?} -: ${distro:?} +: "${openstack_flavor:?}" +: "${openstack_connection_timeout:?}" +: "${openstack_read_timeout:?}" +: "${openstack_write_timeout:?}" +: "${openstack_state_timeout:?}" +: "${openstack_auth_url:?}" +: "${openstack_username:?}" +: "${openstack_api_key:?}" +: "${openstack_domain:?}" +: "${DEBUG_BATS:?}" +: "${distro:?}" +openstack_ca_file_path="${openstack_ca_file_path:-}" optional_value availability_zone # Variables from TF @@ -35,16 +36,15 @@ export_terraform_variable terraform-cpi/metadata "director_public_ip" cpi_release_name="bosh-openstack-cpi" deployment_dir="${PWD}/bosh-director-deployment" -maybe_use_custom_ca_ops_file="" -maybe_load_custom_ca_file="" +maybe_use_custom_ca_ops_file=() +maybe_load_custom_ca_file=() case "$openstack_ca_file_path" in "") - break ;; *) - maybe_use_custom_ca_ops_file="-o ../bosh-deployment/openstack/custom-ca.yml" - maybe_load_custom_ca_file="--var-file=openstack_ca_cert=${openstack_ca_file_path}" + maybe_use_custom_ca_ops_file=(-o ../bosh-deployment/openstack/custom-ca.yml) + maybe_load_custom_ca_file=(--var-file=openstack_ca_cert="${openstack_ca_file_path}") ;; esac @@ -55,26 +55,27 @@ pushd bosh-openstack-cpi-release --tarball "../bosh-openstack-cpi-dev.tgz" popd -cp ./bosh-openstack-cpi-dev.tgz ${deployment_dir}/${cpi_release_name}.tgz -cp ./stemcell-director/*.tgz ${deployment_dir}/stemcell.tgz -prepare_bosh_release ${distro} +cp ./bosh-openstack-cpi-dev.tgz "${deployment_dir}/${cpi_release_name}.tgz" +cp ./stemcell-director/*.tgz "${deployment_dir}/stemcell.tgz" +prepare_bosh_release "${distro}" echo "Calculating MD5 of original stemcell:" -echo $(md5sum stemcell-director/*.tgz) +md5sum stemcell-director/*.tgz echo "Calculating MD5 of copied stemcell:" -echo $(md5sum ${deployment_dir}/stemcell.tgz) +md5sum "${deployment_dir}/stemcell.tgz" -cd ${deployment_dir} +cd "${deployment_dir}" echo "using bosh CLI version..." bosh-go --version echo "check bosh deployment interpolation" +# shellcheck disable=SC2154 bosh-go int ../bosh-deployment/bosh.yml \ --var-errs --var-errs-unused \ --vars-store ./credentials.yml \ -o ../bosh-deployment/openstack/cpi.yml \ - ${maybe_use_custom_ca_ops_file} \ + "${maybe_use_custom_ca_ops_file[@]}" \ -o ../bosh-deployment/external-ip-not-recommended.yml \ -o ../bosh-deployment/misc/source-releases/bosh.yml \ -o ../bosh-deployment/jumpbox-user.yml \ @@ -83,28 +84,28 @@ bosh-go int ../bosh-deployment/bosh.yml \ -o ../bosh-openstack-cpi-release/ci/ops_files/timeouts.yml \ -o ../bosh-openstack-cpi-release/ci/ops_files/remove-registry.yml \ -o ../bosh-openstack-cpi-release/ci/ops_files/move-agent-properties-to-env-for-create-env.yml \ - -v auth_url=${openstack_auth_url} \ - -v availability_zone=${availability_zone:-'~'} \ - -v default_security_groups=[${security_group}] \ - -v default_key_name=${default_key_name} \ + -v auth_url="${openstack_auth_url}" \ + -v availability_zone="${availability_zone:-'~'}" \ + -v default_security_groups="[${security_group}]" \ + -v default_key_name="${default_key_name}" \ -v director_name='bosh' \ - -v dns=${dns} \ - -v internal_ip=${director_private_ip} \ - -v external_ip=${director_public_ip} \ - -v primary_net_id=${primary_net_id} \ - -v internal_cidr=${primary_net_cidr} \ - -v internal_gw=${primary_net_gateway} \ - -v openstack_connection_timeout=${openstack_connection_timeout} \ - -v openstack_project=${openstack_project} \ - -v openstack_domain=${openstack_domain} \ - -v openstack_flavor=${openstack_flavor} \ - -v openstack_password=${openstack_api_key} \ - -v openstack_read_timeout=${openstack_read_timeout} \ - -v openstack_state_timeout=${openstack_state_timeout} \ - -v openstack_username=${openstack_username} \ - -v openstack_write_timeout=${openstack_write_timeout} \ - ${maybe_load_custom_ca_file} \ - -v region=null | tee bosh.yml + -v dns="${dns}" \ + -v internal_ip="${director_private_ip}" \ + -v external_ip="${director_public_ip}" \ + -v primary_net_id="${primary_net_id}" \ + -v internal_cidr="${primary_net_cidr}" \ + -v internal_gw="${primary_net_gateway}" \ + -v openstack_connection_timeout="${openstack_connection_timeout}" \ + -v openstack_project="${openstack_project}" \ + -v openstack_domain="${openstack_domain}" \ + -v openstack_flavor="${openstack_flavor}" \ + -v openstack_password="${openstack_api_key}" \ + -v openstack_read_timeout="${openstack_read_timeout}" \ + -v openstack_state_timeout="${openstack_state_timeout}" \ + -v openstack_username="${openstack_username}" \ + -v openstack_write_timeout="${openstack_write_timeout}" \ + "${maybe_load_custom_ca_file[@]}" \ + -v region=null > bosh.yml echo "deploying BOSH..." bosh-go create-env bosh.yml \ diff --git a/ci/tasks/pipeline-locator.yml b/ci/tasks/pipeline-locator.yml deleted file mode 100644 index 1584a3c5d..000000000 --- a/ci/tasks/pipeline-locator.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -platform: linux - -image_resource: - type: docker-image - source: - repository: bosh/bosh-ecosystem-concourse - -inputs: - - name: pipeline-repo - -params: - PIPELINE_FILENAME: "" - -run: - path: sh - args: - - -ec - - | - echo -n "My pipeline is located in the repo: " - cd pipeline-repo - git remote -v | awk 'NR==1{gsub(/.git/, "", $2); gsub(/github.com:/, "https://github.com/", $2); print $2}' - echo "and it is called: ${PIPELINE_FILENAME}" - echo - echo "Happy continuous thing-doing!" \ No newline at end of file diff --git a/ci/tasks/run-lifecycle.sh b/ci/tasks/run-lifecycle.sh index d8fa017d5..182152e48 100755 --- a/ci/tasks/run-lifecycle.sh +++ b/ci/tasks/run-lifecycle.sh @@ -4,39 +4,50 @@ set -euo pipefail source bosh-openstack-cpi-release/ci/tasks/utils.sh -: ${BOSH_OPENSTACK_DOMAIN:?} -: ${BOSH_OPENSTACK_AUTH_URL_V3:?} -: ${BOSH_OPENSTACK_USERNAME_V3:?} -: ${BOSH_OPENSTACK_API_KEY_V3:?} -: ${BOSH_OPENSTACK_PROJECT:?} -: ${BOSH_CLI_SILENCE_SLOW_LOAD_WARNING:?} -: ${BOSH_OPENSTACK_CONNECT_TIMEOUT:?} -: ${BOSH_OPENSTACK_READ_TIMEOUT:?} -: ${BOSH_OPENSTACK_WRITE_TIMEOUT:?} -: ${BOSH_OPENSTACK_FLAVOR_WITH_NO_ROOT_DISK:?} -: ${BOSH_OPENSTACK_EXCLUDE_CINDER_V1:-""} -: ${BOSH_OPENSTACK_AUTH_URL_V2:-""} -: ${BOSH_OPENSTACK_USERNAME_V2:-""} -: ${BOSH_OPENSTACK_API_KEY_V2:-""} -: ${BOSH_OPENSTACK_CA_CERT:-""} -: ${BOSH_OPENSTACK_VOLUME_TYPE:-""} +: "${BOSH_OPENSTACK_DOMAIN:?}" +: "${BOSH_OPENSTACK_AUTH_URL_V3:?}" +: "${BOSH_OPENSTACK_USERNAME_V3:?}" +: "${BOSH_OPENSTACK_API_KEY_V3:?}" +: "${BOSH_OPENSTACK_PROJECT:?}" +: "${BOSH_CLI_SILENCE_SLOW_LOAD_WARNING:?}" +: "${BOSH_OPENSTACK_CONNECT_TIMEOUT:?}" +: "${BOSH_OPENSTACK_READ_TIMEOUT:?}" +: "${BOSH_OPENSTACK_WRITE_TIMEOUT:?}" +: "${BOSH_OPENSTACK_FLAVOR_WITH_NO_ROOT_DISK:?}" +: "${BOSH_OPENSTACK_EXCLUDE_CINDER_V1:-""}" +: "${BOSH_OPENSTACK_AUTH_URL_V2:-""}" +: "${BOSH_OPENSTACK_USERNAME_V2:-""}" +: "${BOSH_OPENSTACK_API_KEY_V2:-""}" +: "${BOSH_OPENSTACK_CA_CERT:-""}" +: "${BOSH_OPENSTACK_VOLUME_TYPE:-""}" optional_value BOSH_OPENSTACK_AVAILABILITY_ZONE metadata=terraform-cpi/metadata -export BOSH_OPENSTACK_MANUAL_IP=$(cat ${metadata} | jq --raw-output ".manual_ip") -export BOSH_OPENSTACK_ALLOWED_ADDRESS_PAIRS=$(cat ${metadata} | jq --raw-output ".allowed_address_pairs") -export BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_1=$(cat ${metadata} | jq --raw-output ".no_dhcp_manual_ip_1") -export BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_2=$(cat ${metadata} | jq --raw-output ".no_dhcp_manual_ip_2") -export BOSH_OPENSTACK_NET_ID=$(cat ${metadata} | jq --raw-output ".net_id") -export BOSH_OPENSTACK_NET_ID_NO_DHCP_1=$(cat ${metadata} | jq --raw-output ".net_id_no_dhcp_1") -export BOSH_OPENSTACK_NET_ID_NO_DHCP_2=$(cat ${metadata} | jq --raw-output ".net_id_no_dhcp_2") -export BOSH_OPENSTACK_DEFAULT_KEY_NAME=$(cat ${metadata} | jq --raw-output ".default_key_name") -export BOSH_OPENSTACK_FLOATING_IP=$(cat ${metadata} | jq --raw-output ".floating_ip") -export BOSH_OPENSTACK_SECURITY_GROUP_NAME=$(cat ${metadata} | jq --raw-output ".security_group_name") -export BOSH_OPENSTACK_SECURITY_GROUP_ID=$(cat ${metadata} | jq --raw-output ".security_group_id") -pool_name=$(cat ${metadata} | jq --raw-output ".loadbalancer_pool_name") +BOSH_OPENSTACK_MANUAL_IP=$(jq --raw-output ".manual_ip" "${metadata}") +export BOSH_OPENSTACK_MANUAL_IP +BOSH_OPENSTACK_ALLOWED_ADDRESS_PAIRS=$(jq --raw-output ".allowed_address_pairs" "${metadata}") +export BOSH_OPENSTACK_ALLOWED_ADDRESS_PAIRS +BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_1=$(jq --raw-output ".no_dhcp_manual_ip_1" "${metadata}") +export BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_1 +BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_2=$(jq --raw-output ".no_dhcp_manual_ip_2" "${metadata}") +export BOSH_OPENSTACK_NO_DHCP_MANUAL_IP_2 +BOSH_OPENSTACK_NET_ID=$(jq --raw-output ".net_id" "${metadata}") +export BOSH_OPENSTACK_NET_ID +BOSH_OPENSTACK_NET_ID_NO_DHCP_1=$(jq --raw-output ".net_id_no_dhcp_1" "${metadata}") +export BOSH_OPENSTACK_NET_ID_NO_DHCP_1 +BOSH_OPENSTACK_NET_ID_NO_DHCP_2=$(jq --raw-output ".net_id_no_dhcp_2" "${metadata}") +export BOSH_OPENSTACK_NET_ID_NO_DHCP_2 +BOSH_OPENSTACK_DEFAULT_KEY_NAME=$(jq --raw-output ".default_key_name" "${metadata}") +export BOSH_OPENSTACK_DEFAULT_KEY_NAME +BOSH_OPENSTACK_FLOATING_IP=$(jq --raw-output ".floating_ip" "${metadata}") +export BOSH_OPENSTACK_FLOATING_IP +BOSH_OPENSTACK_SECURITY_GROUP_NAME=$(jq --raw-output ".security_group_name" "${metadata}") +export BOSH_OPENSTACK_SECURITY_GROUP_NAME +BOSH_OPENSTACK_SECURITY_GROUP_ID=$(jq --raw-output ".security_group_id" "${metadata}") +export BOSH_OPENSTACK_SECURITY_GROUP_ID +pool_name=$(jq --raw-output ".loadbalancer_pool_name" "${metadata}") if [ "${pool_name}" != "" ]; then export BOSH_OPENSTACK_LBAAS_POOL_NAME=${pool_name} fi @@ -49,14 +60,15 @@ cd bosh-openstack-cpi-release/src/bosh_openstack_cpi bundle install -if [ -n "BOSH_OPENSTACK_EXCLUDE_CINDER_V1" ]; then - rspec_args="--tag ~cinder_v1" +rspec_args=() +if [ -n "${BOSH_OPENSTACK_EXCLUDE_CINDER_V1}" ]; then + rspec_args=(--tag ~cinder_v1) fi if [ -n "${BOSH_OPENSTACK_AUTH_URL_V2}" ]; then - bundle exec rspec -f d $rspec_args spec/integration 2>&1 | tee ../../../output/lifecycle.log + bundle exec rspec -f d "${rspec_args[@]}" spec/integration 2>&1 | tee ../../../output/lifecycle.log else echo "Excluding Keystone V2 tests." - bundle exec rspec -f d $rspec_args spec/integration --exclude-pattern spec/integration/lifecycle_v2_spec.rb 2>&1 | tee ../../../output/lifecycle.log + bundle exec rspec -f d "${rspec_args[@]}" spec/integration --exclude-pattern spec/integration/lifecycle_v2_spec.rb 2>&1 | tee ../../../output/lifecycle.log fi diff --git a/ci/tasks/utils.sh b/ci/tasks/utils.sh index e4a8a8669..9e8303c92 100644 --- a/ci/tasks/utils.sh +++ b/ci/tasks/utils.sh @@ -10,19 +10,20 @@ creds_path() { optional_value() { local name=$1 - local value=$(eval echo '$'$name) + local value + value="${!name}" if [ "$value" == 'replace-me' ] || [ "$value" == 'null' ]; then echo "unsetting optional environment variable $name" - unset $name + unset "$name" fi } init_openstack_cli_env(){ - : ${BOSH_OPENSTACK_AUTH_URL:?} - : ${BOSH_OPENSTACK_USERNAME:?} - : ${BOSH_OPENSTACK_API_KEY:?} - : ${BOSH_OPENSTACK_PROJECT:?} - : ${BOSH_OPENSTACK_DOMAIN_NAME:?} + : "${BOSH_OPENSTACK_AUTH_URL:?}" + : "${BOSH_OPENSTACK_USERNAME:?}" + : "${BOSH_OPENSTACK_API_KEY:?}" + : "${BOSH_OPENSTACK_PROJECT:?}" + : "${BOSH_OPENSTACK_DOMAIN_NAME:?}" optional_value BOSH_OPENSTACK_CA_CERT export OS_DEFAULT_DOMAIN=$BOSH_OPENSTACK_DOMAIN_NAME @@ -35,10 +36,10 @@ init_openstack_cli_env(){ export OS_INTERFACE=$BOSH_OPENSTACK_INTERFACE if [ -n "$BOSH_OPENSTACK_CA_CERT" ]; then - tmpdir=$(mktemp -dt "$(basename $0).XXXXXXXXXX") + tmpdir=$(mktemp -dt "$(basename "$0").XXXXXXXXXX") cacert="$tmpdir/cacert.pem" echo "Writing cacert.pem to $cacert" - echo "$BOSH_OPENSTACK_CA_CERT" > $cacert + echo "$BOSH_OPENSTACK_CA_CERT" > "$cacert" export OS_CACERT=$cacert fi @@ -51,38 +52,40 @@ prepare_bosh_release() { use_compiled_release=true - local s3_path_to_bosh_release=$(find_bosh_compiled_release ${distribution} ${bosh_release_version} ${stemcell_version}) + local s3_path_to_bosh_release + s3_path_to_bosh_release=$(find_bosh_compiled_release "${distribution}" "${bosh_release_version}" "${stemcell_version}") - if [ ! -z ${s3_path_to_bosh_release} ];then + if [ -n "${s3_path_to_bosh_release}" ]; then echo "Using compiled BOSH release: s3://bosh-compiled-release-tarballs/$s3_path_to_bosh_release" - aws --no-sign-request s3 cp s3://bosh-compiled-release-tarballs/${s3_path_to_bosh_release} ${deployment_dir}/bosh-release.tgz + # shellcheck disable=SC2154 + aws --no-sign-request s3 cp "s3://bosh-compiled-release-tarballs/${s3_path_to_bosh_release}" "${deployment_dir}/bosh-release.tgz" else use_compiled_release=false fi - if [ "${use_compiled_release}" = "false" ];then + if [ "${use_compiled_release}" = "false" ]; then echo "Using BOSH release from sources" - if [ -z ${bosh_release_version} ];then - cp ./bosh-release/*.tgz ${deployment_dir}/bosh-release.tgz - else - wget https://bosh.io/d/github.com/cloudfoundry/bosh?v=${bosh_release_version} -O ${deployment_dir}/bosh-release.tgz - echo "$old_bosh_with_registry_sha1 $deployment_dir/bosh-release.tgz" | sha1sum -c - - fi + # shellcheck disable=SC2154 + cp ./bosh-release/*.tgz "${deployment_dir}/bosh-release.tgz" fi } find_bosh_compiled_release(){ local distribution=$1 - local bosh_release_version=${2:-`cat ./bosh-release/version`} - local stemcell_version=${3:-`cat ./stemcell-director/version`} + local bosh_release_version=${2:-$(cat ./bosh-release/version)} + local stemcell_version=${3:-$(cat ./stemcell-director/version)} - local s3_path_to_bosh_release=`aws --no-sign-request s3 ls s3://bosh-compiled-release-tarballs | grep -oE "[^ ](\w|-)*$bosh_release_version.+$distribution.+$stemcell_version.*\.tgz" | sort -r | head -1` - echo ${s3_path_to_bosh_release} + local s3_path_to_bosh_release + s3_path_to_bosh_release=$(aws --no-sign-request s3 ls s3://bosh-compiled-release-tarballs | grep -oE "[^ ](\w|-)*$bosh_release_version.+$distribution.+$stemcell_version.*\.tgz" | sort -r | head -1) + echo "${s3_path_to_bosh_release}" } export_terraform_variable() { local metadata=$1 local variable_name=$2 local prefix=$3 - export ${prefix}${variable_name}=$(cat ${metadata} | jq -c --raw-output ".${variable_name}") + local varname="${prefix}${variable_name}" + local varval + varval=$(jq -c --raw-output ".${variable_name}" "${metadata}") + export "${varname}=${varval}" } diff --git a/ci/tasks/wait-for-devstack.sh b/ci/tasks/wait-for-devstack.sh new file mode 100755 index 000000000..1577700b7 --- /dev/null +++ b/ci/tasks/wait-for-devstack.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Polls the DevStack Keystone endpoint until it answers, so downstream jobs don't start against a +# half-installed cloud. + +set -euo pipefail + +: "${AUTH_URL:?}" +: "${OS_USERNAME:?}" +: "${OS_PASSWORD:?}" +: "${OS_PROJECT:?}" + +echo "waiting for DevStack Keystone at ${AUTH_URL} ..." +for i in $(seq 1 100); do + code="$(curl -s -o /dev/null -m 5 -w '%{http_code}' "${AUTH_URL}" || echo 000)" + if [ "${code}" = "200" ] || [ "${code}" = "300" ]; then + echo "Keystone is up (HTTP ${code})" + break + fi + echo "not ready yet (attempt ${i}, HTTP ${code}); sleeping 30s" + sleep 30 + if [ "${i}" -eq 100 ]; then + echo "timed out waiting for DevStack at ${AUTH_URL}" + exit 1 + fi +done + +echo "waiting for CI user auth (confirms create_project_and_user has run) ..." +for i in $(seq 1 20); do + payload=$(jq -n \ + --arg user "${OS_USERNAME}" \ + --arg pass "${OS_PASSWORD}" \ + --arg project "${OS_PROJECT}" \ + '{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":$user,"domain":{"name":"Default"},"password":$pass}}},"scope":{"project":{"name":$project,"domain":{"name":"Default"}}}}}') + code="$(curl -s -o /dev/null -m 10 -w '%{http_code}' \ + -X POST "${AUTH_URL}/v3/auth/tokens" \ + -H "Content-Type: application/json" \ + -d "${payload}" \ + || echo 000)" + if [ "${code}" = "201" ]; then + echo "CI user auth OK — DevStack fully ready" + exit 0 + fi + echo "auth not ready yet (attempt ${i}, HTTP ${code}); sleeping 30s" + sleep 30 +done + +echo "timed out waiting for CI user auth at ${AUTH_URL}" +exit 1 diff --git a/ci/tasks/wait-for-devstack.yml b/ci/tasks/wait-for-devstack.yml new file mode 100644 index 000000000..5ea8b65df --- /dev/null +++ b/ci/tasks/wait-for-devstack.yml @@ -0,0 +1,11 @@ +--- +platform: linux +inputs: + - name: bosh-openstack-cpi-release +run: + path: bosh-openstack-cpi-release/ci/tasks/wait-for-devstack.sh +params: + AUTH_URL: replace-me + OS_USERNAME: replace-me + OS_PASSWORD: replace-me + OS_PROJECT: replace-me diff --git a/ci/tasks/write-ca-file.sh b/ci/tasks/write-ca-file.sh deleted file mode 100755 index 6ca4ae7df..000000000 --- a/ci/tasks/write-ca-file.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -source bosh-openstack-cpi-release/ci/tasks/utils.sh - -optional_value file_content - -mkdir -p write-file -echo "$(echo ${file_content} | sed -r -e 's/ /\n/g ' -e 's/\nCERTIFICATE-----/ CERTIFICATE-----/g')" > write-file/file diff --git a/ci/tasks/write-ca-file.yml b/ci/tasks/write-ca-file.yml deleted file mode 100644 index bff753317..000000000 --- a/ci/tasks/write-ca-file.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -platform: linux -image_resource: - type: docker-image - source: - repository: boshcpi/openstack-cpi-release -inputs: - - name: bosh-openstack-cpi-release -outputs: - - name: write-file -run: - path: bosh-openstack-cpi-release/ci/tasks/write-ca-file.sh -params: - file_content: replace-me diff --git a/ci/terraform/ci/bats-manual/bats.tf b/ci/terraform/ci/bats-manual/bats.tf index cb51ab528..4c9640a08 100644 --- a/ci/terraform/ci/bats-manual/bats.tf +++ b/ci/terraform/ci/bats-manual/bats.tf @@ -8,11 +8,16 @@ provider "openstack" { cacert_file = var.cacert_file } +data "openstack_networking_network_v2" "ext" { + name = var.ext_net_name + region = var.region_name +} + module "base" { source = "../modules/base" region_name = var.region_name project_name = var.project_name - ext_net_id = var.ext_net_id + ext_net_id = data.openstack_networking_network_v2.ext.id ext_net_cidr = var.ext_net_cidr concourse_external_network_cidr = var.concourse_external_network_cidr openstack_default_key_public_key = var.openstack_default_key_public_key @@ -102,10 +107,6 @@ variable "ext_net_name" { description = "OpenStack external network name to register floating IP" } -variable "ext_net_id" { - description = "OpenStack external network id to create router interface port" -} - variable "ext_net_cidr" { description = "OpenStack external network cidr to define ingress security group rules" } diff --git a/ci/terraform/ci/gcp-devstack/.gitignore b/ci/terraform/ci/gcp-devstack/.gitignore new file mode 100644 index 000000000..283d84eb5 --- /dev/null +++ b/ci/terraform/ci/gcp-devstack/.gitignore @@ -0,0 +1,5 @@ +.terraform/ +*.tfstate +*.tfstate.backup +*.tfplan +.terraform.lock.hcl diff --git a/ci/terraform/ci/gcp-devstack/install-devstack.sh b/ci/terraform/ci/gcp-devstack/install-devstack.sh new file mode 100644 index 000000000..d6d1ff61a --- /dev/null +++ b/ci/terraform/ci/gcp-devstack/install-devstack.sh @@ -0,0 +1,207 @@ +#!/usr/bin/env bash + +# Provisions a self-contained DevStack OpenStack on a fresh Ubuntu 24.04 (Noble) GCP VM. +# Runs as a sudo-capable non-root user. Invoked by the create-devstack CI task. + +set -euo pipefail + +### ----- Tunables (can be overridden via environment variables) --------------------------------- +DEVSTACK_BRANCH="${DEVSTACK_BRANCH:-stable/2025.1}" # Epoxy +STACK_USER="${STACK_USER:-stack}" +STACK_DIR="${STACK_DIR:-/opt/stack}" + +# OpenStack identity defaults — override via environment or VM metadata. +OS_PROJECT="${OS_PROJECT:-bosh}" +OS_USERNAME="${OS_USERNAME:-bosh}" +OS_PASSWORD="${OS_PASSWORD:-bosh-ci-password}" +OS_DOMAIN="${OS_DOMAIN:-Default}" +OS_REGION="${OS_REGION:-RegionOne}" + +# HOST_IP is pinned so auth_url is stable across per-run VMs. Should be set to the VM's static +# internal IP. Falls back to the primary NIC address. +HOST_IP="${HOST_IP:-$(ip -4 route get 1.1.1.1 | awk '{print $7; exit}')}" + +# DevStack external ("public") network. DevStack always regenerates the neutron network UUID, so +# downstream terraform resolves it by name. Only name and CIDR are pinned here. +EXT_NET_NAME="${EXT_NET_NAME:-public}" +FLOATING_RANGE="${FLOATING_RANGE:-172.24.4.0/24}" +PUBLIC_NETWORK_GATEWAY="${PUBLIC_NETWORK_GATEWAY:-172.24.4.1}" + +# CIDR of the Concourse workers that must reach DevStack floating IPs off-box (bosh-concourse subnet). +WORKER_SOURCE_CIDR="${WORKER_SOURCE_CIDR:-10.0.0.0/24}" + +METADATA_OUT="${METADATA_OUT:-/opt/openstack-metadata.json}" +### --------------------------------------------------------------------------------------------- + +log() { echo "[install-devstack] $*"; } + +metadata_attr() { + curl -s -H "Metadata-Flavor: Google" \ + "http://metadata.google.internal/computeMetadata/v1/instance/attributes/$1" 2>/dev/null || true +} + +# The OpenStack user/password are supplied via VM metadata (from CredHub, out of the repo). Falls back +# to the defaults above for manual runs. Called after install_prereqs so curl is present. +load_credentials() { + local u p + u="$(metadata_attr os-username)"; [ -n "$u" ] && OS_USERNAME="$u" + p="$(metadata_attr os-password)"; [ -n "$p" ] && OS_PASSWORD="$p" +} + +install_prereqs() { + export DEBIAN_FRONTEND=noninteractive + sudo apt-get update -y + sudo apt-get install -y git python3 python3-venv python3-pip jq curl net-tools qemu-kvm + if ! id "${STACK_USER}" &>/dev/null; then + sudo useradd -s /bin/bash -d "${STACK_DIR}" -m "${STACK_USER}" + echo "${STACK_USER} ALL=(ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/${STACK_USER}" >/dev/null + fi + sudo chmod 0755 "${STACK_DIR}" +} + +clone_devstack() { + if [[ ! -d "${STACK_DIR}/devstack" ]]; then + sudo -u "${STACK_USER}" git clone https://opendev.org/openstack/devstack "${STACK_DIR}/devstack" \ + --branch "${DEVSTACK_BRANCH}" --depth 1 + fi +} + +write_local_conf() { + # DevStack serves plain HTTP (no tls-proxy): this is a disposable test cloud reached only over the + # bosh-concourse VPC, so no CA to juggle per run. + local admin_password + admin_password=$(printf '%q' "${OS_PASSWORD}") + sudo -u "${STACK_USER}" tee "${STACK_DIR}/devstack/local.conf" >/dev/null </dev/null 2>&1 && openstack \"\$@\"" \ + -- "$@" +} + +configure_offbox_floating_access() { + # Let Concourse workers (off the VM) reach DevStack floating IPs. Traffic is routed here by a GCP VPC + # route (dest=floating_range, next-hop=this VM) + can_ip_forward. OVN's external network drops + # off-subnet sources, so hairpin-SNAT the worker source to the br-ex gateway IP. + sudo sysctl -w net.ipv4.ip_forward=1 + sudo iptables -t nat -C POSTROUTING -s "${WORKER_SOURCE_CIDR}" -d "${FLOATING_RANGE}" -j SNAT --to-source "${PUBLIC_NETWORK_GATEWAY}" 2>/dev/null || \ + sudo iptables -t nat -A POSTROUTING -s "${WORKER_SOURCE_CIDR}" -d "${FLOATING_RANGE}" -j SNAT --to-source "${PUBLIC_NETWORK_GATEWAY}" +} + +register_volumev3_alias() { + # Cinder registers as service type `block-storage`; the fog-openstack gem the CPI/tests use + # expects a `volumev3` service. Register an alias endpoint pointing at the same Cinder URL. + local cinder_url + cinder_url="$(os_admin endpoint list --service block-storage --interface public -f value -c URL | head -1)" + if [[ -n "${cinder_url}" ]]; then + if ! os_admin service list -f value -c Type | grep -qx volumev3; then + os_admin service create --name cinderv3-alias volumev3 + os_admin endpoint create volumev3 public "${cinder_url}" --region "${OS_REGION}" + os_admin endpoint create volumev3 internal "${cinder_url}" --region "${OS_REGION}" + os_admin endpoint create volumev3 admin "${cinder_url}" --region "${OS_REGION}" + fi + fi +} + +create_project_and_user() { + os_admin project show "${OS_PROJECT}" >/dev/null 2>&1 || os_admin project create --domain "${OS_DOMAIN}" "${OS_PROJECT}" + os_admin user show "${OS_USERNAME}" >/dev/null 2>&1 || \ + os_admin user create --domain "${OS_DOMAIN}" --password "${OS_PASSWORD}" "${OS_USERNAME}" + os_admin role add --project "${OS_PROJECT}" --user "${OS_USERNAME}" member || true + os_admin role add --project "${OS_PROJECT}" --user "${OS_USERNAME}" admin || true +} + +create_flavors() { + # Test flavors required by the lifecycle and BATS suites. + os_admin flavor show m1.small >/dev/null 2>&1 || os_admin flavor create --ram 2048 --disk 20 --vcpus 1 m1.small + os_admin flavor show no-root-disk >/dev/null 2>&1 || \ + os_admin flavor create --ram 1024 --disk 0 --vcpus 1 no-root-disk + os_admin flavor show with-ephemeral-disk >/dev/null 2>&1 || \ + os_admin flavor create --ram 1024 --disk 5 --ephemeral 5 --vcpus 1 with-ephemeral-disk + os_admin flavor show without-ephemeral-disk >/dev/null 2>&1 || \ + os_admin flavor create --ram 1024 --disk 5 --ephemeral 0 --vcpus 1 without-ephemeral-disk +} + +bump_quotas() { + os_admin quota set --instances 20 --cores 20 --ram 40960 \ + --volumes 20 --gigabytes 200 \ + --networks 20 --subnets 40 --ports 100 --routers 20 --floating-ips 20 --secgroups 40 \ + "${OS_PROJECT}" +} + +upload_jammy_stemcell() { + # The lifecycle suite uploads its own stemcell via the CPI; BATS needs the Jammy image present in + # Glance for the director/deployment stemcell. Skip if STEMCELL_IMAGE_PATH not provided. + if [[ -n "${STEMCELL_IMAGE_PATH:-}" && -f "${STEMCELL_IMAGE_PATH}" ]]; then + os_admin image show bosh-openstack-kvm-ubuntu-jammy-go_agent >/dev/null 2>&1 || \ + os_admin image create --disk-format qcow2 --container-format bare \ + --file "${STEMCELL_IMAGE_PATH}" bosh-openstack-kvm-ubuntu-jammy-go_agent + else + log "STEMCELL_IMAGE_PATH not set; skipping Glance stemcell upload (lifecycle uploads its own)." + fi +} + +emit_metadata() { + # Values the pipeline may want for debugging; ext net is resolved by NAME downstream (UUID is per-run). + local ext_net_id + ext_net_id="$(os_admin network show "${EXT_NET_NAME}" -f value -c id || true)" + cat </dev/null +{ + "auth_url": "http://${HOST_IP}/identity", + "openstack_domain": "${OS_DOMAIN}", + "openstack_project": "${OS_PROJECT}", + "openstack_username": "${OS_USERNAME}", + "region": "${OS_REGION}", + "ext_net_name": "${EXT_NET_NAME}", + "ext_net_id": "${ext_net_id}", + "ext_net_cidr": "${FLOATING_RANGE}" +} +EOF + log "Wrote ${METADATA_OUT}:"; sudo cat "${METADATA_OUT}" +} + +main() { + install_prereqs + load_credentials + clone_devstack + write_local_conf + run_stack + configure_offbox_floating_access + register_volumev3_alias + create_flavors + bump_quotas + upload_jammy_stemcell + create_project_and_user + emit_metadata + log "DevStack ready." +} + +main "$@" diff --git a/ci/terraform/ci/gcp-devstack/main.tf b/ci/terraform/ci/gcp-devstack/main.tf new file mode 100644 index 000000000..506dbd9ed --- /dev/null +++ b/ci/terraform/ci/gcp-devstack/main.tf @@ -0,0 +1,189 @@ +# GCP-side infrastructure for the OpenStack CPI test environment: an N2 VM that runs DevStack, +# attached to the community Concourse VPC (bosh-concourse) so the Concourse workers can reach it. +# +# Two reachability paths for the workers: +# 1. DevStack API -> the VM's internal IP (allowed by google_compute_firewall.devstack). +# 2. Floating IPs -> routed to the VM (google_compute_route.floating) + can_ip_forward, plus a +# SNAT hairpin rule applied by install-devstack.sh so OVN accepts the off-subnet worker source. +# The VM has no external IP; bosh-concourse Cloud NAT provides egress for the DevStack install. + +provider "google" { + project = var.project + region = var.region + credentials = var.gcp_credentials_json != "" ? var.gcp_credentials_json : null +} + +variable "gcp_credentials_json" { + description = "Service-account JSON key. Leave empty to use GOOGLE_CREDENTIALS / ADC." + type = string + default = "" + sensitive = true +} + +variable "project" { + default = "cloud-foundry-310819" +} + +variable "region" { + default = "europe-west2" +} + +variable "zone" { + default = "europe-west2-a" # same zone as the Concourse workers +} + +variable "network" { + description = "Existing VPC the Concourse workers live in." + default = "bosh-concourse" +} + +variable "subnet_name" { + default = "devstack-openstack-cpi" +} + +variable "subnet_cidr" { + description = "Dedicated subnet; must not overlap 10.0.0.0/24 or the 10.100.x integration ranges." + default = "10.100.30.0/24" +} + +variable "vm_name" { + default = "devstack-openstack-cpi" +} + +variable "machine_type" { + description = "Must be a nested-virt-capable Intel type (e.g. N2). NOT E2 and NOT N2D (no vmx exposed)." + default = "n2-standard-4" +} + +variable "boot_disk_size" { + default = 120 +} + +variable "boot_disk_type" { + default = "pd-balanced" +} + +variable "image" { + default = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2404-lts-amd64" +} + +variable "private_ip" { + description = "Pinned internal IP so the OpenStack auth_url stays stable across per-run VMs." + type = string + default = "10.100.30.2" +} + +variable "floating_range" { + description = "DevStack external/floating network CIDR; routed to the VM for worker reachability." + default = "172.24.4.0/24" +} + +variable "worker_source_ranges" { + description = "CIDRs allowed to reach the VM + floating range (the Concourse worker subnet)." + type = list(string) + default = ["10.0.0.0/24"] +} + +variable "network_tag" { + default = "devstack-openstack-cpi" +} + +variable "os_username" { + description = "OpenStack user the pipeline authenticates as; created inside DevStack by install-devstack.sh." + type = string + default = "bosh" +} + +variable "os_password" { + description = "Password for os_username. Passed to the VM as metadata, never committed to the repo." + type = string + sensitive = true +} + +resource "google_compute_subnetwork" "devstack" { + name = var.subnet_name + ip_cidr_range = var.subnet_cidr + region = var.region + network = var.network +} + +resource "google_compute_instance" "devstack" { + name = var.vm_name + machine_type = var.machine_type + zone = var.zone + tags = [var.network_tag] + + boot_disk { + initialize_params { + image = var.image + size = var.boot_disk_size + type = var.boot_disk_type + } + } + + # Nested KVM for BOSH stemcells. Requires an Intel (N2) type; the flag adds the vmx license. + advanced_machine_features { + enable_nested_virtualization = true + } + + can_ip_forward = true # required to forward floating-range traffic to br-ex + + network_interface { + subnetwork = google_compute_subnetwork.devstack.self_link + network_ip = var.private_ip != "" ? var.private_ip : null + # No access_config: internal-only. Egress via bosh-concourse Cloud NAT. + } + + # DevStack is installed on boot; install-devstack.sh also applies the SNAT hairpin rule. + # os-username/os-password are read by the script from the metadata server (kept out of the repo). + metadata = { + startup-script = file("${path.module}/install-devstack.sh") + os-username = var.os_username + os-password = var.os_password + } +} + +# Route floating IPs to the DevStack VM (longest-prefix match beats the default route). +resource "google_compute_route" "floating" { + name = "${var.vm_name}-floating" + network = var.network + dest_range = var.floating_range + next_hop_instance = google_compute_instance.devstack.self_link + priority = 900 +} + +# Allow the workers to reach the VM (API) and, via the route, the floating range. Target-tagged so it +# cannot affect anything else in the shared VPC. +resource "google_compute_firewall" "devstack" { + name = "${var.vm_name}-access" + network = var.network + direction = "INGRESS" + source_ranges = var.worker_source_ranges + target_tags = [var.network_tag] + + allow { + protocol = "tcp" + } + allow { + protocol = "udp" + } + allow { + protocol = "icmp" + } +} + +output "vm_internal_ip" { + value = google_compute_instance.devstack.network_interface[0].network_ip +} + +output "auth_url" { + value = "http://${google_compute_instance.devstack.network_interface[0].network_ip}/identity" +} + +output "floating_range" { + value = var.floating_range +} + +output "subnet" { + value = google_compute_subnetwork.devstack.self_link +} diff --git a/ci/terraform/ci/gcp-devstack/versions.tf b/ci/terraform/ci/gcp-devstack/versions.tf new file mode 100644 index 000000000..2e5ed753c --- /dev/null +++ b/ci/terraform/ci/gcp-devstack/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 5.0, < 7.0" + } + } +} diff --git a/ci/terraform/ci/lifecycle/lifecycle.tf b/ci/terraform/ci/lifecycle/lifecycle.tf index 90a4f2a5f..1ca3a1490 100644 --- a/ci/terraform/ci/lifecycle/lifecycle.tf +++ b/ci/terraform/ci/lifecycle/lifecycle.tf @@ -8,11 +8,16 @@ provider "openstack" { cacert_file = var.cacert_file } +data "openstack_networking_network_v2" "ext" { + name = var.ext_net_name + region = var.region_name +} + module "base" { source = "../modules/base" region_name = var.region_name project_name = var.project_name - ext_net_id = var.ext_net_id + ext_net_id = data.openstack_networking_network_v2.ext.id ext_net_cidr = "" concourse_external_network_cidr = "" openstack_default_key_public_key = var.openstack_default_key_public_key @@ -63,10 +68,6 @@ variable "region_name" { description = "OpenStack region name" } -variable "ext_net_id" { - description = "OpenStack external network id to create router interface port" -} - variable "ext_net_name" { description = "OpenStack external network name to create router interface port" } diff --git a/src/bosh_openstack_cpi/spec/integration/cpi_logging_spec.rb b/src/bosh_openstack_cpi/spec/integration/cpi_logging_spec.rb index 5840032d4..f2ccf8772 100644 --- a/src/bosh_openstack_cpi/spec/integration/cpi_logging_spec.rb +++ b/src/bosh_openstack_cpi/spec/integration/cpi_logging_spec.rb @@ -25,14 +25,14 @@ 'ephemeral_disk_size' => 2 * 1024, ) - expect(log.string).to match(%r{excon\.request GET https?://.*:\d+/v\d\.\d/}) - expect(log.string).to match(%r{excon\.response HTTP/.*:\d+/v\d\.\d/}) + expect(log.string).to match(%r{excon\.request GET https?://.*:\d+(?:/\w+)*/v\d\.\d/}) + expect(log.string).to match(%r{excon\.response HTTP/.*(?:/\w+)*/v\d\.\d/}) end it 'logs excon exceptions' do cpi.delete_disk('123') - expect(log.string).to match(%r{excon\.error HTTP/1\.1 404 Not Found /v3/.*/volumes/123 params: .*}) + expect(log.string).to match(%r{excon\.error HTTP/1\.1 404 Not Found \S*/v3/\S*volumes/123 params: .*}) expect(log.string).not_to include('excon.error.response') end diff --git a/src/bosh_openstack_cpi/spec/integration/support/integration_config.rb b/src/bosh_openstack_cpi/spec/integration/support/integration_config.rb index 096969fa5..e17fcb5ae 100644 --- a/src/bosh_openstack_cpi/spec/integration/support/integration_config.rb +++ b/src/bosh_openstack_cpi/spec/integration/support/integration_config.rb @@ -45,6 +45,7 @@ def initialize(identity_version = :v3) end @logger = Bosh::Cpi::Logger.new(STDERR) + @logger.level = ::Logger::INFO @logger.set_request_id("fake-#{Random.rand(100000..999999)}") @ca_cert_content = LifecycleHelper.get_config(:ca_cert, nil)