#!/bin/bash
# push container images from a registry to an ECR

set -e

export catalog_dir=/etc/cgyle2ecrmetadata.d
export ecr="ecr"
export alias=""

function usage {
    echo "cgyle2ecr --registry <url> --aws-ecr <url> --filter-policy <file>"
    echo "  [--public]"
    echo "     push to public ECR"
    echo "  [--aws-profile <name>]"
    echo "     aws config profile name"
    echo "  [--alias <name>]"
    echo "     ECR alias name to use, by default taken from sync path"
    echo "  [--dry-run]"
    echo "     apply filter policy only and print list of matches"
    echo "  [--debug]"
    echo "     enable debug information"
    exit 1
}

function get_source_catalog {
    local repo=$1
    local catalog
    repo=$(echo "${repo}" | tr / _)
    catalog="${catalog_dir}/${repo}.json"
    if [ -f "${catalog}" ];then
        echo "file://${catalog}"
    fi
}

ARGUMENT_LIST=(
    "aws-profile:"
    "aws-ecr:"
    "registry:"
    "filter-policy:"
    "alias:"
    "dry-run"
    "debug"
    "public"
)

# read arguments
if ! opts=$(getopt \
    --longoptions "$(printf "%s," "${ARGUMENT_LIST[@]}")" \
    --name "$(basename "$0")" \
    --options "" \
    -- "$@"
); then
    usage
fi

eval set --"${opts}"

while [[ $# -gt 0 ]]; do
    case "$1" in
        --aws-profile)
            argAWSProfile=$2
            shift 2
            ;;

        --aws-ecr)
            argAWSECR=$2
            shift 2
            ;;

        --registry)
            argRegistry=$2
            shift 2
            ;;

        --filter-policy)
            argFilterPolicy=$2
            shift 2
            ;;

        --alias)
            argAlias=$2
            shift 2
            ;;

        --dry-run)
            argDryRun=1
            shift
            ;;

        --debug)
            argDebug=1
            shift
            ;;

        --public)
            argPublic=1
            shift
            ;;

        *)
            break
            ;;
    esac
done

if [ ! "${argAWSECR}" ] || \
   [ ! "${argFilterPolicy}" ];then
    usage
fi

if [ "${argDebug}" ];then
    set -x
fi

registry=${argRegistry}
profile=${argAWSProfile}
push_registry=${argAWSECR}
filter=${argFilterPolicy}
if [ "${argPublic}" ];then
    ecr="ecr-public"
fi

if [ "${argAlias}" ];then
    alias="--push-ecr-alias ${argAlias}"
fi

if [ -n "${profile}" ];then
    aws_ecr="aws ${ecr} --profile ${profile}"
else
    aws_ecr="aws ${ecr}"
fi

# Get credentials
push_creds=$(
    ${aws_ecr} get-login-password
)

# Create repos on the remote ECR
cgyle \
    --updatecache "${registry}" --from "${registry}" \
    --filter-policy "${filter}" 2>&1 |\
grep -v INFO:Proxy: | cut -f2- -d- | cut -f1 -d\[ | while read -r repo;do
    # we searched for containers in the given filter-policy.
    # The result is a path. The first element of that path is
    # the custom alias name of the ECR registry in AWS. The
    # aws ecr|ecr-public command constructs the repositoryUri
    # automatically from the used account which already includes
    # that custom alias name. It is therefore required that we
    # skip the first path element from the search result
    repo=$(echo "${repo}" | cut -f2- -d/)

    echo "${repo}"
    if [ ! "${argDryRun}" ];then
        if ! ${aws_ecr} describe-repositories \
            --repository-names "${repo}" &> /dev/null
        then
            ${aws_ecr} create-repository \
                --repository-name "${repo}"
            ${aws_ecr} put-repository-catalog-data \
                --cli-input-json "$(get_source_catalog "${repo}")"
        fi
    fi
done

# Push images to repos on the remote ECR
if [ ! "${argDryRun}" ];then
    # shellcheck disable=SC2086
    cgyle \
        --updatecache "${registry}" --from "${registry}" \
        --push-oci "${push_registry}" \
        --push-oci-creds=AWS:"${push_creds}" ${alias} \
        --filter-policy "${filter}" \
        --with-attestation \
        --apply
fi
