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

refactor: use $environment_type & $environment_name

Deprecated $appname and $env dynamic variables with $environment_name & $environment_type
With backward compatibility (legacy vars still usable)
parent 14f19f5f
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -251,10 +251,10 @@ The following hook scripts are supported on **deployment jobs**:

Deployment hook scripts may use the following environment variables:

* `$appname`: the application target name to use in this environment
* `$env`: the environment type (`review`, `integration`, `staging` or `production`)
* `$tmpappname`: the application current name being used during the deployment in this environment (different 
  from `$appname` during a blue/green deployment for instance)
* `$environment_name`: the application target name to use in this environment
* `$environment_type`: the environment type (`review`, `integration`, `staging` or `production`)
* `$tmp_environment_name`: the application current name being used during the deployment in this environment (different 
  from `$environment_name` during a blue/green deployment for instance)
* `$hostname`: the current hostname being used during the deployment in this environment 
* `$domain`: the Cloud Foundry domain being used during the deployment in this environment
* `$routepath`: the Cloud Foundry route path being used during the deployment in this environment
@@ -269,7 +269,7 @@ The following hook scripts are supported on **cleanup jobs**:

Cleanup hook scripts may use the following environment variables:

* `$appname`: the name of the application in this environment
* `$environment_name`: the name of the application in this environment
* any [GitLab CI environment](https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables).

##### Cleanup job limitations
@@ -317,7 +317,7 @@ Deployment jobs support a versatile way to evaluate the **deployment manifest**.

#### Manifest file lookup

1. look for a specific `manifest-$env.yml` in your project (e.g. `manifest-staging.yml` for staging environment),
1. look for a specific `manifest-$environment_type.yml` in your project (e.g. `manifest-staging.yml` for staging environment),
2. fallbacks to default `manifest.yml`.

#### Variables replacement support
@@ -325,13 +325,13 @@ Deployment jobs support a versatile way to evaluate the **deployment manifest**.
Deployment jobs support Cloud Foundry [variables replacement](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#-add-variables-to-a-manifest)
  with the following variables:
  
* `((appname))`: the application target name to use in this environment
* `((environment_name))`: the application target name to use in this environment
* `((env))`: the environment type (`review`, `integration`, `staging` or `production`)
* `((hostname))`: the current hostname being used during the deployment in this environment
* merged with file `cf-vars-$env.yml` if present in your project (e.g. `cf-vars-staging.yml` for staging environment).
* or merged with file `cf-vars.yml` if present in your project **and no `cf-vars-$env.yml` file was found**.
* merged with file `cf-vars-$environment_type.yml` if present in your project (e.g. `cf-vars-staging.yml` for staging environment).
* or merged with file `cf-vars.yml` if present in your project **and no `cf-vars-$environment_type.yml` file was found**.

:warning: your `cf-vars-$env.yml` or `cf-vars.yml` files **may** contain variable patterns such as `${MY_SECRET}`.
:warning: your `cf-vars-$environment_type.yml` or `cf-vars.yml` files **may** contain variable patterns such as `${MY_SECRET}`.
If so, those patterns will be evaluated (replaced) with actual environment values. Beware that those values can be leaked by the `cf push` output.
Multiline variables must be surrounded by **double quotes** (`"`).

@@ -350,7 +350,7 @@ Here is the general recommendation (for each one of your environments):
      to use none).
* if the application is mapped to **several routes**:
    * declare the [routes in your manifest](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#routes),
      possibly using `((appname))` and `((hostname))` variables,
      possibly using `((environment_name))` and `((hostname))` variables,
    * set the `$CF_xxx_HOST_NAME` variable to override the hostname to use (or leave unset to use default),
    * `xxx-domain` input or `$CF_xxx_DOMAIN` variables won't be used,
    * `xxx-route-path` input or `$CF_xxx_ROUTE_PATH` variables won't be used. 
@@ -550,7 +550,7 @@ build:
When deploying to review environment, the application name is **generated** (after the project and branch name).
So the project should either not specify the application name in the manifest, or use a specific `manifest-review.yml`
with [variabilized](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#-add-variables-to-a-manifest) 
`((appname))`.
`((environment_name))`.

### Spring Boot back-end

@@ -609,11 +609,11 @@ applications:
  memory: 768m
  instances: 1
  services:
    - ((appname))-db
    - ((environment_name))-db
```

This file will be used for review and staging environments, and uses [variables](https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#-add-variables-to-a-manifest) 
for the MySQL service name (built from `((appname))`).
for the MySQL service name (built from `((environment_name))`).

The manifest doesn't need to specify the application name because it is explicitly set by the template deployment scripts.

@@ -649,11 +649,11 @@ It also uses specific scalability settings (instances & memory).

##### `cf-pre-push.sh`

This script should ensure the required database is created, naming the database service after the application target name (`$appname`).
This script should ensure the required database is created, naming the database service after the application target name (`$environment_name`).

```bash
#!/bin/bash
dbname="${appname:-myproject-backend}-db"
dbname="${environment_name:-myproject-backend}-db"
echo "maybe create database '$dbname'..."
cf service $dbname || cf create-service c-mysql 100mb $dbname
```
@@ -686,11 +686,11 @@ exit 1

##### `cf-post-cleanup.sh`

This script should cleanup the database, naming the database service after the application target name (`$appname`).
This script should cleanup the database, naming the database service after the application target name (`$environment_name`).

```bash
#!/bin/bash
dbname="${appname:-myproject-backend}-db"
dbname="${environment_name:-myproject-backend}-db"
echo "maybe delete database '$dbname'..."
cf delete-service $dbname -f
```
+74 −55
Original line number Diff line number Diff line
@@ -540,14 +540,16 @@ stages:

  function generate_vars_file() {
    # 1: dynamic template variables
    echo -e "appname: $appname\\ntmpappname: $tmpappname\\nhostname: $hostname\\ndomain: $domain\\nenv: $env" > "$targetvarfile"
    echo -e "environment_name: $environment_name\\ntmp_environment_name: $tmp_environment_name\\nhostname: $hostname\\ndomain: $domain\\nenvironment_type: $environment_type" > "$targetvarfile"
    # backward compatibility
    echo -e "appname: $environment_name\\ntmpappname: $tmp_environment_name\\nenv: $environment_type" >> "$targetvarfile"

    # 2: maybe merge with vars file from project
    envvarfile="$CF_SCRIPTS_DIR/cf-vars-${env}.yml"
    envvarfile="$CF_SCRIPTS_DIR/cf-vars-${environment_type}.yml"
    globvarfile="$CF_SCRIPTS_DIR/cf-vars.yml"
    if [[ -f "${envvarfile}" ]]
    then
      log_info "--- variables file for env \\e[33;1m${env}\\e[0m (\\e[33;1m${envvarfile}\\e[0m) found"
      log_info "--- variables file for env \\e[33;1m${environment_type}\\e[0m (\\e[33;1m${envvarfile}\\e[0m) found"
      awkenvsubst < "$envvarfile" >> "$targetvarfile"
    elif [[ -f "${globvarfile}" ]]
    then
@@ -562,18 +564,19 @@ stages:

  function push_application() {
    log_info "--- \\e[32mcf push\\e[0m"
    log_info "--- tmpappname: \\e[33;1m${tmpappname}\\e[0m"
    log_info "--- appname: \\e[33;1m${appname}\\e[0m"
    log_info "--- hostname: \\e[33;1m${hostname}\\e[0m"
    log_info "--- routepath: \\e[33;1m${routepath:-(n/a)}\\e[0m"
    log_info "--- \$tmp_environment_name: \\e[33;1m${tmp_environment_name}\\e[0m"
    log_info "--- \$environment_name: \\e[33;1m${environment_name}\\e[0m"
    log_info "--- \$hostname: \\e[33;1m${hostname}\\e[0m"
    log_info "--- \$routepath: \\e[33;1m${routepath:-(n/a)}\\e[0m"
    log_info "--- manifest: \\e[33;1m${manifestfile}\\e[0m"
    cf_push_args=("$tmpappname" "--vars-file" "$targetvarfile")

    cf_push_args=("$tmp_environment_name" "--vars-file" "$targetvarfile")
    # shellcheck disable=SC2206
    cf_push_args+=($pushargs)

    # extract routes from manifest and replace vars
    routes_from_manifest=$(get_routes "$manifestfile")
    if [[ -n "$routes_from_manifest" && "$appname" == "$tmpappname" ]]
    if [[ -n "$routes_from_manifest" && "$environment_name" == "$tmp_environment_name" ]]
    then
        # routes are defined in the manifest AND this isn't a blue/green deployment: use routes from manifest
        log_info "--- using routes from manifest (\\e[33;1m${routes_from_manifest}\\e[0m)"
@@ -593,16 +596,16 @@ stages:
    fi
    cf_push_args+=("-f" "$manifestfile")

    if [[ "$appname" == "$tmpappname" && -n "$ENV_RETIRED_APP_SUFFIX" ]] && app_present "$appname"
    if [[ "$environment_name" == "$tmp_environment_name" && -n "$ENV_RETIRED_APP_SUFFIX" ]] && app_present "$environment_name"
    then

      # keep retired version for non blue/green deployment
      app_retired_name="${appname}-$ENV_RETIRED_APP_SUFFIX"
      app_retired_name="${environment_name}-$ENV_RETIRED_APP_SUFFIX"

      log_info "--- delete previous retired version \\e[33;1m${app_retired_name}\\e[0m..."
      cf delete "$app_retired_name" -f
      log_info "--- retiring current app (rename \\e[33;1m${appname}\\e[0m to \\e[33;1m${app_retired_name}\\e[0m)..."
      cf rename "$appname" "$app_retired_name"
      log_info "--- retiring current app (rename \\e[33;1m${environment_name}\\e[0m to \\e[33;1m${app_retired_name}\\e[0m)..."
      cf rename "$environment_name" "$app_retired_name"
      
      unmap_app_routes "$app_retired_name"
      cf stop "$app_retired_name"
@@ -617,7 +620,7 @@ stages:
      log_info "--- \\e[32mpre-start hook\\e[0m (\\e[33;1m${pre_start}\\e[0m) found: execute"
      chmod +x "$pre_start"
      "$pre_start"
      cf start "$tmpappname"
      cf start "$tmp_environment_name"
    else
      log_info "--- auto-start: \\e[94;1myes\\e[0m"

@@ -634,7 +637,7 @@ stages:
    if [[ "$map_route_required" ]]
    then
      log_info "--- map route (\\e[33;1m${hostname}.${domain}\\e[0m)"
      cf map-route "$tmpappname" "$domain" --hostname "$hostname" ${routepath:+--path "$routepath"}
      cf map-route "$tmp_environment_name" "$domain" --hostname "$hostname" ${routepath:+--path "$routepath"}
    fi
  }

@@ -678,11 +681,9 @@ stages:
  }

  function simple_deploy() {
    export env=$1
    # for backward compatibility
    export stage=$1
    export tmpappname=$2
    export appname=$2
    export environment_type=$1
    export tmp_environment_name=$2
    export environment_name=$2
    export hostname=$3
    export domain=$4
    if [[ "$5" = "/*" ]]
@@ -695,23 +696,30 @@ stages:
      export routepath="/$5"
    fi
    export pushargs=$6
    # 7th argument is explicit target appname (for blue/green)
    # 7th argument is explicit target environment_name (for blue/green)
    if [[ "$7" ]]
    then
      appname="$7"
      environment_name="$7"
    fi

    # backward compatibility
    export env=$environment_type
    export stage=$environment_type
    export appname=$environment_name

    # find manifest
    manifestfile=$(ls -1 "$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}-${env}.yml" 2>/dev/null || ls -1 "$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}.yml" 2>/dev/null || echo "")
    manifestfile=$(ls -1 "$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}-${environment_type}.yml" 2>/dev/null || ls -1 "$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}.yml" 2>/dev/null || echo "")
    if [[ -z "$manifestfile" ]]
    then
      log_error "Manifest not found, lookedup paths are:\n - \\e[33;1m$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}-${env}.yml\\e[0m\n - \\e[33;1m$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}.yml\\e[0m"
      log_error "Manifest not found, lookedup paths are:\n - \\e[33;1m$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}-${environment_type}.yml\\e[0m\n - \\e[33;1m$CF_SCRIPTS_DIR/${CF_MANIFEST_BASENAME}.yml\\e[0m"
      exit 1
    fi
    export manifestfile

    log_info "--- \\e[32mdeploy\\e[0m (env: \\e[33;1m${env}\\e[0m)"
    log_info "--- looking for CF scripts in directory: \\e[33;1m${CF_SCRIPTS_DIR}\\e[0m"
    log_info "--- \\e[32mdeploy\\e[0m"
    log_info "--- \$environment_type: \\e[33;1m${environment_type}\\e[0m"
    log_info "--- \$environment_name: \\e[33;1m${environment_name}\\e[0m"
    log_info "--- \$hostname: \\e[33;1m${hostname}\\e[0m"

    pre_push

@@ -738,16 +746,17 @@ stages:
  }

  function blue_green_deploy() {
    export env=$1
    # for backward compatibility
    export stage=$1
    export environment_type=$1
    app_target=$2
    hostname_target=$3
    domain_target=$4
    vroute_path=$5
    push_args=$6

    log_info "--- \\e[32mblue_green_deploy\\e[0m (env: \\e[33;1m${env}\\e[0m)"
    # for backward compatibility
    export stage=$environment_type

    log_info "--- \\e[32mblue_green_deploy\\e[0m"
    app_tmp=${app_target}-tmp
    hostname_tmp=${hostname_target}-tmp
    domain_tmp=$(default_domain)
@@ -762,7 +771,7 @@ stages:
      else
        # simple deployment
        log_info "app \\e[33;1m${app_target}\\e[0m not found: proceed with simple deployment"
        simple_deploy "$env" "$app_target" "$hostname_target" "$domain_target" "$vroute_path" "$push_args"
        simple_deploy "$environment_type" "$app_target" "$hostname_target" "$domain_target" "$vroute_path" "$push_args"
        return 0
      fi
    fi
@@ -773,7 +782,7 @@ stages:
    # try/catch-like pattern
    set -E
    trap 'blue_green_rollback "$app_tmp"' ERR
    simple_deploy "$env" "$app_tmp" "$hostname_tmp" "$domain_tmp" "$vroute_path" "$push_args" "$app_target"
    simple_deploy "$environment_type" "$app_tmp" "$hostname_tmp" "$domain_tmp" "$vroute_path" "$push_args" "$app_target"
    set +E

    # map target route(s) to "green"
@@ -784,7 +793,7 @@ stages:
        for route in $routes_from_manifest
        do
            # replace vars
            route=${route//((appname))/$app_target}
            route=${route//((environment_name))/$app_target}
            route=${route//((hostname))/$hostname_target}
            # extract hostname and domain
            route_host=$(echo "$route" | cut -d '.' -f1)
@@ -821,7 +830,6 @@ stages:
      cf rename "$app_target" "$app_retired_name"
      unmap_app_routes "$app_retired_name"
      cf stop "$app_retired_name"

    fi
    echo

@@ -834,27 +842,31 @@ stages:
  }

  function deploy() {
    env=$1
    environment_type=$1
    # zero downtime
    zdt=$2
    appname=$3
    environment_name=$3
    hostname=$4
    domain=${5:-$(default_domain)}
    routepath=${6}
    pushargs=${7}

    # unset any upstream deployment env & artifacts
    rm -f cloudfoundry.env
    rm -f environment_url.txt

    if [[ "$zdt" = "true" ]] && [[ "$CF_ROLLING_STRATEGY" != "true" ]]
    then
      # blue/green deploy
      blue_green_deploy "$env" "$appname" "$hostname" "$domain" "$routepath" "$pushargs"
      blue_green_deploy "$environment_type" "$environment_name" "$hostname" "$domain" "$routepath" "$pushargs"
    else
      # simple deploy
      simple_deploy "$env" "$appname" "$hostname" "$domain" "$routepath" "$pushargs"
      simple_deploy "$environment_type" "$environment_name" "$hostname" "$domain" "$routepath" "$pushargs"
    fi

    # finally persist environment url
    echo "$CI_ENVIRONMENT_URL" > environment_url.txt
    echo -e "environment_type=$env\\nenvironment_name=$appname\\nenvironment_url=$CI_ENVIRONMENT_URL" > cloudfoundry.env
    echo -e "environment_type=$environment_type\\nenvironment_name=$environment_name\\nenvironment_url=$CI_ENVIRONMENT_URL" > cloudfoundry.env
  }

  function pre_delete() {
@@ -884,38 +896,45 @@ stages:
  }

  function delete() {
    export env=$1
    # for backward compatibility
    export stage=$1
    export appname=$2
    export environment_type=$1
    export environment_name=$2

    # backward compatibility
    export env=$environment_type
    export appname=$environment_name
    export stage=$environment_type

    log_info "--- \\e[32mdelete\\e[0m (env: ${env}, appname: ${appname})"
    log_info "--- \\e[32mdelete\\e[0m"
    log_info "--- \$environment_type: \\e[33;1m${environment_type}\\e[0m"
    log_info "--- \$environment_name: \\e[33;1m${environment_name}\\e[0m"

    pre_delete

    # delete app
    log_info "--- \\e[32mcf delete\\e[0m"
    cf delete "$appname" -f -r
    cf delete "$environment_name" -f -r

    post_delete
  }

  function delete_all() {
    export env=$1
    appnameproto=$2
    # make appname regex by replacing $CI_COMMIT_REF_SLUG with .*
    appnameregex=$(echo "$appnameproto" | sed -r "s/$CI_COMMIT_REF_SLUG/.*/g")
    export environment_type=$1
    environment_nameproto=$2
    # make environment_name regex by replacing $CI_COMMIT_REF_SLUG with .*
    environment_nameregex=$(echo "$environment_nameproto" | sed -r "s/$CI_COMMIT_REF_SLUG/.*/g")
    # list apps | pick 1st column (name) | filter apps with name "$regex"
    matchingapps=$(cf apps | cut -d' ' -f1 | awk "/^$appnameregex/ {print \$1}")
    matchingapps=$(cf apps | cut -d' ' -f1 | awk "/^$environment_nameregex/ {print \$1}")
    matchingappscount=$(echo "$matchingapps" | wc -w)

    log_info "--- \\e[32mdelete all\\e[0m (env: \\e[33;1m${env}\\e[0m, appname matcher: \\e[33;1m${appnameregex}\\e[0m): \\e[33;1m${matchingappscount}\\e[0m apps found"
    log_info "--- \\e[32mdelete all\\e[0m"
    log_info "--- \$environment_type: \\e[33;1m${environment_type}\\e[0m"
    log_info "--- environment name matcher: \\e[33;1m${environment_nameregex}\\e[0m) (\\e[33;1m${matchingappscount}\\e[0m apps found)"

    rc=0
    for matchingapp in $matchingapps
    do
      echo -e "\\e[1;93m-------------------------------------------------------------------------------\\e[0m"
      if ! delete "$env" "$matchingapp"
      if ! delete "$environment_type" "$matchingapp"
      then
        log_warn "... failed deleting review app \\e[33;1m${matchingapp}\\e[0m (see logs)"
        rc=1
@@ -936,8 +955,8 @@ stages:
      do
        key=$(echo "$line" | cut -d: -f1)
        value=$(echo "$line" | cut -d: -f2- | sed 's/^[[:space:]]*//')
        # appname and hostname vars will be replace dynamically (necessary for bluegreen deployment)
        if [[ "$key" != "appname" ]] && [[ "$key" != "hostname" ]]; then
        # environment_name and hostname vars will be replace dynamically (necessary for bluegreen deployment)
        if [[ "$key" != "environment_name" ]] && [[ "$key" != "hostname" ]]; then
          routes=$(
            for r in ${routes}; do
              echo "$r" | sed -E "s/\(\(${key}\)\)/${value//\//\\/}/"
@@ -1192,7 +1211,7 @@ stages:
    - assert_defined "$ENV_SPACE" 'Missing required Cloud Foundry space'
    - cf login -a ${ENV_URL:-$CF_URL} -u ${ENV_USER:-$CF_USER} -p "${ENV_PASSWORD:-$CF_PASSWORD}" -o ${ENV_ORG:-$CF_ORG} -s $ENV_SPACE
  script:
    # use $CI_ENVIRONMENT_SLUG for appname to avoid service name constraints (<=50 chars)
    # use $CI_ENVIRONMENT_SLUG for environment_name to avoid service name constraints (<=50 chars)
    # use $CI_ENVIRONMENT_SLUG for hostname to avoid constraints (<=63 chars)
    - manage_services "create"
    - deploy "$ENV_TYPE" "${ENV_ZERODOWNTIME:-false}" "${ENV_APP_NAME:-${CF_BASE_APP_NAME}${ENV_APP_SUFFIX}}" "${ENV_HOST_NAME:-${CF_BASE_APP_NAME}${ENV_APP_SUFFIX}}" "${ENV_DOMAIN:-${CF_DEFAULT_DOMAIN}}" "${ENV_ROUTE_PATH:-${CF_DEFAULT_ROUTE_PATH}}" "${ENV_PUSH_ARGS:-${CF_DEFAULT_PUSH_ARGS}}"
+5 −5
Original line number Diff line number Diff line
#!/usr/bin/env bash
if [[ -z "$appname" ]]
if [[ -z "$environment_name" ]]
then
  echo "[ERROR] appname env not passed"
  echo "[ERROR] environment_name env not passed"
  exit 1
fi

if [[ -z "$tmpappname" ]]
if [[ -z "$tmp_environment_name" ]]
then
  echo "[ERROR] tmpappname env not passed"
  echo "[ERROR] tmp_environment_name env not passed"
  exit 1
fi

echo "pre-push hook called for $appname/$tmpappname"
echo "pre-push hook called for $environment_name/$tmp_environment_name"
+5 −5
Original line number Diff line number Diff line
#!/usr/bin/env bash
if [[ -z "$appname" ]]
if [[ -z "$environment_name" ]]
then
  echo "[ERROR] appname env not passed"
  echo "[ERROR] environment_name env not passed"
  exit 1
fi

if [[ -z "$tmpappname" ]]
if [[ -z "$tmp_environment_name" ]]
then
  echo "[ERROR] tmpappname env not passed"
  echo "[ERROR] tmp_environment_name env not passed"
  exit 1
fi

echo "pre-start hook called for $appname/$tmpappname"
echo "pre-start hook called for $environment_name/$tmp_environment_name"
+1 −1
Original line number Diff line number Diff line
@@ -11,4 +11,4 @@ then
  exit 1
fi

echo "readiness-check hook called for $appname on $hostname.$domain"
echo "readiness-check hook called for $environment_name on $hostname.$domain"