diff --git a/images/kubectl-build-deploy-dind/Dockerfile b/images/kubectl-build-deploy-dind/Dockerfile index 2acbaaa5dc..69451aa799 100644 --- a/images/kubectl-build-deploy-dind/Dockerfile +++ b/images/kubectl-build-deploy-dind/Dockerfile @@ -24,6 +24,9 @@ ENV DBAAS_OPERATOR_HTTP=dbaas.lagoon.svc:5000 RUN curl -sSL https://github.com/uselagoon/lagoon-linter/releases/download/v0.5.0/lagoon-linter_0.5.0_linux_amd64.tar.gz \ | tar -xz -C /usr/local/bin lagoon-linter +RUN curl -sSL https://github.com/uselagoon/build-deploy-tool/releases/download/v0.4.3/build-deploy-tool_0.4.3_linux_amd64.tar.gz \ + | tar -xz -C /usr/local/bin build-deploy-tool + RUN curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin > /dev/null 2>&1 #curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin > /dev/null 2>&1 diff --git a/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh b/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh index 909126f758..8f32479f77 100755 --- a/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh +++ b/images/kubectl-build-deploy-dind/build-deploy-docker-compose.sh @@ -981,11 +981,16 @@ do FASTLY_ARGS=() # if the feature is enabled, then do what is required to generated the labels/annotations etc if [ ! -z $LAGOON_FASTLY_AUTOGENERATED ] && [ "$LAGOON_FASTLY_AUTOGENERATED" == "enabled" ]; then + # work out if there are any lagoon api variable overrides for the annotations that are being added - . /kubectl-build-deploy/scripts/exec-fastly-annotations.sh - # if we get any other populated service id overrides in any of the steps in exec-fastly-annotations.sh + FASTLY_CONFIG=$(build-deploy-tool config fastly --ingress-domain "${ROUTE_DOMAIN}") + LAGOON_FASTLY_SERVICE_ID=$(echo ${FASTLY_CONFIG} | jq -r '."service-id" // ""') + LAGOON_FASTLY_SERVICE_WATCH=$(echo ${FASTLY_CONFIG} | jq -r '."watch" // false') + LAGOON_FASTLY_SERVICE_API_SECRET=$(echo ${FASTLY_CONFIG} | jq -r '."api-secret-name" // ""') + + # if we get any other populated service id overrides in any of the steps in lagoon-routegen # make it available to the ingress creation here by overriding what may be defined in the lagoon.yml - # `LAGOON_FASTLY_SERVICE_ID` is created in the exec-fastly-annotations.sh script + # `LAGOON_FASTLY_SERVICE_ID` is set by the lagoon-routegen script if [ ! -z "$LAGOON_FASTLY_SERVICE_ID" ]; then ROUTE_FASTLY_SERVICE_ID=$LAGOON_FASTLY_SERVICE_ID ROUTE_FASTLY_SERVICE_WATCH=$LAGOON_FASTLY_SERVICE_WATCH @@ -1062,8 +1067,9 @@ TEMPLATE_PARAMETERS=() ### CUSTOM ROUTES ############################################## -# Run the route generation script -. /kubectl-build-deploy/scripts/exec-routes-generation.sh +# Run the route generation process +build-deploy-tool template ingress +MAIN_CUSTOM_ROUTE=$(build-deploy-tool identify primary-ingress) set +x currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" diff --git a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/.helmignore b/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/.helmignore deleted file mode 100644 index 50af031725..0000000000 --- a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/.helmignore +++ /dev/null @@ -1,22 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/Chart.yaml b/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/Chart.yaml deleted file mode 100644 index d2a52f25b8..0000000000 --- a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/Chart.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v2 -name: custom-ingress -description: A Helm chart for Kubernetes creating custom-ingress - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -version: 0.1.0 \ No newline at end of file diff --git a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/_helpers.tpl b/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/_helpers.tpl deleted file mode 100644 index af8b1a79ac..0000000000 --- a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/_helpers.tpl +++ /dev/null @@ -1,69 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "custom-ingress.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "custom-ingress.fullname" -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "custom-ingress.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Common labels -*/}} -{{- define "custom-ingress.labels" -}} -helm.sh/chart: {{ include "custom-ingress.chart" . }} -{{ include "custom-ingress.selectorLabels" . }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{ include "custom-ingress.lagoonLabels" . }} - -{{- end -}} - -{{/* -Selector labels -*/}} -{{- define "custom-ingress.selectorLabels" -}} -app.kubernetes.io/name: {{ include "custom-ingress.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} - -{{/* -Lagoon Labels -*/}} -{{- define "custom-ingress.lagoonLabels" -}} -lagoon.sh/service: {{ .Release.Name }} -lagoon.sh/service-type: {{ .Chart.Name }} -lagoon.sh/project: {{ .Values.project }} -lagoon.sh/environment: {{ .Values.environment }} -lagoon.sh/environmentType: {{ .Values.environmentType }} -lagoon.sh/buildType: {{ .Values.buildType }} -{{- end -}} - -{{/* -Annotations -*/}} -{{- define "custom-ingress.annotations" -}} -lagoon.sh/version: {{ .Values.lagoonVersion | quote }} -{{- if .Values.branch }} -lagoon.sh/branch: {{ .Values.branch | quote }} -{{- end }} -{{- if .Values.prNumber }} -lagoon.sh/prNumber: {{ .Values.prNumber | quote }} -lagoon.sh/prHeadBranch: {{ .Values.prHeadBranch | quote }} -lagoon.sh/prBaseBranch: {{ .Values.prBaseBranch | quote }} -{{- end }} -{{- end -}} diff --git a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/ingress.yaml b/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/ingress.yaml deleted file mode 100644 index 808dcef27d..0000000000 --- a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/templates/ingress.yaml +++ /dev/null @@ -1,71 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -# data: -# hsts: {{ .Values.route_hsts }} -# hsts-max-age: {{ .Values.route_hsts }} -# ssl-redirect: true -metadata: - name: {{ include "custom-ingress.fullname" . }} - labels: - dioscuri.amazee.io/migrate: {{ .Values.routeMigrate | quote }} - lagoon.sh/autogenerated: "false" - {{- include "custom-ingress.labels" . | nindent 4 }} - annotations: - # force-ssl-redirect handling - {{- if eq .Values.insecure "Allow"}} - nginx.ingress.kubernetes.io/ssl-redirect: "false" - ingress.kubernetes.io/ssl-redirect: "false" - {{- else if eq .Values.insecure "Redirect"}} - nginx.ingress.kubernetes.io/ssl-redirect: "true" - ingress.kubernetes.io/ssl-redirect: "true" - {{- else if eq .Values.insecure "None"}} - nginx.ingress.kubernetes.io/ssl-redirect: "true" - ingress.kubernetes.io/ssl-redirect: "true" - {{- end }} - {{- if eq .Values.environmentType "development"}} - nginx.ingress.kubernetes.io/server-snippet: |- - add_header X-Robots-Tag "noindex, nofollow"; - {{- end }} - monitor.stakater.com/enabled: "{{ .Values.ingressmonitorcontroller.enabled }}" - uptimerobot.monitor.stakater.com/interval: "{{ .Values.ingressmonitorcontroller.interval }}" - uptimerobot.monitor.stakater.com/alert-contacts: "{{ .Values.ingressmonitorcontroller.alertContacts }}" - {{- if .Values.ingressmonitorcontroller.path }} - monitor.stakater.com/overridePath: "{{ .Values.ingressmonitorcontroller.path }}" - {{- end }} - {{- if .Values.ingressmonitorcontroller.statuspageId }} - uptimerobot.monitor.stakater.com/status-pages: "{{ .Values.ingressmonitorcontroller.statuspageId }}" - {{- end }} - # HSTS Handling - {{- if .Values.hsts}} - # haproxy.router.openshift.io/hsts_header: {{ .Values.route_hsts }} - {{- end }} - kubernetes.io/tls-acme: {{ .Values.tls_acme | quote }} - # use a specific fastly service - {{- if .Values.fastly.serviceId }} - fastly.amazee.io/service-id: "{{ .Values.fastly.serviceId }}" - {{- end }} - fastly.amazee.io/watch: "{{ .Values.fastly.watch }}" - # use a custom secret for this ingress (customer supplied fastly integration) - {{- if .Values.fastly.apiSecretName }} - fastly.amazee.io/api-secret-name: "{{ .Values.fastly.apiSecretName }}" - {{- end }} - {{- include "custom-ingress.annotations" . | nindent 4 }} - {{- with .Values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - tls: - - hosts: - - {{ .Values.host }} - secretName: {{ include "custom-ingress.fullname" . }}-tls - rules: - - host: {{ .Values.host }} - http: - paths: - - path: "/" - pathType: Prefix - backend: - service: - name: {{ .Values.service }} - port: - name: http diff --git a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/values.yaml b/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/values.yaml deleted file mode 100644 index ff22a39dce..0000000000 --- a/images/kubectl-build-deploy-dind/helmcharts/custom-ingress/values.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Default values for custom-ingress. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -host: '' -hsts: 'null' -tls_acme: true -insecure: Allow -service: '' -annotations: {} -routeMigrate: false - -ingressmonitorcontroller: - enabled: 'false' - interval: '60' - alertContacts: 'unconfigured' - -## example fastly block -fastly: - watch: false -# serviceId: '' -# apiSecretName: '' \ No newline at end of file diff --git a/images/kubectl-build-deploy-dind/scripts/exec-fastly-annotations.sh b/images/kubectl-build-deploy-dind/scripts/exec-fastly-annotations.sh deleted file mode 100755 index 39343d2c50..0000000000 --- a/images/kubectl-build-deploy-dind/scripts/exec-fastly-annotations.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# this script is used to work out the fastly annotation overrides that could be defined in the lagoon api - -# if no service id is provided in the `.lagoon.yml` which will be present in `ROUTE_FASTLY_SERVICE_ID` -if [ -z "$ROUTE_FASTLY_SERVICE_ID" ]; then - # then insert the one provided by lagoon in `LAGOON_FASTLY_NOCACHE_SERVICE_ID` if it is available - if [ ! -z "$LAGOON_FASTLY_NOCACHE_SERVICE_ID" ]; then - ROUTE_FASTLY_SERVICE_ID=$LAGOON_FASTLY_NOCACHE_SERVICE_ID - # if the nocache service id was injected by the lagoon builddeploy controller - # then set the watch status to true so it is set in the ingress annotations - # if the lagoon builddeploy controller has the fastly service injection disabled - # then the `LAGOON_FASTLY_NOCACHE_SERVICE_ID` will be empty - ROUTE_FASTLY_SERVICE_WATCH=true - fi -fi - -# check lagoon api variables for `LAGOON_FASTLY_SERVICE_ID` -# this is supported as `SERVICE_ID:WATCH_STATUS:SECRET_NAME(optional)` eg: "fa23rsdgsdgas:false", "fa23rsdgsdgas:true" or "fa23rsdgsdgas:true:examplecom" -# this will apply to ALL ingresses if one is not specifically defined in the `LAGOON_FASTLY_SERVICE_IDS` environment variable override -# see section `FASTLY SERVICE ID PER INGRESS OVERRIDE` in `build-deploy-docker-compose.sh` for info on `LAGOON_FASTLY_SERVICE_IDS` -if [ ! -z "$LAGOON_PROJECT_VARIABLES" ]; then - LAGOON_FASTLY_SERVICE_ID_DATA=($(echo $LAGOON_PROJECT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_FASTLY_SERVICE_ID") | "\(.value)"')) - echo $LAGOON_FASTLY_SERVICE_ID_DATA - if [ ! -z "$LAGOON_FASTLY_SERVICE_ID_DATA" ]; then - IFS=':' read -ra LAGOON_FASTLY_SERVICE_ID_SPLIT <<< "$LAGOON_FASTLY_SERVICE_ID_DATA" - if [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]}" ] || [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]}" ]; then - echo -e "An override was defined in the lagoon API with LAGOON_FASTLY_SERVICE_ID but one of the components was missing, the format should be FASTLY_SERVICE_ID:WATCH_STATUS" - exit 1 - fi - LAGOON_FASTLY_SERVICE_ID=${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]} - LAGOON_FASTLY_SERVICE_WATCH=${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]} - fi -fi -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - TEMP_LAGOON_FASTLY_SERVICE_ID_DATA=($(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_FASTLY_SERVICE_ID") | "\(.value)"')) - if [ ! -z $TEMP_LAGOON_FASTLY_SERVICE_ID_DATA ]; then - IFS=':' read -ra LAGOON_FASTLY_SERVICE_ID_SPLIT <<< "$TEMP_LAGOON_FASTLY_SERVICE_ID_DATA" - if [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]}" ] || [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]}" ]; then - echo -e "An override was defined in the lagoon API with LAGOON_FASTLY_SERVICE_ID but one of the components was missing, the format should be FASTLY_SERVICE_ID:WATCH_STATUS" - exit 1 - fi - LAGOON_FASTLY_SERVICE_ID=${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]} - LAGOON_FASTLY_SERVICE_WATCH=${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]} - # if the optional secret name is defined in the colon separated values configure that here - if [ ! -z ${LAGOON_FASTLY_SERVICE_ID_SPLIT[2]} ]; then - LAGOON_FASTLY_SERVICE_API_SECRET=${LAGOON_FASTLY_SERVICE_ID_SPLIT[2]} - fi - fi -fi - -# check the `LAGOON_FASTLY_SERVICE_IDS` to see if we have a domain specific override -# this is useful if all domains are using the nocache service, but you have a specific domain that should use a different service -# and you haven't defined it in the lagoon.yml file -# see section `FASTLY SERVICE ID PER INGRESS OVERRIDE` in `build-deploy-docker-compose.sh` for info on `LAGOON_FASTLY_SERVICE_IDS` -if [ ! -z "$LAGOON_FASTLY_SERVICE_IDS" ]; then - IFS=',' read -ra LAGOON_FASTLY_SERVICE_IDS_SPLIT <<< "$LAGOON_FASTLY_SERVICE_IDS" - for LAGOON_FASTLY_SERVICE_ID_DATA in "${LAGOON_FASTLY_SERVICE_IDS_SPLIT[@]}" - do - IFS=':' read -ra LAGOON_FASTLY_SERVICE_ID_SPLIT <<< "$LAGOON_FASTLY_SERVICE_ID_DATA" - if [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]}" ] || [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]}" ] || [ -z "${LAGOON_FASTLY_SERVICE_ID_SPLIT[2]}" ]; then - echo -e "An override was defined in the lagoon API with LAGOON_FASTLY_SERVICE_IDS but was not structured correctly, the format should be DOMAIN_NAME:FASTLY_SERVICE_ID:WATCH_STATUS and comma separated for multiples" - exit 1 - fi - if [ "${LAGOON_FASTLY_SERVICE_ID_SPLIT[0]}" == "$ROUTE_DOMAIN" ]; then - LAGOON_FASTLY_SERVICE_ID=${LAGOON_FASTLY_SERVICE_ID_SPLIT[1]} - LAGOON_FASTLY_SERVICE_WATCH=${LAGOON_FASTLY_SERVICE_ID_SPLIT[2]} - # if the optional secret name is defined in the colon separated values configure that here - if [ ! -z ${LAGOON_FASTLY_SERVICE_ID_SPLIT[3]} ]; then - LAGOON_FASTLY_SERVICE_API_SECRET=${LAGOON_FASTLY_SERVICE_ID_SPLIT[3]} - fi - fi - done -fi \ No newline at end of file diff --git a/images/kubectl-build-deploy-dind/scripts/exec-routes-generation.sh b/images/kubectl-build-deploy-dind/scripts/exec-routes-generation.sh deleted file mode 100644 index 8103897827..0000000000 --- a/images/kubectl-build-deploy-dind/scripts/exec-routes-generation.sh +++ /dev/null @@ -1,367 +0,0 @@ -#!/bin/bash - -set +x - -YQ=yq -LAGOONYML=.lagoon.yml - -############################################## -### New JSON format for routes that can be defined in an environment variable -############################################## -# cat << EOF > routes.json -# {"routes": [ -# { -# "domain": "example.com", -# "service": "nginx", -# "hsts": "max-age=31536000", -# "insecure": "Allow", -# "monitoring-path": "/", -# "fastly": { -# "service-id": "123456", -# "watch": true -# }, -# "annotations": { -# "nginx.ingress.kubernetes.io/permanent-redirect": "https://www.example.com$request_uri" -# } -# }, -# { -# "domain": "www.example.com", -# "service": "nginx", -# "hsts": "max-age=31536000", -# "insecure": "Allow", -# "monitoring-path": "/", -# "fastly": { -# "service-id": "123456", -# "watch": true -# } -# } -# ]} -# EOF -# -# When added this variable `LAGOON_ROUTES_JSON` to the specific environment (must be environment, not project), -# the value should be base64 encoded to preserve the formatting of the original JSON -# the best way to generate the base64 encoded version would be to use `jq` to compact the json and then base64 encode that -# -# eg, `cat routes.json | jq -c | base64` -# -# or by using the lagoon-cli, and given a JSON file with the routes in it -# lagoon add variable --project example-project \ -# --environment main \ -# --name LAGOON_ROUTES_JSON \ -# --value $(cat routes.json | jq -c | base64) \ -# --scope build` - -function containsElement () { - local e match="$1" - shift - for e - do - [[ "$(echo $e | base64 -d | jq -r '.domain')" == "$match" ]] && echo $e && return 0 - done - return 1 -} - -############################################## -### Function to convert existing route data from .lagoon.yml into newer -### JSON format used by the merging function and the route generator -############################################## -function routeDataCollection() { - YAMLPREFIX=${1} - ROUTES_SERVICE=${2} - ROUTES_SERVICE_COUNTER=${3} - ROUTE_DOMAIN_COUNTER=${4} - ACTIVE_STANDBY=${5} - if cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER &> /dev/null; then - ROUTE_DOMAIN=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER) - # Route Domains include dots, which need to be esacped via `\.` in order to use them within shyaml - ROUTE_DOMAIN_ESCAPED=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER | sed 's/\./\\./g') - ROUTE_TLS_ACME=$(set -o pipefail; cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.tls-acme true | tr '[:upper:]' '[:lower:]') - ROUTE_MIGRATE=$(set -o pipefail; cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.migrate ${ACTIVE_STANDBY} | tr '[:upper:]' '[:lower:]') - ROUTE_INSECURE=$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.insecure Redirect) - ROUTE_HSTS=$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.hsts null) - MONITORING_PATH=$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.monitoring-path "/") - ROUTE_ANNOTATIONS=$(${YQ} -o=json --prettyPrint eval <(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.annotations {})) - # get the fastly configuration values from ${LAGOONYML} - if cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.fastly &> /dev/null; then - ROUTE_FASTLY_SERVICE_ID=$(cat ${LAGOONYML} | shyaml ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.fastly.service-id "") - ROUTE_FASTLY_SERVICE_API_SECRET=$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.fastly.api-secret-name "") - ROUTE_FASTLY_SERVICE_WATCH=$(set -o pipefail; cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER.$ROUTE_DOMAIN_ESCAPED.fastly.watch false | tr '[:upper:]' '[:lower:]') - else - ROUTE_FASTLY_SERVICE_ID="" - ROUTE_FASTLY_SERVICE_API_SECRET="" - ROUTE_FASTLY_SERVICE_WATCH=false - fi - else - # Only a value given, assuming some defaults - ROUTE_DOMAIN=$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER) - ROUTE_TLS_ACME=true - ROUTE_MIGRATE=${ACTIVE_STANDBY} - ROUTE_INSECURE=Redirect - ROUTE_HSTS=null - MONITORING_PATH="/" - ROUTE_ANNOTATIONS="{}" - ROUTE_FASTLY_SERVICE_ID="" - ROUTE_FASTLY_SERVICE_API_SECRET="" - ROUTE_FASTLY_SERVICE_WATCH=false - fi - - FASTLY_JSON_FMT='{"service-id":"%s","api-secret-name":"%s","watch":%s}\n' - FASTLY_JSON=$(printf "$FASTLY_JSON_FMT" "$ROUTE_FASTLY_SERVICE_ID" "$ROUTE_FASTLY_SERVICE_API_SECRET" "$ROUTE_FASTLY_SERVICE_WATCH") - - ROUTE_JSON_FMT='{"domain":"%s","service":"%s","tls-acme":%s,"hsts":"%s", "insecure": "%s", "monitoring-path": "%s", "fastly": %s, "annotations": %s}\n' - ROUTE_JSON=$(printf "$ROUTE_JSON_FMT" "$ROUTE_DOMAIN" "$ROUTES_SERVICE" "$ROUTE_TLS_ACME" "$ROUTE_HSTS" "$ROUTE_INSECURE" "$MONITORING_PATH" "$FASTLY_JSON" "$ROUTE_ANNOTATIONS") - echo ${ROUTE_JSON} -} - - -############################################## -### Function that actually generates the templates for routes -### This is to use the new routes JSON to simplify route creation -############################################## -function generateRoutes() { - LAGOON_FINAL_ROUTES=${1} - ACTIVE_STANDBY=${2} - ROUTE_DATA=$(${YQ} eval <(echo ${LAGOON_FINAL_ROUTES})) - - MONITORING_ENABLED="false" - ROUTES_SERVICE_COUNTER=0 - while [ -n "$(echo "${ROUTE_DATA}" | shyaml keys routes.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; do - ROUTES_SERVICE=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.service) - ROUTE_DOMAIN=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.domain) - # Route Domains include dots, which need to be esacped via `\.` in order to use them within shyaml - ROUTE_DOMAIN_ESCAPED=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.domain | sed 's/\./\\./g') - ROUTE_TLS_ACME=$(set -o pipefail; echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.tls-acme true | tr '[:upper:]' '[:lower:]') - ROUTE_MIGRATE=$(set -o pipefail; echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.migrate ${ACTIVE_STANDBY} | tr '[:upper:]' '[:lower:]') - ROUTE_INSECURE=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.insecure Redirect) - ROUTE_HSTS=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.hsts null) - MONITORING_PATH=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.monitoring-path "/") - ROUTE_ANNOTATIONS=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.annotations {}) - # get the fastly configuration values from .lagoon.yml - if echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.fastly &> /dev/null; then - ROUTE_FASTLY_SERVICE_ID=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.fastly.service-id "") - ROUTE_FASTLY_SERVICE_API_SECRET=$(echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.fastly.api-secret-name "") - ROUTE_FASTLY_SERVICE_WATCH=$(set -o pipefail; echo "${ROUTE_DATA}" | shyaml get-value routes.$ROUTES_SERVICE_COUNTER.fastly.watch false | tr '[:upper:]' '[:lower:]') - else - ROUTE_FASTLY_SERVICE_ID="" - ROUTE_FASTLY_SERVICE_API_SECRET="" - ROUTE_FASTLY_SERVICE_WATCH=false - fi - - # work out if there are any lagoon api variable overrides for the annotations that are being added - . /kubectl-build-deploy/scripts/exec-fastly-annotations.sh - - # if we get any other populated service id overrides in any of the steps in exec-fastly-annotations.sh - # make it available to the ingress creation here by overriding what may be defined in the lagoon.yml - # `LAGOON_FASTLY_SERVICE_ID` is created in the exec-fastly-annotations.sh script - if [ ! -z "$LAGOON_FASTLY_SERVICE_ID" ]; then - ROUTE_FASTLY_SERVICE_ID=$LAGOON_FASTLY_SERVICE_ID - ROUTE_FASTLY_SERVICE_WATCH=$LAGOON_FASTLY_SERVICE_WATCH - if [ ! -z $LAGOON_FASTLY_SERVICE_API_SECRET ]; then - ROUTE_FASTLY_SERVICE_API_SECRET=$LAGOON_FASTLY_SERVICE_API_SECRET - fi - fi - - # Create the fastly values required - FASTLY_ARGS=() - if [ ! -z "$ROUTE_FASTLY_SERVICE_ID" ]; then - FASTLY_ARGS+=(--set fastly.serviceId=${ROUTE_FASTLY_SERVICE_ID}) - if [ ! -z "$ROUTE_FASTLY_SERVICE_API_SECRET" ]; then - if contains $FASTLY_API_SECRETS "${FASTLY_API_SECRET_PREFIX}${ROUTE_FASTLY_SERVICE_API_SECRET}"; then - FASTLY_ARGS+=(--set fastly.apiSecretName=${FASTLY_API_SECRET_PREFIX}${ROUTE_FASTLY_SERVICE_API_SECRET}) - else - echo "$ROUTE_FASTLY_SERVICE_API_SECRET requested, but not found in .lagoon.yml file"; exit 1; - fi - fi - ROUTE_FASTLY_SERVICE_WATCH=true - fi - - touch /kubectl-build-deploy/${ROUTE_DOMAIN}-values.yaml - ${YQ} eval '{"annotations": .}' <(echo "$ROUTE_ANNOTATIONS") > /kubectl-build-deploy/${ROUTE_DOMAIN}-values.yaml - - # ${ROUTE_DOMAIN} is used as a helm release name which be max 53 characters long. - # So we need some logic to make sure it's always max 53 characters - if [[ ${#ROUTE_DOMAIN} -gt 53 ]] ; then - # Trim the route domain to 47 characters, and add an 5 character hash of the domain at the end - # this gives a total of 53 characters - INGRESS_NAME="${ROUTE_DOMAIN:0:47}" - INGRESS_NAME="${INGRESS_NAME%%.*}-$(echo "${ROUTE_DOMAIN}" | md5sum | cut -f 1 -d " " | cut -c 1-5)" - else - INGRESS_NAME=${ROUTE_DOMAIN} - fi - - # The very first found route is set as MAIN_CUSTOM_ROUTE - if [ -z "${MAIN_CUSTOM_ROUTE+x}" ]; then - MAIN_CUSTOM_ROUTE=$INGRESS_NAME - - # if we are in production we enabled monitoring for the main custom route - if [ "${ENVIRONMENT_TYPE}" == "production" ]; then - MONITORING_ENABLED="true" - fi - - fi - - ROUTE_SERVICE=$ROUTES_SERVICE - - # Print the values for some reason? - cat /kubectl-build-deploy/${ROUTE_DOMAIN}-values.yaml - - helm template ${INGRESS_NAME} \ - /kubectl-build-deploy/helmcharts/custom-ingress \ - --set host="${ROUTE_DOMAIN}" \ - --set service="${ROUTE_SERVICE}" \ - --set tls_acme="${ROUTE_TLS_ACME}" \ - --set insecure="${ROUTE_INSECURE}" \ - --set hsts="${ROUTE_HSTS}" \ - --set routeMigrate="${ROUTE_MIGRATE}" \ - --set ingressmonitorcontroller.enabled="${MONITORING_ENABLED}" \ - --set ingressmonitorcontroller.path="${MONITORING_PATH}" \ - --set ingressmonitorcontroller.alertContacts="${MONITORING_ALERTCONTACT}" \ - --set ingressmonitorcontroller.statuspageId="${MONITORING_STATUSPAGEID}" \ - "${FASTLY_ARGS[@]}" --set fastly.watch="${ROUTE_FASTLY_SERVICE_WATCH}" \ - -f /kubectl-build-deploy/values.yaml -f /kubectl-build-deploy/${ROUTE_DOMAIN}-values.yaml "${HELM_ARGUMENTS[@]}" > $YAML_FOLDER/${ROUTE_DOMAIN}.yaml - - MONITORING_ENABLED="false" # disabling a possible enabled monitoring again - - let ROUTES_SERVICE_COUNTER=ROUTES_SERVICE_COUNTER+1 - done -} - -############################################## -### Calculate any active/standby routes -############################################## -# we need to check for production routes for active/standby if they are defined, as these will get migrated between environments as required -if [ "${ENVIRONMENT_TYPE}" == "production" ]; then - PRODUCTION_ROUTES_JSON_FMT='{"routes": []}' - ROUTES_SERVICE_COUNTER=0 - if [ "${BRANCH//./\\.}" == "${ACTIVE_ENVIRONMENT}" ]; then - YMLPREFIX="production_routes.active.routes" - if [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; then - while [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; do - ROUTES_SERVICE=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER) - ROUTE_DOMAIN_COUNTER=0 - while [ -n "$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER 2> /dev/null)" ]; do - LAGOON_ROUTE_JSON=$(routeDataCollection "${YAMLPREFIX}" "${ROUTES_SERVICE}" "${ROUTES_SERVICE_COUNTER}" "${ROUTE_DOMAIN_COUNTER}" true) - PRODUCTION_ROUTES_JSON_FMT=$(echo $PRODUCTION_ROUTES_JSON_FMT | jq -r --argjson LAGOON_ROUTE_JSON "$LAGOON_ROUTE_JSON" '.routes |= . + [$LAGOON_ROUTE_JSON]') - let ROUTE_DOMAIN_COUNTER=ROUTE_DOMAIN_COUNTER+1 - done - let ROUTES_SERVICE_COUNTER=ROUTES_SERVICE_COUNTER+1 - done - fi - fi - if [ "${BRANCH//./\\.}" == "${STANDBY_ENVIRONMENT}" ]; then - YMLPREFIX="production_routes.standby.routes" - if [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; then - while [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; do - ROUTES_SERVICE=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER) - ROUTE_DOMAIN_COUNTER=0 - while [ -n "$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER 2> /dev/null)" ]; do - LAGOON_ROUTE_JSON=$(routeDataCollection "${YAMLPREFIX}" "${ROUTES_SERVICE}" "${ROUTES_SERVICE_COUNTER}" "${ROUTE_DOMAIN_COUNTER}" true) - PRODUCTION_ROUTES_JSON_FMT=$(echo $PRODUCTION_ROUTES_JSON_FMT | jq -r --argjson LAGOON_ROUTE_JSON "$LAGOON_ROUTE_JSON" '.routes |= . + [$LAGOON_ROUTE_JSON]') - let ROUTE_DOMAIN_COUNTER=ROUTE_DOMAIN_COUNTER+1 - done - let ROUTES_SERVICE_COUNTER=ROUTES_SERVICE_COUNTER+1 - done - fi - fi - if [ "${ROUTES_SERVICE_COUNTER}" != "0" ]; then - ### Run the generation function to create all the kubernetes resources etc - ### Merging of active/standby routes with environment variabled defined routes is not currently supported - echo "Generating the production_routes templates" - generateRoutes "$(echo "${PRODUCTION_ROUTES_JSON_FMT}" | jq -r)" true - fi -fi - -############################################## -### Calculate any standard routes from the `.lagoon.yml` -############################################## -ROUTES_JSON_FMT='{"routes": []}' - -ROUTES_SERVICE_COUNTER=0 -YMLPREFIX="${PROJECT}.environments.${BRANCH//./\\.}.routes" -if [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; then - while [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; do - ROUTES_SERVICE=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER) - ROUTE_DOMAIN_COUNTER=0 - while [ -n "$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER 2> /dev/null)" ]; do - LAGOON_ROUTE_JSON=$(routeDataCollection "${YAMLPREFIX}" "${ROUTES_SERVICE}" "${ROUTES_SERVICE_COUNTER}" "${ROUTE_DOMAIN_COUNTER}" false) - ROUTES_JSON_FMT=$(echo $ROUTES_JSON_FMT | jq -r --argjson LAGOON_ROUTE_JSON "$LAGOON_ROUTE_JSON" '.routes |= . + [$LAGOON_ROUTE_JSON]') - let ROUTE_DOMAIN_COUNTER=ROUTE_DOMAIN_COUNTER+1 - done - let ROUTES_SERVICE_COUNTER=ROUTES_SERVICE_COUNTER+1 - done -else - YMLPREFIX="environments.${BRANCH//./\\.}.routes" - while [ -n "$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER 2> /dev/null)" ]; do - ROUTES_SERVICE=$(cat ${LAGOONYML} | shyaml keys ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER) - ROUTE_DOMAIN_COUNTER=0 - while [ -n "$(cat ${LAGOONYML} | shyaml get-value ${YMLPREFIX}.$ROUTES_SERVICE_COUNTER.$ROUTES_SERVICE.$ROUTE_DOMAIN_COUNTER 2> /dev/null)" ]; do - LAGOON_ROUTE_JSON=$(routeDataCollection "${YAMLPREFIX}" "${ROUTES_SERVICE}" "${ROUTES_SERVICE_COUNTER}" "${ROUTE_DOMAIN_COUNTER}" false) - ROUTES_JSON_FMT=$(echo $ROUTES_JSON_FMT | jq -r --argjson LAGOON_ROUTE_JSON "$LAGOON_ROUTE_JSON" '.routes |= . + [$LAGOON_ROUTE_JSON]') - let ROUTE_DOMAIN_COUNTER=ROUTE_DOMAIN_COUNTER+1 - done - let ROUTES_SERVICE_COUNTER=ROUTES_SERVICE_COUNTER+1 - done -fi - -############################################## -### Merge any routes that have been defined in the API/EnvVar -### over the top of what is in the `.lagoon.yml` file -############################################## -FINAL_ROUTES_JSON='{"routes": []}' -# these are routes from the .lagoon.yml file -LAGOON_YML_ROUTES=($(echo "${ROUTES_JSON_FMT}" | jq -r '.routes | .[] | @base64')) - -# these are routes that are in the api as "environment" environment variables (not project) -if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then - LAGOON_ROUTES_JSON=$(echo $LAGOON_ENVIRONMENT_VARIABLES | jq -r '.[] | select(.name == "LAGOON_ROUTES_JSON") | "\(.value)"' | base64 -d) -fi - -MERGE_ROUTES_ARR=($(echo "${LAGOON_ROUTES_JSON}" | jq -r '.routes | .[] | @base64')) - -# check if any of the routes in the merge routes array exist in the existing routes -# if they don't, then add them to the new routes format so that the ingress is created -for MERGE_ROUTE in "${MERGE_ROUTES_ARR[@]}"; do - _jq() { - echo ${MERGE_ROUTE} | base64 -d | jq -r ${1} - } - if ! containsElement "$(_jq '.domain')" "${LAGOON_YML_ROUTES[@]}" > /dev/null; then - # add the domain to the new routes format - echo "Adding route $(_jq '.domain') from LAGOON_ROUTES_JSON to processing list" - FINAL_ROUTES_JSON=$(echo $FINAL_ROUTES_JSON | jq -r --argjson LAGOON_ROUTE_JSON "$(echo $(_jq))" '.routes |= . + [$LAGOON_ROUTE_JSON]') - fi -done - -# now check if the routes contain any of the ones to merge -# if they do, then merge whats in the merging json over the top of the existing json -for YAML_ROUTE in "${LAGOON_YML_ROUTES[@]}"; do - _jq() { - echo ${YAML_ROUTE} | base64 -d | jq -r ${1} - } - if containsElement "$(_jq '.domain')" "${MERGE_ROUTES_ARR[@]}" > /dev/null; then - # merge the domain over the existing one - echo "Merging route $(_jq '.domain') from LAGOON_ROUTES_JSON on top of the '.lagoon.yml', adding to processing list" - MERGED_JSON=$(jq -s '.[0] * .[1]' <(_jq) <(containsElement "$(_jq '.domain')" "${MERGE_ROUTES_ARR[@]}" | base64 -d | jq -r)) - FINAL_ROUTES_JSON=$(echo $FINAL_ROUTES_JSON | jq -r --argjson LAGOON_ROUTE_JSON "$(echo ${MERGED_JSON})" '.routes |= . + [$LAGOON_ROUTE_JSON]') - fi - if ! containsElement "$(_jq '.domain')" "${MERGE_ROUTES_ARR[@]}" > /dev/null; then - # add the domain to the new routes format - echo "Adding route $(_jq '.domain') from '.lagoon.yml' to processing list" - FINAL_ROUTES_JSON=$(echo $FINAL_ROUTES_JSON | jq -r --argjson LAGOON_ROUTE_JSON "$(echo $(_jq))" '.routes |= . + [$LAGOON_ROUTE_JSON]') - fi -done - -### Add the merged or to be created routes into a configmap -echo "${FINAL_ROUTES_JSON}" | jq -r > /kubectl-build-deploy/routes.json -echo "Updating lagoon-routes configmap with the newly generated routes JSON" -if kubectl -n ${NAMESPACE} get configmap lagoon-routes &> /dev/null; then - # if the key does exist, then nuke it and put the new key - kubectl -n ${NAMESPACE} create configmap lagoon-routes --from-file=lagoon-routes=/kubectl-build-deploy/routes.json -o yaml --dry-run=client | kubectl replace -f - -else - # create it - kubectl -n ${NAMESPACE} create configmap lagoon-routes --from-file=lagoon-routes=/kubectl-build-deploy/routes.json -fi - -### Run the generation function to create all the kubernetes resources etc -echo "Generating the routes templates" -generateRoutes "$(cat /kubectl-build-deploy/routes.json | jq -r)" false -set -x