Commit ea4f606a authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

feat: improve environments url

parent aa9ea238
Loading
Loading
Loading
Loading
+45 −15
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ The AWS template uses some global configuration used throughout all jobs.
| ------------------------ | -------------------------------------- | ----------------- |
| `AWS_CLI_IMAGE`          | the Docker image used to run AWS CLI commands| `amazon/aws-cli:latest` |
| `AWS_BASE_APP_NAME`      | Base application name                  | `$CI_PROJECT_NAME` ([see GitLab doc](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)) |
| `AWS_ENVIRONMENT_URL`    | Default environments url _(only define for static environment URLs declaration)_<br/>_supports late variable expansion (ex: `https://%{appname}.aws.acme.com`)_ | _none_ |
| `AWS_SCRIPTS_DIR`        | Directory where AWS scripts (deploy & cleanup) are located | `.` _(root project dir)_ |
| `AWS_OIDC_ROLE_ARN`    | Default IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) | _none_ (disabled) |

@@ -116,9 +117,28 @@ In order to be able to implement some **genericity** in your scripts and templat
2. any [custom variable](https://docs.gitlab.com/ee/ci/variables/#custom-environment-variables)
    (ex: `${SECRET_TOKEN}` that you have set in your project CI/CD variables)
3. **dynamic variables** set by the template:
    * `${appname}`: the application target name to use in this environment (ex: `myproject-review-fix-bug-12` or `myproject-staging`)
    * `${appname}`: the application target name to use for this environment (ex: `myproject-review-fix-bug-12` or `myproject-staging`) - see below
    * `${env}`: the environment type (`review`, `integration`, `staging` or `production`)
    * `${hostname}`: the environment hostname, extracted from `${CI_ENVIRONMENT_URL}` (has to be explicitly declared as [`environment:url`](https://docs.gitlab.com/ee/ci/yaml/#environmenturl) in your `.gitlab-ci.yml` file)
    * `${hostname}`: the environment hostname, extracted from the current environment url (after late variable expansion - see below)

##### `appname` generation

Each environment is given an _appname_, generated programmatically by the template.

The appname is obtained using:

* `AWS_BASE_APP_NAME` defines the application _base_ name (defaults to `$CI_PROJECT_NAME`)
* `appname=$AWS_BASE_APP_NAME-$CI_ENVIRONMENT_SLUG` except for the production environment, where `appname` is directly `AWS_BASE_APP_NAME` (no suffix)
* each appname can be overriden per environment with the appropriate `AWS_XXX_APP_NAME` variable

Examples (with an application's base name `myapp`):

| `$environment_type` | Branch        | `$CI_ENVIRONMENT_SLUG`  | `$appname` |
|---------------------|---------------|-------------------------|------------|
| review              | `feat/blabla` | `review-feat-bla-xmuzs6`| `myapp-review-feat-bla-xmuzs6` |
| integration         | `main`        | `develop`               | `myapp-integration` |
| staging             | `main`        | `staging`               | `myapp-staging` |
| production          | `main`        | `production`            | `myapp` |

#### AWS authentication

@@ -165,12 +185,25 @@ The AWS template supports two ways of defining your environments url:
* a [**dynamic way**](https://docs.gitlab.com/ee/ci/environments/#set-dynamic-environment-urls-after-a-job-finishes): when the url cannot be known before the
  deployment job is executed.

The static way can be implemented simply by setting the appropriate configuration variables depending on the environments (see environments configuration chapters below):

* `$AWS_REVIEW_ENVIRONMENT_SCHEME` and`$AWS_REVIEW_ENVIRONMENT_DOMAIN` for the review environments, 
* `$AWS_INTEG_ENVIRONMENT_URL`, `$AWS_STAGING_ENVIRONMENT_URL` and `$AWS_PROD_ENVIRONMENT_URL` for others.

To implement the dynamic way, your deployment script shall simply generate a `environment_url.txt` file, containing only
The **static way** can be implemented simply by setting the appropriate configuration variable(s) depending on the environment (see environments configuration chapters below):

* `$AWS_ENVIRONMENT_URL` to define a default url pattern for all your envs,
* `$AWS_REVIEW_ENVIRONMENT_URL`, `$AWS_INTEG_ENVIRONMENT_URL`, `$AWS_STAGING_ENVIRONMENT_URL` and `$AWS_PROD_ENVIRONMENT_URL` to override the default.

> :information_source: Each of those variables support a late variable expansion mechanism with `%{somevar}` syntax, allowing you to use any dynamically evaluated variables such as `$appname`.
>
> Example:
>
> ```yaml
> variables:
>   AWS_BASE_APP_NAME: "wonderapp"
>   # global url for all environments
>   AWS_ENVIRONMENT_URL: "https://%{appname}.nonprod.acme.domain"
>   # override for prod (no need to late exand $AWS_BASE_APP_NAME here)
>   AWS_PROD_ENVIRONMENT_URL: "https://$AWS_BASE_APP_NAME.acme.domain"
> ```

To implement the **dynamic way**, your deployment script shall simply generate a `environment_url.txt` file, containing only
the dynamically generated url.

#### Deployment output variables
@@ -203,10 +236,7 @@ Here are variables supported to configure review environments:
| `AWS_REVIEW_ENABLED`     | AWS project ID for `review` env | _none_ (disabled) |
| `AWS_REVIEW_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `review` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_REVIEW_APP_NAME`    | Application name for `review` env      | `"${AWS_BASE_APP_NAME}-${CI_ENVIRONMENT_SLUG}"` (ex: `myproject-review-fix-bug-12`) |
| `AWS_REVIEW_ENVIRONMENT_SCHEME`| The review environment protocol scheme.<br/>_For static environment URLs declaration_ | `https` |
| `AWS_REVIEW_ENVIRONMENT_DOMAIN`| The review environment domain.<br/>_For static environment URLs declaration_ | _none_ |

Note: If you're managing your environment URLs statically, review environment URLs will be built as `${AWS_REVIEW_ENVIRONMENT_SCHEME}://${$CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${AWS_REVIEW_ENVIRONMENT_DOMAIN}`
| `AWS_REVIEW_ENVIRONMENT_URL`| The review environments url _(only define for static environment URLs declaration and if different from default)_ | `$AWS_ENVIRONMENT_URL` |

#### Integration environment

@@ -221,7 +251,7 @@ Here are variables supported to configure the integration environment:
| `AWS_INTEG_ENABLED`      | AWS project ID for `integration` env | _none_ (disabled) |
| `AWS_INTEG_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `integration` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_INTEG_APP_NAME`     | Application name for `integration` env | `${AWS_BASE_APP_NAME}-integration` |
| `AWS_INTEG_ENVIRONMENT_URL`| The integration environment url (ex: `https://my-application-integration.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |
| `AWS_INTEG_ENVIRONMENT_URL`| The integration environment url _(only define for static environment URLs declaration and if different from default)_ | `$AWS_ENVIRONMENT_URL` |

#### Staging environment

@@ -237,7 +267,7 @@ Here are variables supported to configure the staging environment:
| `AWS_STAGING_ENABLED`    | AWS project ID for `staging` env | _none_ (disabled) |
| `AWS_STAGING_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `staging` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_STAGING_APP_NAME`   | Application name for `staging` env     | `${AWS_BASE_APP_NAME}-staging` |
| `AWS_STAGING_ENVIRONMENT_URL` | The staging environment url (ex: `https://my-application-staging.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |
| `AWS_STAGING_ENVIRONMENT_URL`| The staging environment url _(only define for static environment URLs declaration and if different from default)_ | `$AWS_ENVIRONMENT_URL` |

#### Production environment

@@ -252,7 +282,7 @@ Here are variables supported to configure the production environment:
| `AWS_PROD_ENABLED`        | AWS project ID for `production` env | _none_ (disabled) |
| `AWS_PROD_OIDC_ROLE_ARN`| IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `production` env _(only define if different from global)_ | _none_ (disabled) |
| `AWS_PROD_APP_NAME`       | Application name for `production` env  | `$AWS_BASE_APP_NAME` |
| `AWS_PROD_ENVIRONMENT_URL`| The production environment url (ex: `https://my-application.compute-1.amazonaws.com`).<br/>_For static environment URLs declaration_ | _none_ |
| `AWS_PROD_ENVIRONMENT_URL`| The production environment url _(only define for static environment URLs declaration and if different from default)_ | `$AWS_ENVIRONMENT_URL` |
| `AUTODEPLOY_TO_PROD`      | Set this variable to auto-deploy to production. If not set deployment to production will be `manual` (default behaviour). | _none_ (disabled) |

## Examples
+30 −25
Original line number Diff line number Diff line
@@ -15,6 +15,11 @@
      "default": "$CI_PROJECT_NAME",
      "advanced": true
    },
    {
      "name": "AWS_ENVIRONMENT_URL",
      "type": "url",
      "description": "The default environments url _(only define for static environment URLs declaration)_\n\n_supports late variable expansion (ex: `https://%{environment_name}.aws.acme.com`)_"
    },
    {
      "name": "AWS_OIDC_ROLE_ARN",
      "description": "Default IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/)",
@@ -40,18 +45,15 @@
          "advanced": true
        },
        {
          "name": "AWS_REVIEW_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `review` env _(only define if different from global)_",
          "name": "AWS_REVIEW_ENVIRONMENT_URL",
          "type": "url",
          "description": "The review environments url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "AWS_REVIEW_ENVIRONMENT_SCHEME",
          "description": "The review environment protocol scheme",
          "default": "https"
        },
        {
          "name": "AWS_REVIEW_ENVIRONMENT_DOMAIN",
          "description": "The review environment domain (ex: `noprod-aws.domain.com`).\n\nRequired for static environment URLs declaration only (see doc).\n\nBy default review `environment.url` will be built as `${AWS_REVIEW_ENVIRONMENT_SCHEME}://${$CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${AWS_REVIEW_ENVIRONMENT_DOMAIN}`"
          "name": "AWS_REVIEW_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `review` env _(only define if different from global)_",
          "advanced": true
        }
      ]
    },
@@ -67,14 +69,15 @@
          "advanced": true
        },
        {
          "name": "AWS_INTEG_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `integration` env _(only define if different from global)_",
          "name": "AWS_INTEG_ENVIRONMENT_URL",
          "type": "url",
          "description": "The integration environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "AWS_INTEG_ENVIRONMENT_URL",
          "type": "url",
          "description": "The integration environment url including scheme (ex: `https://my-application-integration.noprod-aws.domain.com`).\n\nRequired for static environment URLs declaration only (see doc).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that."
          "name": "AWS_INTEG_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `integration` env _(only define if different from global)_",
          "advanced": true
        }
      ]
    },
@@ -90,14 +93,15 @@
          "advanced": true
        },
        {
          "name": "AWS_STAGING_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `staging` env _(only define if different from global)_",
          "name": "AWS_STAGING_ENVIRONMENT_URL",
          "type": "url",
          "description": "The staging environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "AWS_STAGING_ENVIRONMENT_URL",
          "type": "url",
          "description": "The staging environment url including scheme (ex: `https://my-application-staging.noprod-aws.domain.com`).\n\nRequired for static environment URLs declaration only (see doc).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that."
          "name": "AWS_STAGING_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `staging` env _(only define if different from global)_",
          "advanced": true
        }
      ]
    },
@@ -113,14 +117,15 @@
          "advanced": true
        },
        {
          "name": "AWS_PROD_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `production` env _(only define if different from global)_",
          "name": "AWS_PROD_ENVIRONMENT_URL",
          "type": "url",
          "description": "The production environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "AWS_PROD_ENVIRONMENT_URL",
          "type": "url",
          "description": "The production environment url including scheme (ex: `https://my-application.aws.domain.com`).\n\nRequired for static environment URLs declaration only (see doc).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that."
          "name": "AWS_PROD_OIDC_ROLE_ARN",
          "description": "IAM Role ARN associated with GitLab to [authenticate using OpenID Connect](https://docs.gitlab.com/ee/ci/cloud_services/aws/) on `production` env _(only define if different from global)_",
          "advanced": true
        },
        {
          "name": "AUTODEPLOY_TO_PROD",
+8 −4
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ stages:
  }
  
  function awkenvsubst() {
    awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);val=ENVIRON[var];gsub(/["\\]/,"\\\\&", val);gsub("\n", "\\n", val);gsub("\r", "\\r", val);gsub("[$]{"var"}",val)}}1'
    awk '{while(match($0,"[$%]{[^}]*}")) {g0=substr($0,RSTART,RLENGTH); val=ENVIRON[substr(g0,3,RLENGTH-3)]; gsub(g0,val)}}1'
  }

  function exec_hook() {
@@ -276,7 +276,10 @@ stages:
  function deploy() {
    export env=$1
    export appname=$2
    export environment_url=$3
    environment_url=$3
    # variables expansion in $environment_url
    environment_url=$(echo "$environment_url" | awkenvsubst)
    export environment_url
    # extract hostname from $environment_url
    hostname=$(echo "$environment_url" | awk -F[/:] '{print $4}')
    export hostname
@@ -366,7 +369,7 @@ stages:
  variables:
    ENV_APP_SUFFIX: "-$CI_ENVIRONMENT_SLUG"
  script:
    - deploy "$ENV_TYPE" "${ENV_APP_NAME:-${AWS_BASE_APP_NAME}${ENV_APP_SUFFIX}}" "$ENV_URL"
    - deploy "$ENV_TYPE" "${ENV_APP_NAME:-${AWS_BASE_APP_NAME}${ENV_APP_SUFFIX}}" "${ENV_URL:-${AWS_ENVIRONMENT_URL:-$ENV_URL_LEGACY}}"
  artifacts:
    name: "$ENV_TYPE env url for $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    paths:
@@ -401,7 +404,8 @@ aws-review:
  variables:
    ENV_TYPE: review
    ENV_APP_NAME: "$AWS_REVIEW_APP_NAME"
    ENV_URL: "${AWS_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${AWS_REVIEW_ENVIRONMENT_DOMAIN}"
    ENV_URL: "${AWS_REVIEW_ENVIRONMENT_URL}"
    ENV_URL_LEGACY: "${AWS_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${AWS_REVIEW_ENVIRONMENT_DOMAIN}"
    ENV_OIDC_ROLE_ARN: "$AWS_REVIEW_OIDC_ROLE_ARN"
  environment:
    name: review/$CI_COMMIT_REF_NAME