From a89a7ddf72923a30d5e75774ae4c364e88af4e10 Mon Sep 17 00:00:00 2001 From: Thierry Martinez <Thierry.Martinez@inria.fr> Date: Wed, 15 Feb 2023 17:31:42 +0100 Subject: [PATCH] Fix #2: Unique state and runner for a given pipeline This commit makes state filename unique for a given pipeline (and remove this state in the cleaning phase), and adds a unique tag to the runners created for the pipeline for jobs not to be run in runners from other pipelines that run in parallel. --- .gitlab-ci.yml | 72 +++++++++----------------------------- README.md | 28 +++------------ cloud-init.sh.tftpl | 2 +- dynamic-pipeline.yml | 70 ++++++++++++++++++++++++++++++++++++ generate-child-pipeline.sh | 6 ++++ main.tf | 13 +++---- 6 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 dynamic-pipeline.yml create mode 100644 generate-child-pipeline.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1affdae..2f6e6ac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,63 +1,23 @@ -variables: - CI_TEMPLATE_REGISTRY_HOST: registry.gitlab.inria.fr - TF_STATE_NAME: default +workflow: + rules: + - if: $CLOUDSTACK_API_KEY -include: - - template: Terraform/Base.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml - -stages: - - validate - - deploy - - execute - - cleanup - -fmt: +generate-child-pipeline: tags: - linux - small - extends: .terraform:fmt - -validate: - tags: - - linux - - small - extends: .terraform:validate - before_script: - - cp $SSH_PRIVATE_KEY id_rsa - -deploy: - stage: deploy - tags: - - linux - - small - script: - - cp $SSH_PRIVATE_KEY id_rsa - - gitlab-terraform plan -var runner_count=0 - - gitlab-terraform apply - - gitlab-terraform plan -var runner_count=3 - - gitlab-terraform apply - -execute: - stage: execute image: alpine - parallel: - matrix: - - index: [0, 1, 2] - tags: - - terraform - - docker - - runner-$index script: - - echo Greetings from runner $index! + - sh generate-child-pipeline.sh > generated-child-pipeline.yml + artifacts: + paths: + - generated-child-pipeline.yml -cleanup: - stage: cleanup - tags: - - linux - - small - script: - - cd "${TF_ROOT}" - - cp $SSH_PRIVATE_KEY id_rsa - - gitlab-terraform plan -var runner_count=0 - - gitlab-terraform apply - when: always +execute-child-pipeline: + needs: + - generate-child-pipeline + trigger: + include: + - artifact: generated-child-pipeline.yml + job: generate-child-pipeline + diff --git a/README.md b/README.md index 85fbc09..8c75ab6 100644 --- a/README.md +++ b/README.md @@ -33,26 +33,6 @@ configuration file described for the [`terraform](https://gitlab.inria.fr/gitlabci_gallery/orchestration/terraform#the-terraform-configuration-file-maintf) project. -There is one additional variable: `runner_count`, of type `number` . -```terraform -variable "runner_count" { - type = number -} -``` - -The variable `runner_count` has two purposes: -- It allows to deploy a virtual machine conditionally. - Indeed, one can pass `-var runner_count 0` to `terraform plan` - in order to destroy the virtual machine(s). -- It allows to deploy many virtual machines if needed. - For instance, this example deploys 3 copies of the template virtual machine, - to run three jobs in parallel. -It is worth noticing that even if you don't need many copies of a virtual -machine (either because you need only one virtual machine, or because you -need virtual machines with different templates or characteristics), such -a variable `runner_count` is still useful to pass either `1` or `0`, -depending upon whether the virtual machines should be deployed or destroyed. - The virtual machines themselves are specified below. ```terraform resource "cloudstack_instance" "runner" { @@ -177,8 +157,8 @@ execute: ``` There is an additional `cleanup` job that is always executed -(even if previous jobs failed) and destroys all the runners -by assigning `runner_count=0`. +(even if previous jobs failed), destroys all the runners +and deletes the state. ```yaml cleanup: stage: cleanup @@ -188,7 +168,7 @@ cleanup: script: - cd "${TF_ROOT}" - cp $SSH_PRIVATE_KEY id_rsa - - gitlab-terraform plan -var runner_count=0 - - gitlab-terraform apply + - gitlab-terraform destroy + - 'curl --user "gitlab-ci-token:$CI_JOB_TOKEN" --request DELETE "$CI_API_V4_URL/projects/$CI_PROJECT_ID/terraform/state/$TF_STATE_NAME"' when: always ``` diff --git a/cloud-init.sh.tftpl b/cloud-init.sh.tftpl index 2b4d6de..4111b67 100644 --- a/cloud-init.sh.tftpl +++ b/cloud-init.sh.tftpl @@ -16,7 +16,7 @@ # We install docker.io to be able to register a docker executor apt-get install --yes gitlab-runner docker.io gitlab-runner register --non-interactive \ - --tag-list terraform,docker,runner-${index} \ + --tag-list terraform,docker,pipeline-${CI_PARENT_PIPELINE_ID},runner-${index} \ --executor docker --docker-image alpine --url https://gitlab.inria.fr \ --registration-token ${REGISTRATION_TOKEN} ) >>/root/log.txt 2>&1 diff --git a/dynamic-pipeline.yml b/dynamic-pipeline.yml new file mode 100644 index 0000000..6296b34 --- /dev/null +++ b/dynamic-pipeline.yml @@ -0,0 +1,70 @@ +# Workaround for child pipeline to work in merge requests +# See: https://gitlab.com/gitlab-org/gitlab/-/issues/222370#note_662695503 +workflow: + rules: + - if: $CI_MERGE_REQUEST_IID + - if: $CI_COMMIT_BRANCH + +variables: + CI_TEMPLATE_REGISTRY_HOST: registry.gitlab.inria.fr + TF_STATE_NAME: pipeline-$CI_PARENT_PIPELINE_ID + TF_VAR_CI_PARENT_PIPELINE_ID: $CI_PARENT_PIPELINE_ID + +include: + - template: Terraform/Base.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml + +stages: + - validate + - deploy + - execute + - cleanup + +fmt: + tags: + - linux + - small + extends: .terraform:fmt + +validate: + tags: + - linux + - small + extends: .terraform:validate + before_script: + - cp $SSH_PRIVATE_KEY id_rsa + +deploy: + stage: deploy + tags: + - linux + - small + script: + - cp $SSH_PRIVATE_KEY id_rsa + - gitlab-terraform plan + - gitlab-terraform apply + +execute: + stage: execute + image: alpine + parallel: + matrix: + - index: [0, 1, 2] + tags: + - terraform + - docker + - pipeline-$CI_PARENT_PIPELINE_ID + - runner-$index + script: + - echo Greetings from runner $index! + +cleanup: + stage: cleanup + tags: + - linux + - small + script: + - cd "${TF_ROOT}" + - cp $SSH_PRIVATE_KEY id_rsa + - gitlab-terraform destroy + - 'curl --user "gitlab-ci-token:$CI_JOB_TOKEN" --request DELETE "$CI_API_V4_URL/projects/$CI_PROJECT_ID/terraform/state/$TF_STATE_NAME"' + when: always diff --git a/generate-child-pipeline.sh b/generate-child-pipeline.sh new file mode 100644 index 0000000..b127e0f --- /dev/null +++ b/generate-child-pipeline.sh @@ -0,0 +1,6 @@ +set -ex +cat <<EOF +include: "dynamic-pipeline.yml" +variables: + CI_PARENT_PIPELINE_ID: "$CI_PIPELINE_ID" +EOF diff --git a/main.tf b/main.tf index 7683dcf..86bb8b4 100644 --- a/main.tf +++ b/main.tf @@ -24,13 +24,13 @@ variable "SSH_PUBLIC_KEY" { type = string } -variable "runner_count" { +variable "CI_PARENT_PIPELINE_ID" { type = number } resource "cloudstack_instance" "runner" { - count = var.runner_count - name = "gitlabcigallery-terraform-runner-${count.index}" + count = 3 + name = "gitlabcigallery-terraform-pipeline-${var.CI_PARENT_PIPELINE_ID}-${count.index}" service_offering = "Custom" template = "ubuntu-20.04-lts" zone = "zone-ci" @@ -40,9 +40,10 @@ resource "cloudstack_instance" "runner" { } expunge = true user_data = templatefile("cloud-init.sh.tftpl", { - index = count.index - REGISTRATION_TOKEN = var.REGISTRATION_TOKEN - SSH_PUBLIC_KEY = var.SSH_PUBLIC_KEY + index = count.index + REGISTRATION_TOKEN = var.REGISTRATION_TOKEN + SSH_PUBLIC_KEY = var.SSH_PUBLIC_KEY + CI_PARENT_PIPELINE_ID = var.CI_PARENT_PIPELINE_ID }) connection { type = "ssh" -- GitLab