#!/bin/bash
# ------------------------------------- USAGE ----------
function USAGE {
cat<<ENDUSAGE
 USAGE: image-service <COMMAND> [module_dir]
        image-service build [(-n|--no-cache)] [(-v|--version)=ver] (-i|--image)=(image_dir|all) [(-q|--quiet)]
        image-service push (-i|--image)=image_dir
        image-service commit (-i|--image)=module_dir [(-m|--message)=message]
        image-service build-product (-v|--version)=ver [(-n|--no-cache)]
        image-service (import|export) (-v|--version)=ver
        image-service [os-stat|os-list]
        image-service os-set <cluster_name>

  Environment handling:
    env-stat     - status on current cluster/environment
    env-list     - list configured/registered clusters/environments
    env-set      - set current working cluster/environment

  Staging area (source code) maintenance:
    list        - list registered modules
    checkout    - prepare staging area in svn stage from where this script runs
    clean       - cleanup staging area (removes all sources!)
    update, u   - perform 'svn update' on sources
    status      - perform 'svn status' on sources
    commit      - perform 'svn ci' on sources
    set-branch  - change current SVN branch

  Build/publishing support:
    b, build    - build staging area into images
    p, push     - push images into cluster
    bp          - build/push and remove
    ubp         - update/build/push and remove
    tag-minor   - update work area and create a new "minor version tag" on the latest repository state
    tag-major   - update work area and create a new "minor version tag" on the latest repository state

  Operations for remote deployment support:
    build-product       - build all MISSING images for the versioned product (must provide -v), use --no-cache to build ALL
    copy-definitions    - copy register-k8s/cleanup-k8s versioned(!) files into the project staging area (must provide -v)
    product-status      - check presence of tagged images for the versioned product (must provide -v)
    export-product      - export service images from local Docker Image Registry into tar at stage/overcast-v.e.r-yyyymmdd-hhmm.tar
    push-latest-release - (dev) tag release images as latest and push to current registry

ENDUSAGE
}

SCRIPTDIR=$(dirname $0)
DEBUG=0

# Workaround for initial 'env-set'
if [ ! -f "$HOME/.overcast" -a "$1" == "env-set" ]; then
    echo $2 > "$HOME/.overcast"
fi

# Workaround for initial setup on clean system
if [ "$1" == "init" ]; then
    for arg in "$@"; do
        case $arg in
            --dev)
                export OVERCAST_ENV=dev
                ;;
            --prod)
                export OVERCAST_ENV=prod
                ;;
            -q|--quiet)
                export QUIET=1
                ;;
            --env=*)
                export CLUSTER_ENV="${arg#*=}"
                ;;
            --branch=*)
                export SVN_BRANCH="${arg#*=}"
                ;;
        esac
    done
    [ -z "$OVERCAST_ENV" ] && die 123 "--dev or --prod should be specified"
    [ -z "$CLUSTER_ENV" ] && die 124 "cluster env should be specified"
    [ -z "$SVN_BRANCH" -a "$OVERCAST_ENV" == "dev" ] && die 125 "branch should be specified for DEV environment"

    if [ "$OVERCAST_ENV" == "dev" ]; then
        rm -f "$HOME/.overcast-prod"
        echo dev > "$HOME/.overcast-dev"
    else
        rm -f "$HOME/.overcast-dev"
        echo prod > "$HOME/.overcast-prod"
        mkdir -p "$HOME/docker"
    fi

    . $SCRIPTDIR/_environment
    . $SCRIPTDIR/_functions

    # Set branch on DEV env only
    [ "$OVERCAST_ENV" == "dev" ] && set-branch $SVN_BRANCH

    export SELECTED_MODULE_DIR=$CLUSTER_ENV
    set-env

    exit 0
fi

. $SCRIPTDIR/_environment
. $SCRIPTDIR/_functions

# ----------------------------------- push-image ----------
function push-image {
    if [ ! -f Makefile ] ; then
        echo SKIPPING $imagedir as Makefile is not present...
        return
    fi
    export IMAGE=`grep ^IMAGE_NAME Makefile 2>/dev/null | cut -f2 -d= | tr -d ' '`   # ex.: overcast/ptz
    [ -n  "$VERSION" ] && export IVER=":$VERSION" || export IVER=":latest"
    export SHORTNAME=${IMAGE##*/} # ex.: ptz

    if [[ $SHORTNAME =~ ^vae- ]]; then
        docker login -u $VAE_REGISTRY_USERNAME -p $VAE_REGISTRY_PASSWORD $VAE_REGISTRY_HOST
        [ $? != 0 ] && die 15 "Login to VAE registry failed"
        docker tag $IMAGE$IVER $VAE_REGISTRY_HOST/overcast/$SHORTNAME$IVER
        docker push $VAE_REGISTRY_HOST/overcast/$SHORTNAME$IVER
        docker logout $VAE_REGISTRY_HOST
    else
        $BASE_DIR/deploy/iaas/${CLUSTER_IAAS}/docker-push
    fi
}

# ----------------------------------------------------- repo-exec --------
function repo-exec {
    local OPERATION=$1 && shift
    local ver=$VERSION
    [ -z "$ver" ] && ver=latest

    if [ "$OPERATION" == "update" ]; then
        if [ "$ver" != "latest" ]; then
            if (( QUIET == 0 )); then
                echo Specifying version will perform CLEANUP on source code directories and module directory!
                echo Press Enter to proceed and Ctrl-C to abort operation.
                read
            fi

            [ -n "$(git status -s | sed '/^\s*$/d')" ] && die 20 "ABORTED: local changes in $(pwd) found"

            git pull origin
            git checkout --force "v$ver" &>/dev/null || die 789 "Cannot checkout tag $ver"
        else
            # Check if we are in 'detached HEAD' state - tag was selected
            LC_ALL=en git branch --no-color | grep '*' | grep detached &>/dev/null
            if [ $? == 0 ]; then
                echo Switching to 'dev' branch
                git checkout dev
            fi
            
            git pull origin
        fi
        
        # Update dependencies
        if [ -f .gitman.yml -o -f gitman.yml ]; then
            if [ "$ver" != "latest" ]; then
                gitman install
            else
                gitman update
            fi
        fi
    fi
    return
}

# ------------------------------------- make-builder-docker-scripts --------
function make-builder-docker-scripts {
    echo \
        docker run -it --rm \
        -v $(pwd)/app-files:/build/app-files:ro \
        -v $(pwd)/src:/build/src:ro \
        -v $(pwd)/compiled:/build/compiled \
        $BUILDER bash > scripts/run-builder
    echo \
        docker run -it --rm \
        ${IMAGE} bash > scripts/run-container
}

# --------------------------------------------------- build-sources --------
function build-sources {
    [ -d build ] || return 0
    # create src/app-files: if "checkout" was not done, docekr will create them root-owned
    mkdir -p src app-files scripts compiled/TRANSIT/opt/sarch
    # "build" directlry may contain eitehr of Makefile and/or Dockerfile
    # Step 1: Makefile ----------------------
    # note: it is OK not to have a Makefile
    if [ -f build/Makefile ]; then
        IMAGENAME=$(get-image-name-from-makefile Makefile)
        pushd build >/dev/null
        make build | log builds
        if [ ${PIPESTATUS[0]} -ne 0 ]; then
            echo Make failed | log builds
            popd >/dev/null
            return 1
        fi
        popd >/dev/null
    fi
    # Step 2: Dockerfile --------------------
    # note: it is OK not to have a Dockerfile
    if [ -f build/Dockerfile ]; then
        # $IMAGE variable is supplied via 'iterate-directories'
        BUILDER=${IMAGE}_builder
        docker build -f build/Dockerfile -t ${BUILDER}:latest . | log builds
        if [ ${PIPESTATUS[0]} -ne 0 ]; then
            echo Builder image assembly failed | log builds
            return 2
        fi
        # provide sample scripts into "scripts" subdir
        make-builder-docker-scripts
        # "app-files" directory (read-only!) supplies module-specific files to /build/src
        # "src" directory (read-only!) supplies sources as volume mounted to /build/src
        # "compiled" directory (writable) is provided to place results to /build/compiled
        local CMD="docker run --rm \
            -v $(pwd)/app-files:/build/app-files:ro \
            -v $(pwd)/src:/build/src:ro \
            -v $(pwd)/compiled:/build/compiled \
            $BUILDER"
        pushd build >/dev/null
        $CMD | log builds
        if [ ${PIPESTATUS[0]} -ne 0 ]; then
            echo Compilation failed | log builds
            popd >/dev/null
            return 3
        fi
        popd >/dev/null
    fi
}

# ------------------------------------------------- build-one-image --------
function build-one-image {
    if [ -n "$VERSION" ]; then
        if [ "$VERSION" != "latest" ]; then
            [ -n "$(git status -s | sed '/^\s*$/d')" ] && die 20 "ABORTED: local changes in $(pwd) found"
            # Check if we are on specified tag
            LC_ALL=en git branch --no-color | grep '*' | grep detached | grep v$VERSION &>/dev/null
            [ $? == 0 ] || die 342 "Tag $VERSION is not selected as current one. Run 'image-service update -v=$VERSION' first"
        fi
    fi
    
    build-image
    if [ $? -ne 0 ]; then
        echo "Failed 'build-image' phase" | log builds
        return 7
    fi

    if [ -n "$VERSION" ]; then
        docker tag $IMAGE:latest $IMAGE:$VERSION
        (( DEBUG != 0 )) && echo STAGE=$PRODUCT_STAGE IMAGE=$IMAGE
    fi
    return 0
}

function tag-list {
    git fetch --tags
    git tag -n1
}

# --------------------------------------------------- tag-one-image --------
function tag-one-image {
    if [ -z "$COMMIT_MESSAGE" ]; then
        die 85 "Empty commit message not allowed"
    fi

    local version_dir=$STAGE_DIR/version
    [ -d $version_dir ] && rm -rf $version_dir
    git clone $GIT_VERSION_REPO $version_dir &>/dev/null || die 88 "Clone version repo failed"

    local svc=$SELECTED_MODULE_DIR
    local version=0
    local release="$(cat $version_dir/release)"
    [ -f "$version_dir/$svc" ] && version="$(cat $version_dir/$svc)"
    let version++
    local tag=v${release}${version}

    mkdir -p $STAGE_DIR/vsaas
    pushd $STAGE_DIR/vsaas &>/dev/null
    rm -rf $svc
    git clone --depth 1 -b dev $GIT_VSAAS/$svc &>/dev/null || die 99 "Cannot clone 'dev' branch"
    pushd $svc &>/dev/null

    # Create tag and push to the server
    git tag -a $tag -m "$COMMIT_MESSAGE" && git push origin : $tag
    while [ $? != 0 ]; do
        let version++
        tag=v${release}${version}
        git tag -a $tag -m "$COMMIT_MESSAGE" && git push origin : $tag
    done

    if [ $? == 0 ]; then
        pushd $version_dir &>/dev/null
        echo $version > $svc
        git add $svc
        git commit -m "$COMMIT_MESSAGE"
        git push origin master
        popd &>/dev/null
    fi
    echo TAGGED: $tag
}

# --------------------------------------------------- cleanup -------------
function cleanup {
    sudo rm -rf compiled
    [ -d src ] || return 0
    for srcitem in $(ls src); do
        if [ -d "src/$srcitem" -a -d "src/$srcitem/.svn" ]; then
            rm -rf src/$srcitem
            continue
        fi
    done
}

# --------------------------------------------------------------------------
function check-product-version-exists {
    export IMGLIST_FILE=$REV_DIR/overcast.$VERSION
    if [ ! -f $IMGLIST_FILE ]; then
        echo Product versioned images list file:
        cd $REV_DIR
        ls overcast*
        die 20 "Missing product versioned images list file for requested version=$VERSION"
    fi
    export PRODUCT_STAGE=$STAGE_DIR/$VERSION
    [ -d $PRODUCT_STAGE ] || mkdir $PRODUCT_STAGE
}

# --------------------------------------------------- product-status -------
function product-status {
    check-product-version-exists
    local LIST=$(make-image-list MISSING)
    if [ -z "$LIST" ]; then
        echo ALL images are ready
        return
    fi
    echo MISSING IMAGES:
    for IMG_REV in $LIST; do
        echo $IMG_REV
    done
}

# ---------------------------------------------------- copy-definitions -------
function copy-definitions {
    check-product-version-exists
    rm -rf $STAGE_DIR/$VERSION

    local LIST=$(make-image-list ALL)
    (( DEBUG != 0 )) && echo LIST=$LIST

    # For now definitions are stored for specific cluster
    mkdir -p $PRODUCT_STAGE
    echo $CLUSTER_ENV > $PRODUCT_STAGE/cluster-env

    local TMPDIR=$STAGE_DIR/tmp
    rm -rf $TMPDIR
    mkdir -p $TMPDIR
    pushd $TMPDIR
    # Copy deployment scripts
    for IMG_REV in $LIST; do
        (( DEBUG != 0 )) && echo "---------- copy-definitions / image => $IMG_REV ---------"
        # overcast/media-streamer:1.0
        local IMG_NAME=${IMG_REV%%:*}
        IMG_NAME=${IMG_NAME##*/}
        local VER=${IMG_REV##*:}

        git clone "$GIT_VSAAS/$IMG_NAME"

        pushd $TMPDIR/$IMG_NAME
        if [ "$VERSION" != "latest" ]; then
            git checkout --force "v$VER" &>/dev/null || die 21 "ABORTED: specified Git version tag was not found"
        fi

        mkdir -p $PRODUCT_STAGE/$IMG_NAME

        cp -vf deploy/* $PRODUCT_STAGE/$IMG_NAME/ 2>/dev/null

        popd >/dev/null 2>&1
    done

    # Export staging environment
    mkdir -p $PRODUCT_STAGE/etc
    echo Export staging environment for mask=$EXPORT2ENV_MASK
    export PRODUCT_VERSION=$VERSION
    set|egrep $EXPORT2ENV_MASK|egrep '^\w+=.*$'|grep -v EXPORT2ENV_MASK | grep -v BASH_REMATCH | grep -v line= | grep -v ^_= > $PRODUCT_STAGE/etc/staging-env.conf

    # Copy "deploy-xxx" / destroy
    (( DEBUG != 0 )) && echo "---------- copy-definitions / deploy-xxx & destroy ---------"
    for i in $(seq -f "%03g" 0 $(get-deploy-level)); do
        cp -vf $BASE_DIR/deploy/$CLUSTER_IAAS/iaas-deploy-${i}* $PRODUCT_STAGE/ 2>/dev/null
    done
    cp -vf $BASE_DIR/deploy/k8s/deploy* $PRODUCT_STAGE/ 2>/dev/null
    cp -vf $BASE_DIR/deploy/iaas/$CLUSTER_IAAS/{test-cli,cluster-*,docker-*} $REV_DIR/overcast.$VERSION $PRODUCT_STAGE/

    # Checkout DB scripts
    pushd $PRODUCT_STAGE &>/dev/null
    DB_LEVEL=$(grep DB_DEPLOY_LEVEL $PRODUCT_STAGE/overcast.$VERSION | cut -d: -f2 | tr -d ' ')
    if [ "$DB_LEVEL" == latest ]; then
        svn co http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/db &>/dev/null
    else
        svn co -r $DB_LEVEL http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/db &>/dev/null
    fi
    rm -rf $PRODUCT_STAGE/db/.svn
    popd &>/dev/null

    # Add AVATAR_VERSION_MIN to staging environment
    AVATAR_VERSION_MIN=$(grep AVATAR_VERSION_MIN $PRODUCT_STAGE/overcast.$VERSION | cut -d: -f2 | tr -d ' ')
    echo "AVATAR_VERSION_MIN=$AVATAR_VERSION_MIN" >> $PRODUCT_STAGE/etc/staging-env.conf

    # Add CAM_MRETR_VERSION to staging environment
    CAM_MRETR_VERSION=$(grep cam-mretr $PRODUCT_STAGE/overcast.$VERSION | cut -d: -f2 | tr -d ' ')
    echo "CAM_MRETR_VERSION=$CAM_MRETR_VERSION" >> $PRODUCT_STAGE/etc/staging-env.conf

    # Preserve images/versions list
    echo $LIST > $PRODUCT_STAGE/image-list
}

# ---------------------------------------------- build-product-images -------
function build-product-images {
    check-product-version-exists
    local SCOPE=$([ -z "$NO_CACHE" ] && echo MISSING || echo ALL)
    local LIST=$(make-image-list $SCOPE)
    (( DEBUG != 0 )) && echo LIST=[$LIST] SCOPE=$SCOPE

    if (( QUIET == 0 )); then
        echo You are about to build all missing images:
        for i in $LIST; do
            echo "    $i"
        done
        wait-confirmation It will be a long operation!
        QUIET=1
    fi

    for IMG_REV in $LIST; do
        (( DEBUG != 0 )) && echo build-product-images / image =\> $IMG_REV
        # overcast/media-streamer:1.0
        IMAGE=${IMG_REV%%:*}
        IMG_NAME=${IMAGE##*/}
        VERSION=${IMG_REV##*:}
        (( DEBUG != 0 )) && echo IMAGE=$IMAGE IMG_NAME=$IMG_NAME IMG_VER=$IMG_VER
        pushd $IMG_SRC_DIR/$IMG_NAME
        repo-exec update
        build-one-image
        popd
    done
}

# ------------------------------------------------ export-product ---------
function export-product {
    check-product-version-exists
    local LIST=$(make-image-list READY2GO)
    (( DEBUG != 0 )) && echo LIST=[$LIST]
    [[ "$LIST" =~ 'ABORT' ]] && die 22 'ABORTING export'

    # Copy deployment scripts first
    copy-definitions

    pushd $STAGE_DIR/..

    DB_LEVEL=$(grep DB_DEPLOY_LEVEL $STAGE_DIR/$VERSION/overcast.$VERSION | cut -d: -f2 | tr -d ' ')
    if [ "$DB_LEVEL" == latest ]; then
        svn co http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/db &>/dev/null
    else
        svn co -r $DB_LEVEL http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/db &>/dev/null
    fi

    svn co http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/lib &>/dev/null
    svn co http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/drafts &>/dev/null
    svn co http://svn.dev.videonext.net/svn/va/branches/$SVN_BRANCH/docker/deploy &>/dev/null

    cp -r revisions deploy/

    TARFILE=overcast-$VERSION-$CLUSTER_ENV-$(date +%Y%m%d-%H%M%S).tar
    echo $(date +%H:%M:%S) Packaging into TGZ: $TARFILE
    tar cfv $TARFILE \
        stage/$VERSION \
        bin/_* \
        bin/overcast-deployer \
        bin/image-service \
        bin/db-conf \
        bin/conf-helper \
        bin/curve_keygen \
        bin/k8s-helper \
        bin/log_parser \
        bin/node-label \
        bin/substitute \
        bin/tls-helper \
        bin/realm-helper \
        bin/pod* \
        env/environment-sample.k8s \
        env/environment.$CLUSTER_ENV \
        db \
        lib \
        drafts/realm \
        deploy/revisions/overcast.$VERSION \
        deploy/k8s \
        deploy/iaas/$CLUSTER_IAAS
    # Create symlink
    ln -sf $TARFILE overcast-$VERSION-$CLUSTER_ENV.tar
    echo $(date +%H:%M:%S) DONE

    # Cleanup
    rm -rf ./{db,lib,drafts,deploy}
    rm -rf ./db/.svn ./lib/.svn ./drafts/.svn ./deploy/.svn

    popd
}

function push-latest-release {
    check-product-version-exists
    local LIST=$(make-image-list READY2GO)
    [[ "$LIST" =~ 'ABORT' ]] && die 22 'ABORTING operation'

    for IMG_REV in $LIST; do
        (( DEBUG != 0 )) && echo tag-product-images / image =\> $IMG_REV
        # overcast/media-streamer:1.0
        IMAGE=${IMG_REV%%:*}
        IMG_NAME=${IMAGE##*/}
        IMG_VER=${IMG_REV##*:}
        IMG_NS=${IMAGE%%/*}
        docker tag $IMG_NS/$IMG_NAME:$IMG_VER $IMG_NS/$IMG_NAME:latest

        export IMAGE=$IMG_NS/$IMG_NAME   # ex.: overcast/ptz
        export IVER=":latest"
        export SHORTNAME=${IMAGE##*/} # ex.: ptz
        $BASE_DIR/deploy/iaas/${CLUSTER_IAAS}/docker-push
    done
}

# --------------------------------------------------------------------------
# ---------------------------------= MAIN =---------------------------------
# --------------------------------------------------------------------------

IMG_SRC_DIR=$BASE_DIR/images/service
IMAGES=''
export QUIET=0
export COMMAND=$1

[ -z "$COMMAND" ] && USAGE && die 1 "Need at least one argument"

for ARG in "$@"; do
    case $ARG in
        --debug)
            export DEBUG=1
            ;;
        -q|--quiet)
            export QUIET=1
            ;;
        -n|--no-cache)
            export NO_CACHE="--no-cache"
            ;;
        -i=*|--image=*)
            SELECTED_MODULE_DIR="${ARG#*=}"
            if [ ! -f $IMG_SRC_DIR/$SELECTED_MODULE_DIR/Makefile ]; then
                fetch-git-images
                if [ $SELECTED_MODULE_DIR != all -a ! -f $IMG_SRC_DIR/$SELECTED_MODULE_DIR/Makefile ]; then
                    die 17 'Module specified does not exist!'
                fi
            fi
            ;;
        -v=*|--version=*)
            VERSION="${ARG#*=}"
            #if [ -n "$VERSION" -a $VERSION != "latest" -a $SVN_BRANCH != "1.2.0" -a $SVN_BRANCH != "1.2.1" ]; then
            #    echo Only 'latest' version allowed for custom SVN branch
            #fi
            ;;
        -m=*|--message=*)
            COMMIT_MESSAGE="${ARG#*=}"
            ;;
    esac
done

(( DEBUG == 0 )) || cat <<EOF
========== Processing command ==========
  COMMAND  => $COMMAND
  MODULE   => $SELECTED_MODULE_DIR
  VERSION  => $VERSION
  NO_CACHE => $NO_CACHE
  QUIET    => $QUIET
  CI_MSG   => $COMMIT_MESSAGE
========================================
EOF

PRODUCT_STAGE=$STAGE_DIR/latest
mkdir -p $PRODUCT_STAGE

case $COMMAND in
    list)
        iterate-directories $IMG_SRC_DIR
        ;;
    clean)
        wait-confirmation 'Cleaning stage area will delete all files in "docker/images/service/<image>/src". Hit Ctrl-C now to abort, Enter to proceed...'
        iterate-directories $IMG_SRC_DIR cleanup
        svn up $BASE_DIR
        ;;
    checkout)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        echo ============ CHECKOUT ========== | log repo-operations
        iterate-directories $IMG_SRC_DIR repo-exec checkout
        ;;
    u|update)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''
        echo ============ Update itself ========== | log repo-operations
        svn update $BASE_DIR
        svn update $SCRIPTDIR
        #fetch-git-images
        echo ============ UPDATE ============ | log repo-operations
        iterate-directories $IMG_SRC_DIR repo-exec update
        ;;
    commit)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        echo ============ COMMIT ============ | log repo-operations
        iterate-directories $IMG_SRC_DIR repo-exec commit $@
        ;;
    status)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        iterate-directories $IMG_SRC_DIR repo-exec status
        ;;
    b|build)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''
        echo ============ BUILD ============ | log builds
        iterate-directories $IMG_SRC_DIR build-one-image
        ;;
    build-product)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        fetch-git-images
        build-product-images
        ;;
    copy-definitions)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        copy-definitions
        ;;
    product-status)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        product-status
        ;;
    export-product)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        export-product
        ;;
    import-product)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        import-product
        ;;
    p|push)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''
        iterate-directories $IMG_SRC_DIR push-image
        ;;
    bp)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''

        echo ============ BUILD ============ | log builds
        iterate-directories $IMG_SRC_DIR build-one-image

        iterate-directories $IMG_SRC_DIR push-image

        if ! [[ $SELECTED_MODULE_DIR =~ ^vae- ]]; then
            pod-rm $SELECTED_MODULE_DIR
        fi
        ;;
    ubp)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''

        echo ============ Update itself ========== | log repo-operations
        svn update $BASE_DIR
        svn update $SCRIPTDIR
        #fetch-git-images
        echo ============ UPDATE ============ | log repo-operations
        iterate-directories $IMG_SRC_DIR repo-exec update

        echo ============ BUILD ============ | log builds
        iterate-directories $IMG_SRC_DIR build-one-image

        iterate-directories $IMG_SRC_DIR push-image

        if ! [[ $SELECTED_MODULE_DIR =~ ^vae- ]]; then
            pod-rm $SELECTED_MODULE_DIR
        fi
        ;;
    set-branch)
        [ -z "$2" ] && die 20 'Must specify branch'
        set-branch $2
        #fetch-git-images
        ;;
    tag-minor|tag-major)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        #[ "$SVN_BRANCH" != "$DEFAULT_SVN_BRANCH" -a "$SVN_BRANCH" != "$UNSTABLE_SVN_BRANCH"  -a "$SVN_BRANCH" != "$HOTFIX_SVN_BRANCH" ] && die 17 'Tagging is forbidden for current branch'
        [ -n "$VERSION" ] && die 18 'Tag version generation is automatic, you can not specify your own version'
        echo ============ BUILD ============ | log builds
        svn update $BASE_DIR
        #iterate-directories $IMG_SRC_DIR repo-exec update
        iterate-directories $IMG_SRC_DIR tag-one-image
        ;;
    tag-list)
        [ -z "$SELECTED_MODULE_DIR" ] && die 16 'Must specify module name'
        [ "$SELECTED_MODULE_DIR" == 'all' ] && SELECTED_MODULE_DIR=''
        iterate-directories $IMG_SRC_DIR tag-list
        ;;
    push-latest-release)
        [ -z "$VERSION" ] && die 19 'Must provide version parameter'
        push-latest-release
        ;;
    env-stat)
        echo "Current environment: $CLUSTER_ENV"
        tail -n+2 $ENV_LOADER
        ;;
    env-list)
        echo "Environments registered ($SCRIPTDIR/env.*):"
        list-env
        ;;
    env-set)
        SELECTED_MODULE_DIR=$2
        set-env
        ;;
    *)
        USAGE
        die 1 "COMMAND not recognized"
esac
echo
