#!/bin/bash

update_resources::label() {
  echo "Update resources"
}

update_resources::doc() {
  cat <<EOT
This command first will call out to migraton scripts for updating stateful resources (ConfigMap, Secrets, PersistentVolumeClaims).

This part is similar to the DB migration, except that upgrade shell scripts are used for each version:

.Example dynamic upgrade

```
/migration/resource/
    10-update-serverconfig.sh
    20-update-uiconfig.sh
      ...
```

These update scripts will be always executed during the upgrade process.
Hence, they need to be idempotent as if they detect that they already performed their update then they should be a no-op.
In general, these upgrades scripts are used to add default values for new features (if not present) or change defaults.

Within the scripts you are free to do what you want to do, but typically this will be tweaking of some scripts

NOTE: No resources from generated integration pods are upgraded. This needs to be done as part of the <<upgrade-integration,Integration Upgrade>> process.

After this, the upgrade of the new version with an `oc replace` for all other resource objects extracted <<step-create-upgrade-json, previously>>.
This command will automatically spin up new versions (or the same if unchanged in this release) for all deployments.


.Rollback
Restore all the resource objects backuped in a previous step
EOT
}

# All resources which should be update by force (delete/create) because
# an in-place update is not possible
# * Service and Route can't be replaced because there are immutable datat in the spec (like clusterip)
# * ServiceAccounts are force replaced so that hopefully the associated secrets are cleaned up, too.
FORCE_UPGRADE_RESOURCES="Service Route ServiceAccount"

# Document which resource shouldn't be updated
DONT_TOUCH_RESOURCES="ConfigMap Secret PersistentVolumeClaim RoleBinding"

update_resources::run() {
    local backupdir=$1
    local workdir=$2
    local tag=$3
    local migrationdir=$4

    run_update_scripts "$backupdir" "$workdir" "$tag" "$migrationdir"
    apply_resources "$workdir/resources" "$DONT_TOUCH_RESOURCES"
    link_pull_secret
}

update_resources::rollback() {
    local backupdir=${1}
    local workdir=${2}
    local cleanup=${3:-}

    apply_resources "$backupdir/resources" "Template"
}

# =========================================================================================

apply_resources() {
    local resource_dir=${1}
    local skip_resources=${2:-}

    for kind in $(ls $resource_dir); do
      echo -n "      - $kind: "
      if [ -n "${skip_resources}" ] && [ -z "${skip_resources/*${kind}*/}" ]; then
          echo "skipped"
      else
          local extra_opt=""
          if [ -z "${FORCE_UPGRADE_RESOURCES/*${kind}*/}" ]; then
            echo "force update (delete/create)"
            extra_opt="--force"
          else
            echo "update (replace)"
          fi
          for resource in $(ls $resource_dir/$kind); do
              local name=$(basename $resource .json)
              echo "        * $name"
              local result
              local rc
              set +e
              local resource_temp=$(mktemp)
              cat "$resource_dir/$kind/$resource" | \
                 jq '.metadata |= del(.resourceVersion)' | \
                 jq '.metadata.annotations |= del(."service.alpha.openshift.io/serving-cert-signed-by")' \
                 > $resource_temp
              if [ "$kind" = "DeploymentConfig" ]; then
                  # Set replicas to 0 for DCs to avoid redeployment when patching the resource
                  local temp_dc=$(mktemp)
                  cat $resource_temp | jq -M '.spec.replicas |= 0' > $temp_dc
                  mv $temp_dc $resource_temp
              fi
              result=$(oc replace $extra_opt -f "$resource_temp" 2>&1)
              rc=$?
              set -e
              if [ $rc -gt 0 ]; then
                if [ -z "${result/*not found*/}" ]; then
                    echo "          not existing --> trying to create"
                    oc create -f "$resource_temp"
                    rm $resource_temp
                else
                    echo "$result"
                    rm $resource_temp
                    exit 1
                fi
              fi
          done
      fi
    done
}

link_pull_secret() {
  if oc get secret syndesis-pull-secret -o name >/dev/null 2>&1; then
    # Add pull secrets to every service account specific to syndesis
    for sa in $(oc get sa -o jsonpath='{.items[*].metadata.name}'); do
      # For all sa's which start with "syndesis-" + the camel k operator
      if [ ${sa/#syndesis-/} != $sa ]; then
        echo "       ### Linking syndesis-pull-secret --> SA $sa (pull)"
        oc secrets link $sa syndesis-pull-secret --for=pull
      fi
    done

    # Add pull and push secrets to the builder account
    echo "       ### Linking syndesis-pull-secret --> SA builder (pull + mount)"
    oc secrets link builder syndesis-pull-secret --for=pull,mount
  fi
}

# Just as reference, not currently used
remove_rcs_for_dc() {
    local dc=${1}
    for rc in $(oc get rc -l openshift.io/deployment-config.name=$dc -o name); do
        oc delete $rc
    done
}

run_update_scripts() {
    local backupdir=$1
    local workdir=$2
    local tag=$3
    local migrationdir=$4

    # Only when --migration is given we will check for migration scripts
    if [ -z "${migrationdir}" ]; then
        return
    fi

    local resourcedir=${migrationdir}/resource

    for script in $(ls ${resourcedir}/*.sh); do
        echo "      - Executing $(basename $script)"
        source ${script}
    done
}
