Commit 00a733ba authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

Merge branch 'feat/env-url-improvement' into 'master'

Simplify environments url management in deployment templates

See merge request to-be-continuous/openshift!33
parents e8a6e546 4bceed78
Loading
Loading
Loading
Loading
+269 −223

File changed.

Preview size limit exceeded, changes collapsed.

+17 −17
Original line number Diff line number Diff line
@@ -27,6 +27,11 @@
      "default": "$CI_PROJECT_NAME",
      "advanced": true
    },
    {
      "name": "OS_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}.openshift.acme.com`)_"
    },
    {
      "name": "OS_SCRIPTS_DIR",
      "description": "directory where OpenShift scripts (templates, hook scripts) are located",
@@ -35,13 +40,13 @@
    },
    {
      "name": "OS_APP_LABEL",
      "description": "The OpenShift [label](https://docs.openshift.com/container-platform/3.11/dev_guide/templates.html#writing-labels) set with the `$appname` dynamic variable.",
      "description": "The OpenShift [label](https://docs.openshift.com/container-platform/3.11/dev_guide/templates.html#writing-labels) set with the `$environment_name` dynamic variable.",
      "default": "app",
      "advanced": true
    },
    {
      "name": "OS_ENV_LABEL",
      "description": "The OpenShift [label](https://docs.openshift.com/container-platform/3.11/dev_guide/templates.html#writing-labels) set with the `$env` dynamic variable.",
      "description": "The OpenShift [label](https://docs.openshift.com/container-platform/3.11/dev_guide/templates.html#writing-labels) set with the `$environment_type` dynamic variable.",
      "default": "env",
      "advanced": true
    }
@@ -63,15 +68,10 @@
          "advanced": true
        },
        {
          "name": "OS_REVIEW_ENVIRONMENT_SCHEME",
          "description": "The review environment protocol scheme",
          "default": "https",
          "mandatory": true
        },
        {
          "name": "OS_REVIEW_ENVIRONMENT_DOMAIN",
          "description": "The review environment domain (ex: `noprod-openshift.domain.com`).\n\nBy default review `environment.url` will be built as `${OS_REVIEW_ENVIRONMENT_SCHEME}://${$CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${OS_REVIEW_ENVIRONMENT_DOMAIN}`",
          "mandatory": true
          "name": "OS_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": "OS_REVIEW_URL",
@@ -109,8 +109,8 @@
        {
          "name": "OS_INTEG_ENVIRONMENT_URL",
          "type": "url",
          "description": "The integration environment url including scheme (ex: `https://my-application-integration.noprod-openshift.domain.com`).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that.",
          "mandatory": true
          "description": "The integration environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "OS_INTEG_URL",
@@ -143,8 +143,8 @@
        {
          "name": "OS_STAGING_ENVIRONMENT_URL",
          "type": "url",
          "description": "The staging environment url including scheme (ex: `https://my-application-staging.noprod-openshift.domain.com`).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that.",
          "mandatory": true
          "description": "The staging environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "OS_STAGING_URL",
@@ -177,8 +177,8 @@
        {
          "name": "OS_PROD_ENVIRONMENT_URL",
          "type": "url",
          "description": "The production environment url including scheme (ex: `https://my-application.openshift.domain.com`).\n\nDo not use variable inside variable definition as it will result in a two level cascade variable and gitlab does not allow that.",
          "mandatory": true
          "description": "The production environment url _(only define for static environment URLs declaration and if different from default)_",
          "advanced": true
        },
        {
          "name": "AUTODEPLOY_TO_PROD",
+91 −62
Original line number Diff line number Diff line
@@ -313,11 +313,11 @@ stages:
    log_info "--- template: \\e[33;1m${templatefile}\\e[0m"

    # evaluate template parameters from environment and dotenv files
    param_args=$(build_template_param_args "${OS_SCRIPTS_DIR}/${OS_BASE_TEMPLATE_NAME}.env" "${OS_SCRIPTS_DIR}/${OS_BASE_TEMPLATE_NAME}-${env}.env" < "$templatefile")
    param_args=$(build_template_param_args "${OS_SCRIPTS_DIR}/${OS_BASE_TEMPLATE_NAME}.env" "${OS_SCRIPTS_DIR}/${OS_BASE_TEMPLATE_NAME}-${environment_type}.env" < "$templatefile")

    # set label 'app' and 'env' on all created objects ($OS_STAGE_LABEL for backwards compatibility)
    echo "oc process --labels \"${OS_ENV_LABEL:-${OS_STAGE_LABEL:-env}}=$env,${OS_APP_LABEL:-app}=$appname\" $param_args -f $templatefile"
    eval oc process --labels "${OS_ENV_LABEL:-${OS_STAGE_LABEL:-env}}=$env,${OS_APP_LABEL:-app}=$appname" "$param_args" -f "$templatefile" | oc ${TRACE+--loglevel=6} apply -f -
    echo "oc process --labels \"${OS_ENV_LABEL:-${OS_STAGE_LABEL:-env}}=$environment_type,${OS_APP_LABEL:-app}=$environment_name\" $param_args -f $templatefile"
    eval oc process --labels "${OS_ENV_LABEL:-${OS_STAGE_LABEL:-env}}=$environment_type,${OS_APP_LABEL:-app}=$environment_name" "$param_args" -f "$templatefile" | oc ${TRACE+--loglevel=6} apply -f -
  }

  function check_readiness() {
@@ -350,27 +350,39 @@ stages:
    # export project as it may be usefull to build image name based on internal registry (ex: docker-registry.default.svc:5000/${project}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_LABEL} )
    project=$(oc project -q)
    export project
    export env=$1
    # for backward compatibility
    export stage=$1
    export appname=$2
    # also export appname in SCREAMING_SNAKE_CASE format (may be useful with OpenShift env variables)
    appname_ssc=$(to_ssc "$2")
    export appname_ssc
    # extract hostname from $CI_ENVIRONMENT_URL
    hostname=$(echo "$CI_ENVIRONMENT_URL" | awk -F[/:] '{print $4}')
    export environment_type=$1
    export environment_name=$2
    environment_url=$3
    # also export environment_name in SCREAMING_SNAKE_CASE format (may be useful with OpenShift env variables)
    environment_name_ssc=$(to_ssc "$2")
    export environment_name_ssc

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

    # 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

    log_info "--- \\e[32mdeploy\\e[0m (env: \\e[33;1m${env}\\e[0m)"
    log_info "--- looking for OS scripts in directory: \\e[33;1m${OS_SCRIPTS_DIR}\\e[0m"
    log_info "--- project: \\e[33;1m${project}\\e[0m"
    log_info "--- appname: \\e[33;1m${appname}\\e[0m"
    log_info "--- appname_ssc: \\e[33;1m${appname_ssc}\\e[0m"
    log_info "--- env: \\e[33;1m${env}\\e[0m"
    log_info "--- hostname: \\e[33;1m${hostname}\\e[0m"
    log_info "--- \\e[32mdeploy\\e[0m"
    log_info "--- \$project: \\e[33;1m${project}\\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 "--- \$environment_name_ssc: \\e[33;1m${environment_name_ssc}\\e[0m"
    log_info "--- \$hostname: \\e[33;1m${hostname}\\e[0m"

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

    # maybe execute deploy script
    deployscript=$(ls -1 "$OS_SCRIPTS_DIR/os-deploy-${env}.sh" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/os-deploy.sh" 2>/dev/null || echo "")
    deployscript=$(ls -1 "$OS_SCRIPTS_DIR/os-deploy-${environment_type}.sh" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/os-deploy.sh" 2>/dev/null || echo "")
    if [[ -f "$deployscript" ]]
    then
      log_info "--- deploy script (\\e[33;1m${deployscript}\\e[0m) found: execute"
@@ -380,7 +392,7 @@ stages:
      log_info "--- no deploy script found: run template-based deployment"

      # find template
      templatefile=$(ls -1 "$OS_SCRIPTS_DIR/${OS_BASE_TEMPLATE_NAME}-${env}.yml" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/${OS_BASE_TEMPLATE_NAME}.yml" 2>/dev/null || echo "")
      templatefile=$(ls -1 "$OS_SCRIPTS_DIR/${OS_BASE_TEMPLATE_NAME}-${environment_type}.yml" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/${OS_BASE_TEMPLATE_NAME}.yml" 2>/dev/null || echo "")
      if [[ -z "$templatefile" ]]
      then
        log_error "--- no template"
@@ -397,8 +409,15 @@ stages:
    check_readiness

    # finally persist environment url
    echo "$CI_ENVIRONMENT_URL" > environment_url.txt
    echo -e "environment_type=$env\\nenvironment_name=$appname\\nenvironment_url=$CI_ENVIRONMENT_URL" > openshift.env
    if [[ -f environment_url.txt ]]
    then
      environment_url=$(cat environment_url.txt)
      export environment_url
      log_info "--- dynamic environment url found: (\\e[33;1m$environment_url\\e[0m)"
    else
      echo "$environment_url" > environment_url.txt
    fi
    echo -e "environment_type=$environment_type\\nenvironment_name=$environment_name\\nenvironment_url=$environment_url" > openshift.env
  }

  # $1 deployment name
@@ -463,21 +482,25 @@ stages:
  }

  function delete() {
    export env=$1
    # for backward compatibility
    export stage=$1
    export appname=$2
    # also export appname in SCREAMING_SNAKE_CASE format (may be useful with OpenShift env variables)
    appname_ssc=$(to_ssc "$2")
    export appname_ssc

    log_info "--- \\e[32mdelete\\e[0m (env: ${env})"
    log_info "--- appname: \\e[33;1m${appname}\\e[0m"
    log_info "--- appname_ssc: \\e[33;1m${appname_ssc}\\e[0m"
    log_info "--- env: \\e[33;1m${env}\\e[0m"
    export environment_type=$1
    export environment_name=$2
    # also export environment_name in SCREAMING_SNAKE_CASE format (may be useful with OpenShift env variables)
    environment_name_ssc=$(to_ssc "$2")
    export environment_name_ssc

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

    log_info "--- \\e[32mdelete"
    log_info "--- \$environment_type: \\e[33;1m${environment_type}\\e[0m"
    log_info "--- \$environment_name: \\e[33;1m${environment_name}\\e[0m"
    log_info "--- \$environment_name_ssc: \\e[33;1m${environment_name_ssc}\\e[0m"

    # maybe execute cleanup script
    cleanupscript=$(ls -1 "$OS_SCRIPTS_DIR/os-cleanup-${env}.sh" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/os-cleanup.sh" 2>/dev/null || echo "")
    cleanupscript=$(ls -1 "$OS_SCRIPTS_DIR/os-cleanup-${environment_type}.sh" 2>/dev/null || ls -1 "$OS_SCRIPTS_DIR/os-cleanup.sh" 2>/dev/null || echo "")
    if [[ -f "$cleanupscript" ]]
    then
      log_info "--- cleanup script (\\e[33;1m${cleanupscript}\\e[0m) found: execute"
@@ -499,8 +522,8 @@ stages:

      # delete app
      log_info "--- \\e[32moc delete\\e[0m"
      # delete all objects with label 'app=$appname'
      oc ${TRACE+--loglevel=6} delete "${OS_CLEANUP_OBJECT_TYPES}" --selector "${OS_APP_LABEL:-app}=$appname"
      # delete all objects with label 'app=$environment_name'
      oc ${TRACE+--loglevel=6} delete "${OS_CLEANUP_OBJECT_TYPES}" --selector "${OS_APP_LABEL:-app}=$environment_name"

      # maybe execute post cleanup script
      postscript="$OS_SCRIPTS_DIR/os-post-cleanup.sh"
@@ -516,23 +539,25 @@ stages:
  }

  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 services | remove 1st line | pick 7th column (selector) | filter services with label "app=$regex"
    matchingselectors=$(oc get svc -o wide | tail -n +2 | awk '{print $7}' | awk "/${OS_APP_LABEL:-app}=$appnameregex/ {print \$1}")
    matchingselectors=$(oc get svc -o wide | tail -n +2 | awk '{print $7}' | awk "/${OS_APP_LABEL:-app}=$environment_nameregex/ {print \$1}")
    matchcount=$(echo "$matchingselectors" | 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${matchcount}\\e[0m apps found"
    log_info "--- \\e[32mdelete all"
    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${matchcount}\\e[0m apps found)"

    rc=0
    for appselector in $matchingselectors
    do
      # extract review appname from selector (can be 'app=name,env=env,foo=bar')
      # extract review environment_name from selector (can be 'app=name,env=env,foo=bar')
      matchingapp=$(echo "$appselector" | sed -E "s/${OS_APP_LABEL:-app}=([^,]*).*/\\1/")
      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
@@ -583,7 +608,8 @@ stages:
# @arg ENV_TYPE      : environment type
# @arg ENV_APP_NAME  : env-specific application name
# @arg ENV_APP_SUFFIX: env-specific application suffix
# @arg ENV_URL       : env-specific OpenShift API url
# @arg ENV_URL       : env-specific deployment url (static)
# @arg ENV_API_URL   : env-specific OpenShift API url
# @arg ENV_TOKEN     : env-specific OpenShift API token
# @arg ENV_PROJECT   : env-specific OpenShift project name
.os-deploy:
@@ -594,18 +620,20 @@ stages:
  before_script:
    - *os-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - assert_defined "${ENV_URL:-$OS_URL}" 'Missing required OpenShift url'
    - assert_defined "${ENV_API_URL:-$OS_URL}" 'Missing required OpenShift url'
    - assert_defined "${ENV_TOKEN:-$OS_TOKEN}" 'Missing required OpenShift token'
    - assert_defined "$ENV_PROJECT" 'Missing required OpenShift project'
    - oc login ${ENV_URL:-$OS_URL} --token=${ENV_TOKEN:-$OS_TOKEN} -n $ENV_PROJECT
    - oc login ${ENV_API_URL:-$OS_URL} --token=${ENV_TOKEN:-$OS_TOKEN} -n $ENV_PROJECT
  script:
    - deploy "$ENV_TYPE" "${ENV_APP_NAME:-${OS_BASE_APP_NAME}${ENV_APP_SUFFIX}}"
    - deploy "$ENV_TYPE" "${ENV_APP_NAME:-${OS_BASE_APP_NAME}${ENV_APP_SUFFIX}}" "${ENV_URL:-${OS_ENVIRONMENT_URL:-$ENV_URL_LEGACY}}"
  artifacts:
    name: "$ENV_TYPE env url for $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    paths:
      - environment_url.txt
    reports:
      dotenv: openshift.env
  environment:
    url: "$environment_url" # can be either static or dynamic

# Cleanup job prototype
# Can be extended for each deletable environment
@@ -613,7 +641,7 @@ stages:
# @arg ENV_TYPE      : environment type
# @arg ENV_APP_NAME  : env-specific application name
# @arg ENV_APP_SUFFIX: env-specific application suffix
# @arg ENV_URL       : env-specific OpenShift API url
# @arg ENV_API_URL   : env-specific OpenShift API url
# @arg ENV_TOKEN     : env-specific OpenShift API token
# @arg ENV_PROJECT   : env-specific OpenShift project name
.os-cleanup:
@@ -626,10 +654,10 @@ stages:
  before_script:
    - *os-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - assert_defined "${ENV_URL:-$OS_URL}" 'Missing required OpenShift url'
    - assert_defined "${ENV_API_URL:-$OS_URL}" 'Missing required OpenShift url'
    - assert_defined "${ENV_TOKEN:-$OS_TOKEN}" 'Missing required OpenShift token'
    - assert_defined "$ENV_PROJECT" 'Missing required OpenShift project'
    - oc login ${ENV_URL:-$OS_URL} --token=${ENV_TOKEN:-$OS_TOKEN} -n $ENV_PROJECT
    - oc login ${ENV_API_URL:-$OS_URL} --token=${ENV_TOKEN:-$OS_TOKEN} -n $ENV_PROJECT
  script:
    - delete "$ENV_TYPE" "${ENV_APP_NAME:-${OS_BASE_APP_NAME}${ENV_APP_SUFFIX}}"
  environment:
@@ -644,12 +672,13 @@ os-review:
  variables:
    ENV_TYPE: review
    ENV_APP_NAME: "$OS_REVIEW_APP_NAME"
    ENV_URL: "$OS_REVIEW_URL"
    ENV_URL: "${OS_REVIEW_ENVIRONMENT_URL}"
    ENV_URL_LEGACY: "${OS_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${OS_REVIEW_ENVIRONMENT_DOMAIN}"
    ENV_API_URL: "$OS_REVIEW_URL"
    ENV_TOKEN: "$OS_REVIEW_TOKEN"
    ENV_PROJECT: "$OS_REVIEW_PROJECT"
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: "${OS_REVIEW_ENVIRONMENT_SCHEME}://${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG}.${OS_REVIEW_ENVIRONMENT_DOMAIN}"
    on_stop: os-cleanup-review
  resource_group: review/$CI_COMMIT_REF_NAME
  rules:
@@ -668,7 +697,7 @@ os-cleanup-review:
  variables:
    ENV_TYPE: review
    ENV_APP_NAME: "$OS_REVIEW_APP_NAME"
    ENV_URL: "$OS_REVIEW_URL"
    ENV_API_URL: "$OS_REVIEW_URL"
    ENV_TOKEN: "$OS_REVIEW_TOKEN"
    ENV_PROJECT: "$OS_REVIEW_PROJECT"
  environment:
@@ -721,12 +750,12 @@ os-integration:
  variables:
    ENV_TYPE: integration
    ENV_APP_NAME: "$OS_INTEG_APP_NAME"
    ENV_URL: "$OS_INTEG_URL"
    ENV_URL: "${OS_INTEG_ENVIRONMENT_URL}"
    ENV_API_URL: "$OS_INTEG_URL"
    ENV_TOKEN: "$OS_INTEG_TOKEN"
    ENV_PROJECT: "$OS_INTEG_PROJECT"
  environment:
    name: integration
    url: "${OS_INTEG_ENVIRONMENT_URL}"
  resource_group: integration
  rules:
    # only on integration branch(es), with $OS_INTEG_PROJECT set
@@ -743,12 +772,12 @@ os-staging:
  variables:
    ENV_TYPE: staging
    ENV_APP_NAME: "$OS_STAGING_APP_NAME"
    ENV_URL: "$OS_STAGING_URL"
    ENV_URL: "${OS_STAGING_ENVIRONMENT_URL}"
    ENV_API_URL: "$OS_STAGING_URL"
    ENV_TOKEN: "$OS_STAGING_TOKEN"
    ENV_PROJECT: "$OS_STAGING_PROJECT"
  environment:
    name: staging
    url: "${OS_STAGING_ENVIRONMENT_URL}"
  resource_group: staging
  rules:
    # only on production branch(es), with $OS_STAGING_PROJECT set
@@ -762,12 +791,12 @@ os-production:
    ENV_TYPE: production
    ENV_APP_SUFFIX: "" # no suffix for prod
    ENV_APP_NAME: "$OS_PROD_APP_NAME"
    ENV_URL: "$OS_PROD_URL"
    ENV_URL: "${OS_PROD_ENVIRONMENT_URL}"
    ENV_API_URL: "$OS_PROD_URL"
    ENV_TOKEN: "$OS_PROD_TOKEN"
    ENV_PROJECT: "$OS_PROD_PROJECT"
  environment:
    name: production
    url: "${OS_PROD_ENVIRONMENT_URL}"
  resource_group: production
  rules:
    # exclude non-production branches
+1 −1
Original line number Diff line number Diff line
@@ -3,4 +3,4 @@ SOURCE_REPOSITORY_URL The URL of the repository with your application source c
GITHUB_WEBHOOK_SECRET   A secret string used to configure the GitHub webhook          expression          [a-zA-Z0-9]{40}
REPLICA_COUNT           Number of replicas to run                                                         2
TLS_CERTIFICATE         TLS certificate to use by the server
appname                 the application target name to use in this environment (provided by GitLab CI template)
environment_name                 the application target name to use in this environment (provided by GitLab CI template)
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ parameters:
  - name: TLS_CERTIFICATE
    description: TLS certificate to use by the server
    required: true
  - name: appname
  - name: environment_name
    description: Application name (dynamically provided by the template)
    required: true
message: "... The GitHub webhook secret is ${GITHUB_WEBHOOK_SECRET} ..."
Loading