Skip to content
Snippets Groups Projects
deploy_component.sh 8.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/bin/bash
    # Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    
    ########################################################################################################################
    # Read deployment settings
    ########################################################################################################################
    
    # If not already set, set the URL of your local Docker registry where the images will be uploaded to.
    # Leave it blank if you do not want to use any Docker registry.
    export TFS_REGISTRY_IMAGE=${TFS_REGISTRY_IMAGE:-""}
    #export TFS_REGISTRY_IMAGE="http://my-container-registry.local/"
    
    TFS_COMPONENTS=$1
    
    # If not already set, set the tag you want to use for your images.
    export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"}
    
    # If not already set, set the name of the Kubernetes namespace to deploy to.
    export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"}
    
    # If not already set, set additional manifest files to be applied after the deployment
    export TFS_EXTRA_MANIFESTS=${TFS_EXTRA_MANIFESTS:-""}
    
    # If not already set, set the neew Grafana admin password
    export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"}
    
    ########################################################################################################################
    # Automated steps start here
    ########################################################################################################################
    
    # Constants
    GITLAB_REPO_URL="registry.gitlab.com/teraflow-h2020/controller"
    TMP_FOLDER="./tmp"
    
    # Create a tmp folder for files modified during the deployment
    TMP_MANIFESTS_FOLDER="$TMP_FOLDER/manifests"
    TMP_LOGS_FOLDER="$TMP_FOLDER/logs"
    
    echo "Deploying component and collecting environment variables..."
    ENV_VARS_SCRIPT=tfs_runtime_env_vars.sh
    
    for COMPONENT in $TFS_COMPONENTS; do
        echo "Processing '$COMPONENT' component..."
        IMAGE_NAME="$COMPONENT:$TFS_IMAGE_TAG"
        IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGE/$IMAGE_NAME" | sed 's,//,/,g' | sed 's,http:/,,g')
    
        echo "  Building Docker image..."
        BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log"
    
        if [ "$COMPONENT" == "automation" ] || [ "$COMPONENT" == "policy" ]; then
            docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG"
    
            BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-frontend.log"
            docker build -t "$COMPONENT-frontend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/frontend/Dockerfile . >> "$BUILD_LOG"
    
            BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-backend.log"
            docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG"
            # next command is redundant, but helpful to keep cache updated between rebuilds
            docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG-builder" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG"
        else
            docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG"
        fi
    
        if [ -n "$TFS_REGISTRY_IMAGE" ]; then
            echo "  Pushing Docker image to '$TFS_REGISTRY_IMAGE'..."
    
            if [ "$COMPONENT" == "pathcomp" ]; then
                TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-frontend.log"
                docker tag "$COMPONENT-frontend:$TFS_IMAGE_TAG" "$IMAGE_URL-frontend" > "$TAG_LOG"
    
                TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-backend.log"
                docker tag "$COMPONENT-backend:$TFS_IMAGE_TAG" "$IMAGE_URL-backend" > "$TAG_LOG"
    
                PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-frontend.log"
                docker push "$IMAGE_URL-frontend" > "$PUSH_LOG"
    
                PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-backend.log"
                docker push "$IMAGE_URL-backend" > "$PUSH_LOG"
            else
                TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}.log"
                docker tag "$IMAGE_NAME" "$IMAGE_URL" > "$TAG_LOG"
    
                PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}.log"
                docker push "$IMAGE_URL" > "$PUSH_LOG"
            fi
        fi
    
        echo "  Adapting '$COMPONENT' manifest file..."
        MANIFEST="$TMP_MANIFESTS_FOLDER/${COMPONENT}service.yaml"
        cp ./manifests/"${COMPONENT}"service.yaml "$MANIFEST"
    
        if [ -n "$TFS_REGISTRY_IMAGE" ]; then
            # Registry is set
            if [ "$COMPONENT" == "pathcomp" ]; then
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-frontend:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-frontend:${VERSION}#image: $IMAGE_URL-frontend#g" "$MANIFEST"
    
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-backend:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-backend:${VERSION}#image: $IMAGE_URL-backend#g" "$MANIFEST"
    
                sed -E -i "s#imagePullPolicy: .*#imagePullPolicy: Always#g" "$MANIFEST"
            else
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST"
                sed -E -i "s#imagePullPolicy: .*#imagePullPolicy: Always#g" "$MANIFEST"
            fi
        else
            # Registry is not set
            if [ "$COMPONENT" == "pathcomp" ]; then
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-frontend:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-frontend:${VERSION}#image: $IMAGE_NAME-frontend#g" "$MANIFEST"
    
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-backend:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-backend:${VERSION}#image: $IMAGE_NAME-backend#g" "$MANIFEST"
    
                sed -E -i "s#imagePullPolicy: .*#imagePullPolicy: Never#g" "$MANIFEST"
            else
                VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f3)
                sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT:${VERSION}#image: $IMAGE_NAME#g" "$MANIFEST"
                sed -E -i "s#imagePullPolicy: .*#imagePullPolicy: Never#g" "$MANIFEST"
            fi
        fi
    
        # TODO: harmonize names of the monitoring component
    
        echo "  Deploying '$COMPONENT' component to Kubernetes..."
        DEPLOY_LOG="$TMP_LOGS_FOLDER/deploy_${COMPONENT}.log"
        kubectl --namespace $TFS_K8S_NAMESPACE delete -f "$MANIFEST" > "$DEPLOY_LOG"
        kubectl --namespace $TFS_K8S_NAMESPACE apply -f "$MANIFEST" > "$DEPLOY_LOG"
        COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/")
        kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=0 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG"
        kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=1 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG"
    
        echo "  Collecting env-vars for '$COMPONENT' component..."
    
        SERVICE_DATA=$(kubectl get service ${COMPONENT}service --namespace $TFS_K8S_NAMESPACE -o json)
        if [ -z "${SERVICE_DATA}" ]; then continue; fi
    
        # Env vars for service's host address
        SERVICE_HOST=$(echo ${SERVICE_DATA} | jq -r '.spec.clusterIP')
        if [ -z "${SERVICE_HOST}" ]; then continue; fi
        # TODO: remove previous value from file
        ENVVAR_HOST=$(echo "${COMPONENT}service_SERVICE_HOST" | tr '[:lower:]' '[:upper:]')
        echo "export ${ENVVAR_HOST}=${SERVICE_HOST}" >> $ENV_VARS_SCRIPT
    
        # Env vars for service's 'grpc' port (if any)
        SERVICE_PORT_GRPC=$(echo ${SERVICE_DATA} | jq -r '.spec.ports[] | select(.name=="grpc") | .port')
        if [ -n "${SERVICE_PORT_GRPC}" ]; then
            ENVVAR_PORT_GRPC=$(echo "${COMPONENT}service_SERVICE_PORT_GRPC" | tr '[:lower:]' '[:upper:]')
            echo "export ${ENVVAR_PORT_GRPC}=${SERVICE_PORT_GRPC}" >> $ENV_VARS_SCRIPT
        fi
    
        # Env vars for service's 'http' port (if any)
        SERVICE_PORT_HTTP=$(echo ${SERVICE_DATA} | jq -r '.spec.ports[] | select(.name=="http") | .port')
        if [ -n "${SERVICE_PORT_HTTP}" ]; then
            ENVVAR_PORT_HTTP=$(echo "${COMPONENT}service_SERVICE_PORT_HTTP" | tr '[:lower:]' '[:upper:]')
            echo "export ${ENVVAR_PORT_HTTP}=${SERVICE_PORT_HTTP}" >> $ENV_VARS_SCRIPT
        fi
    
        printf "\n"
    done
    
    # By now, leave this control here. Some component dependencies are not well handled
    for COMPONENT in $TFS_COMPONENTS; do
        echo "Waiting for '$COMPONENT' component..."
        kubectl wait --namespace $TFS_K8S_NAMESPACE \
    
        --for='condition=available' --timeout=3s deployment/${COMPONENT}service