#!/bin/sh
#
# Installs Deepfactor runtime from OS distribution package
#
# @param --version: optional version to install
# @param --no-docker-volume: option to skip creation of docker volume
# @param --no-package-install: option to install from runtime image instead of package manager
# @param --skip-package-download: option to skip downloading package to install when already exists
# @param --dfrt-image: optional staging repo for DF_RUNTIME_IMAGE
#            include tag when used with no-package-install
# @param --no-version-check: skip all version checks and install the latest or specified version
# @param --verbose: write each command to standard error (preceded by a ‘+ ’) before it is executed.  Useful for debugging.
set -e

PLATFORM=`uname -s`
if [ "${PLATFORM}" = "Darwin" ] ; then
	OSSTR="Darwin"
fi

if [ "${PLATFORM}" != "Darwin" ] ; then
	DISTRO=$(cat /etc/os-release | grep "^ID=" | awk -F = '{print $2}')
	OSSTR=$(echo "${DISTRO}" | sed -e 's/^"//' -e 's/"$//')
fi

# since we are installing dfctl, use it's version to get the tag to pull
DF_RUNTIME_IMAGE="public.ecr.aws/deepfactor/df/runtime"

if [ "$(id -u)" -ne "0" ] ; then
	sudo="sudo"
	if [ "${OSSTR}" = "alpine" ] ; then
		echo "Missing privileges. Kindly re-run with sudo"
		exit 1
	fi
fi

invalidparam() {
    echo "Invalid parameters ${1} supplied"
    exit 1
}

get_pkgver_str() {
    pkgver_str=""
	if [ ! -z "$2" ] ; then
        case "${1}" in
          "centos" )
              # centos format is "-A.B-BLD" or "-A.B.C-BLD"
              pkgver_str="-${2}"
          ;;
          "debian" )
              # debian format is "=A.B-BLD" or "=A.B.C-BLD"
              pkgver_str="=${2}"
          ;;
          "alpine" )
              # alpine format is "=A.B-rBLD" or "=A.B.C-rBLD"
              eval "$(echo -n ${2} | awk -F'\\.|-' '{print "MAJ="$1"\nMIN="$2"\nPCH="$3"\nBLD="$4}')"
              if [ ! -z "$BLD" ] ; then
                  pkgver_str="=${MAJ}.${MIN}.${PCH}-r${BLD}"
              else
                  pkgver_str="=${MAJ}.${MIN}-r${PCH}"
              fi
          ;;
          * )
            pkgver_str=""
          ;;
        esac
	else
        pkgver_str=""
	fi
	echo ${pkgver_str}
}

# @param1 glibc|musl
non_pkg_install() {
  if [ ! "$package_install" = "false" ]; then
    # error exit code
    return 1
  fi
  # TODO cleanup prior install without wiping portal
  #${sudo} rm -rf /opt/deepfactor
  ${sudo} docker pull $DF_RUNTIME_IMAGE
  ${sudo} docker create --name deepfactor-runtime-install $DF_RUNTIME_IMAGE
  ${sudo} docker cp deepfactor-runtime-install:/opt/deepfactor /opt/
  ${sudo} docker cp deepfactor-runtime-install:/bin/busybox.static /opt/deepfactor/
  ${sudo} docker rm deepfactor-runtime-install

  # from .deb deepfactor-runtime.postinst
  # create /opt/deepfactor/service for use in service sealing
  ${sudo} mkdir -p /opt/deepfactor/service
  # create /opt/deepfactor/manifest as default location for manifest file
  ${sudo} mkdir -p /opt/deepfactor/manifest
  ${sudo} ln -sf /opt/deepfactor/$1/dfctl /usr/bin/dfctl
  # ensure dfeventd upgrade starts with next instrumented run
  ${sudo} pkill -9 dfeventd || true

  #TODO check if libstdc++ installed, dfctl test?
  /usr/bin/dfctl version

  # return exit code 0 on success or exit on failure
  return 0
}

parse_key_value() {
	echo "$1" | grep -o "\"$2\": *[^,}]*" | sed "s/\"$2\"://" | sed 's/^ *//;s/ *$//'| tr -d '"'
}

parse_portal_type() {
	parse_key_value "$1" "portal_type"
}

parse_portal_certs() {
	parse_key_value "$1" "certs" | base64 -d
}

parse_portal_url() {
	parse_key_value "$1" "portal_url"
}

parse_access_token() {
	parse_key_value "$1" "access_token"
}


invalid_runtoken() {
	printf "%s\n" "Error: could not decode run token."\
	"Obtain a new run token from the portal. This token can be obtained from the Deepfactor management portal's 'START' dialog." >&2
	exit 1
}

empty_runtoken() {
	printf "%s\n" "Error: missing DF_RUN_TOKEN environment variable."\
	"This token can be obtained from the Deepfactor management portal's 'START' dialog." >&2
	exit 1
}

unsupported_version() {
	printf "%s\n" "Error: trying to install an unsupported version of dfctl($1)."\
	"The minimum supported version is $2."\
	"The recommended version is $3."\
	"Please install the recommended version to get the latest functionality and fixes." >&2
	exit 1
}

unsupported_max_version() {
	printf "%s\n" "Error: trying to install an unsupported version of dfctl($1)."\
	"The minimum supported version is $2."\
	"The recommended version is $3."\
	"The maximum supported version is $4." \
	"Please install the recommended version to get the latest functionality and fixes." >&2
	exit 1
}

version_greaterthan_recommended(){
	printf "%s\n" "Warning: trying to install a version of dfctl($1) that is greater than recommended."\
	"The minimum supported version is $2. The recommended version is $3." >&2
}

# Get access token from portal
# returns:
#		exits with return code 1, if portal does not provide an access_token
#		"<access_token>",         if portal supports short-lived tokens and access token generation failed
get_access_token() {
	if [ -z "$DF_RUN_TOKEN" ] ; then
		empty_runtoken
	fi
	decoded_runtoken=$(echo "$DF_RUN_TOKEN" | base64 -d)
	portal_type=$(parse_portal_type "$decoded_runtoken")
	certs=$(parse_portal_certs "$decoded_runtoken")
	portal_hostname=$(parse_portal_url "$decoded_runtoken")
	# portal_hostname will be empty for tokens < 3.3.2
	if [ "$portal_hostname" = "" ]; then
		invalid_runtoken
	fi

	access_token_url="https://$portal_hostname/api/auth/v1/access-token"
	curl_command="curl -sS -w '\n%{http_code}' -d '$decoded_runtoken' '$access_token_url'"
	DF_CERT_FILE="/tmp/df_ca.crt"
	if [ "$portal_type" = "onprem" ]; then
		if [ "$certs" = "" ]; then
			invalid_runtoken
		fi
		echo "-----BEGIN CERTIFICATE-----" > $DF_CERT_FILE
		echo "$certs" >> $DF_CERT_FILE
		echo "-----END CERTIFICATE-----" >> $DF_CERT_FILE
		curl_command="$curl_command --cacert $DF_CERT_FILE"
	elif [ "$portal_type" != "saas" ]; then
		invalid_runtoken
	fi

	curl_resp=$(eval "$curl_command")
	if [ "$portal_type" = "onprem" ]; then
		rm $DF_CERT_FILE
	fi
	http_code=$(echo "$curl_resp" | tail -n1);
	if [ "$http_code" = "401" ]; then
		invalid_runtoken
	elif [ "$http_code" != "200" ]; then
		echo "Error: Generating access token failed with htttp-status=$http_code." >&2
		exit 1
	fi
	access_token=$(parse_access_token "$curl_resp")
	if [ "${access_token}" = "" ]; then
		echo "Error: unable to obtain access token from portal. response: $curl_resp." >&2
		exit 1
	fi
	echo "$access_token"
}

# validates if we're able to connect to the portal using the provided access token
# @param1 access_token
#	exists with return code 1 when validation fails
validate_portal_connection() {
	if [ -z "$DF_RUN_TOKEN" ] ; then
		empty_runtoken
	fi

	decoded_runtoken=$(echo "$DF_RUN_TOKEN" | base64 -d)
	portal_type=$(parse_portal_type "$decoded_runtoken")
	certs=$(parse_portal_certs "$decoded_runtoken")
	portal_hostname=$(parse_portal_url "$decoded_runtoken")
	if [ "$portal_hostname" = "" ]; then
		invalid_runtoken
	fi

	verify_access_token_url="https://$portal_hostname/api/services/v1/verifyruntoken"
	curl_command="curl -sS -w '\n%{http_code}' --header 'Authorization: Bearer $1' $verify_access_token_url"
	DF_CERT_FILE="/tmp/df_ca.crt"
	if [ "$portal_type" = "onprem" ]; then
		if [ "$certs" = "" ]; then
			invalid_runtoken
		fi
		echo "-----BEGIN CERTIFICATE-----" > $DF_CERT_FILE
		echo "$certs" >> $DF_CERT_FILE
		echo "-----END CERTIFICATE-----" >> $DF_CERT_FILE
		curl_command="$curl_command --cacert $DF_CERT_FILE"
	elif [ "$portal_type" != "saas" ]; then
		invalid_runtoken
	fi

	curl_resp=$(eval "$curl_command")
	if [ "$portal_type" = "onprem" ]; then
		rm $DF_CERT_FILE
	fi
	http_code=$(echo "$curl_resp" | tail -n1)
	if [ "$http_code" = "401" ]; then
		echo "Error: generating access token failed with htttp-status=$http_code." \
		"Access token expired in flight. Please try running the install script again" >&2
		exit 1
	elif [ "$http_code" = "403" ]; then
		echo ""
		return 0
	elif [ "$http_code" != "200" ]; then
		echo "Error: generating access token failed with htttp-status=$http_code." >&2
		exit 1
	fi

	if [ "$(parse_key_value "$curl_resp" "is_valid")" != "true" ]; then
		echo "DF_RUN_TOKEN validation failed" >&2
		invalid_runtoken
	else
		echo "validated DF_RUN_TOKEN validation successful"
	fi
}

# Gets the minimum and recommended version for runtime from portal
# @param1 access_token
# returns:
#		"",                         when portal doesn't support recommended versions query (3.3.2)
#		exists with return code 1,  when portal supports recommended versions query and query fails
#		"<min_ver> <rec_ver>",      when portal supports recommended versions query
get_recommended_versions() {
	decoded_runtoken=$(echo "$DF_RUN_TOKEN" | base64 -d)
	portal_type=$(parse_portal_type "$decoded_runtoken")
	certs=$(parse_portal_certs "$decoded_runtoken")
	portal_hostname=$(parse_portal_url "$decoded_runtoken")
	if [ "$portal_hostname" = "" ]; then
		invalid_runtoken
	fi

	get_recommended_versions_url="https://$portal_hostname/api/services/v1/versionsupport"
	curl_command="curl -sS -w '\n%{http_code}' --header 'Authorization: Bearer $1' '$get_recommended_versions_url'"
	DF_CERT_FILE="/tmp/df_ca.crt"
	if [ "$portal_type" = "onprem" ]; then
		if [ "$certs" = "" ]; then
			invalid_runtoken
		fi
		echo "-----BEGIN CERTIFICATE-----" > $DF_CERT_FILE
		echo "$certs" >> $DF_CERT_FILE
		echo "-----END CERTIFICATE-----" >> $DF_CERT_FILE
		curl_command="$curl_command --cacert $DF_CERT_FILE"
	elif [ "$portal_type" != "saas" ]; then
		invalid_runtoken
	fi

	curl_resp=$(eval "$curl_command")
	if [ "$portal_type" = "onprem" ]; then
		rm $DF_CERT_FILE
	fi
	http_code=$(echo "$curl_resp" | tail -n1)
	if [ "$http_code" = "401" ]; then
		echo "Error: getting recommended version from the portal failed with http-status:$http_code." \
		"Access token expired in flight. Please try running the install script again" >&2
		exit 1
	elif [ "$http_code" = "403" ]; then
		# expected for 3.3.2 portal
		echo ""
		return 0
	elif [ "$http_code" != "200" ]; then
		echo "Error: getting recommended version from the portal failed with http-status:$http_code." >&2
		exit 1
	fi

	runtime_versions=$(echo "$curl_resp" | grep -o '"version_support"\s*:\s*\[.*\]' | grep -o '{[^}]*runtime[^}]*}')
	min_supported_ver=$(parse_key_value "$runtime_versions" "min")
	recommended_ver=$(parse_key_value "$runtime_versions" "recommended")
	echo "$min_supported_ver $recommended_ver"
}

version_gt() {
  test "$(printf '%s\n' "${@}" | sort -V | head -n 1)" != "${1}"
}

# Compares two df version strings:
#  versions should follow the format MAJOR.MINOR.PATCH / MAJOR.MINOR.PATCH-BUILD
#  -1 if a<b
#   0 if a=b
#   1 if a>b
dfver_comp() {
  # Extract MAJOR.MINOR.PATCH from the version
  a_mmp=${1%-*}
  b_mmp=${2%-*}

  # Extract BUILD from the version
  a_build=$(expr "$1" : '.*-\([0-9]*\)$' || true)
  b_build=$(expr "$2" : '.*-\([0-9]*\)$' || true)

  # If the two reconstituted version strings are equal then the versions
  # are equal.
  if [ "${1}" = "${2}" ]; then
    result=0

  # If neither version have a build or if both versions have a build
  # then the versions may be compared with sort -V.
  elif { [ "${a_build}" = "" ] && [ "${b_build}" = "" ]; } || \
     { [ "${a_build}" != "" ] && [ "${b_build}" != "" ]; }; then
    { version_gt "${1}" "${2}" && result=1; } || result=-1

  # If $1 does not have a build and the two MAJOR.MINOR.PATCH
  # version strings are equal, then $1>$2.
  elif [ "${a_build}" = "" ] && [ "${a_mmp}" = "${b_mmp}" ]; then
    result=1

  # If $1 does have a build and the two MAJOR.MINOR.PATCH
  # version strings are equal, then $1<$2.
  elif [ "${a_build}" != "" ] && [ "${a_mmp}" = "${b_mmp}" ]; then
    result=-1

  # Otherwise compare the two versions using sort -V.
  else
    { version_gt "${1}" "${2}" && result=1; } || result=-1
  fi

  echo "${result}"
}

# set recommended versions to install
# @param1 minimum supported version
# @param2 recommended version
# @param3 optional: maximum version if applicable
# modifies DF_RUNTIME_IMAGE | reqver
set_recommended_version() {
	if [ "$package_install" = "false" ] ; then
		dfimagetag=$(basename "$DF_RUNTIME_IMAGE" | grep -o ':.*' | sed 's/://' || echo "")
		if [ "$dfimagetag" != "" ] ; then
			if [ "$(dfver_comp "$dfimagetag" "$1")" = "-1" ]; then
				unsupported_version "$dfimagetag" "$1" "$2"
			elif [ "$(dfver_comp "$dfimagetag" "$2")" = "1" ]; then
				if [ "$3" != "" ] && [ "$(dfver_comp "$dfimagetag" "$3")" = "1" ]; then
					unsupported_max_version "$dfimagetag" "$1" "$2" "$3"
				fi
				version_greaterthan_recommended "$dfimagetag" "$1" "$2"
			fi
		else
			DF_RUNTIME_IMAGE="$DF_RUNTIME_IMAGE:$2"
		fi
	else
		if [ "$reqver" != "" ]; then
			if [ "$(dfver_comp "$reqver" "$1")" = "-1" ]; then
				unsupported_version "$reqver" "$1" "$2"
			elif [ "$(dfver_comp "$reqver" "$2")" = "1" ]; then
				if [ "$3" != "" ] && [ "$(dfver_comp "$reqver" "$3")" = "1" ]; then
					unsupported_max_version "$reqver" "$1" "$2" "$3"
				fi
				version_greaterthan_recommended "$reqver" "$1" "$2"
			fi
		else
			reqver="$2"
		fi
	fi
}

check_if_old_runtoken_format() {
	case "$DF_RUN_TOKEN" in
		*.*.*)
		echo 1
		;;
		*)
		echo 0
		;;
	esac
}

#
# Main script starts here
#

ver_str=""
reqver=""
init_dckr_vol="true"
package_install=""
package_download=""
skip_version_check="false"
# Parse command line arguments to determine is specific runtime version
# needs to be installed, and or to skip docker volume initialization.
while [ "${1}" != "" ]; do
   case ${1} in
      -v|--version )
          shift
          reqver="${1}"
          shift
          ;;
      -r|--dfrt-image )
          shift
          DF_RUNTIME_IMAGE="${1}"
          shift
          ;;
      -n|--no-docker-volume )
          shift
          init_dckr_vol="false"
          ;;
      -p|--no-package-install )
          shift
          package_install="false"
          ;;
      --skip-package-download )
          shift
          package_download="false"
          ;;
      --no-version-check )
          shift
          skip_version_check="true"
          ;;
      --verbose )
          shift
          set -x
          ;;
      * )
          invalidparam "${1}"
          exit 1
    esac
done

if [ "$skip_version_check" = "false" ]; then
	if [ "$(check_if_old_runtoken_format)" = "1" ]; then
		set_recommended_version "3.3.0-2152" "3.3.1-2199" "3.3.1-2199"
	else
		# token >= 3.3.2
		access_token="$(get_access_token)"
		validate_portal_connection "$access_token"
		# refresh access token again just to be safe
		access_token="$(get_access_token)"
		min_rec_vers=$(get_recommended_versions "$access_token")
		if [ "$min_rec_vers" != "" ]; then
			min_ver=${min_rec_vers% *}
			rec_ver=${min_rec_vers#* }

			if [ "$(dfver_comp "$rec_ver" "$min_ver")" = "-1" ]; then
				echo "Error: received recommended version \"$rec_ver\" which is less than minimum" \
				"supported version \"$min_ver\" from portal." >&2
				exit 1
			fi
			set_recommended_version "$min_ver" "$rec_ver"
		else
			# 3.3.2 portal
			set_recommended_version "3.3.2-2257" "3.3.2-2273" "3.3.2-2273"
		fi
	fi
fi

if [ "$package_install" = "false" ] ; then
  if [ -f /opt/deepfactor/bin/portalctl ]; then
    echo "Error: --no-package-install not supported on deepfactor-portal" >&2 && false
  fi
  command -v docker >/dev/null ||
	(echo "Error: --no-package-install requires docker" >&2 && false)
fi

case "${OSSTR}" in
 "Darwin")
	#
	# cleanup old install. Remove the file content but leave the dirs
	# intact. This is because Docker Desktop will likely have open file
	# handles to the various volume mountpoints, and we don't want to
	# make the user restart docker.
	#
	${sudo} rm -f /usr/local/bin/dfctl
	${sudo}	rm -f /usr/local/share/man/man8/dfctl.8
	${sudo} rm -rf /opt/deepfactor/bin/*
	${sudo} rm -rf /opt/deepfactor/glibc/*
	${sudo} rm -rf /opt/deepfactor/musl/*
	${sudo} rm -rf /opt/deepfactor/etc/*
	${sudo} rm -rf /opt/deepfactor/manifest/*

	${sudo} mkdir -p /opt/deepfactor
	cd /opt/deepfactor
	echo "Retrieving Deepfactor runtime for macOS ${reqver}"
	if [ ! "$package_download" = "false" ]; then
	  ${sudo} curl -LO https://repo.deepfactor.io/dfctl-darwin-${reqver}.tgz
	fi
	${sudo} cat dfctl-darwin-${reqver}.tgz | ${sudo} tar -zxvpf -
	${sudo} rm dfctl-darwin-${reqver}.tgz
	${sudo} chmod +x /opt/deepfactor/bin/dfscan
	${sudo} chmod +x /opt/deepfactor/bin/dfctl
	${sudo} ln -s /opt/deepfactor/bin/dfctl /usr/local/bin/dfctl
	${sudo} mkdir -p /usr/local/share/man/man8
	${sudo} ln -s /opt/deepfactor/bin/dfctl.8 /usr/local/share/man/man8
	${sudo} mkdir -p /opt/deepfactor/manifest
	${sudo} mkdir -p /opt/deepfactor/glibc
	${sudo} mkdir -p /opt/deepfactor/musl
	${sudo} chmod 777 /opt/deepfactor/glibc
	${sudo} chmod 777 /opt/deepfactor/musl
	${sudo} chmod 777 /opt/deepfactor/manifest
	#
	# docker setup will write into /opt/deepfactor/bin, this needs to
	# temporarily be 777
	#
	${sudo} chmod 777 /opt/deepfactor/bin
	if [ ! -f /usr/local/bin/docker ] ; then
		echo "Installation complete, but docker was not found."
		echo "If you want to use 'dfctl run --docker-run', install"
		echo "Docker Desktop for macOS and re-run this installation script."
		exit 0
	else
		echo "Package installation complete. The Deepfactor runtime"
		echo "docker container will now be provisioned."
		echo
		echo "On macOS platforms, this requires you to add the following"
		echo "three paths to the Docker Desktop 'Virtual file shares' list:"
		echo
		echo "/opt/deepfactor/bin"
		echo "/opt/deepfactor/glibc"
		echo "/opt/deepfactor/musl"
		echo
		echo "This cannot be done automatically from this script. Please"
		echo "launch Docker desktop, and add these three paths under:"
		echo
		echo "Settings (Gear icon)->Resources->Virtual file shares"
		echo
		echo "*NOTE* If you are reinstalling, you must restart Docker"
		echo "       engine before continuing."
		echo
		echo "Press enter when you have done this and are ready to proceed."
		read xx
	fi
 ;;
 "sles"|"opensuse-leap"|"opensuse")
  if ! non_pkg_install "glibc"; then
	curl -LO https://repo.deepfactor.io/repo/yum/x86_64/deepfactor-runtime-latest.rpm
	if [ ! -f /usr/bin/dfctl ] ; then
		${sudo} rpm --import https://repo.deepfactor.io/repo/yum/keys/D5DC8225.asc
		${sudo} rpm -ih deepfactor-runtime-latest.rpm
	else
		${sudo} rpm -Uvh deepfactor-runtime-latest.rpm
	fi
	rm -f deepfactor-runtime-latest.rpm
  fi
 ;;
 "centos"|"fedora"|"amzn"|"rhel"|"rocky"|"ol" )
  if ! non_pkg_install "glibc"; then
	ver_str=$(get_pkgver_str "centos"  ${reqver})
	if [ ! -f /usr/bin/dfctl ] ; then
		if [ ! -f /usr/bin/yum ] ; then
			echo "Error: yum must be installed on RPM-based platforms"
			exit 1
		fi
		if [ ! -f /usr/bin/curl ] ; then
			${sudo} yum install -y curl
		fi
		if [ ! -f /etc/yum.repos.d/deepfactor.repo ] ; then
			cd /etc/yum.repos.d && ${sudo} curl -LO https://repo.deepfactor.io/repo/yum/deepfactor.repo
		fi
		${sudo} rpm --import https://repo.deepfactor.io/repo/yum/keys/D5DC8225.asc
		${sudo} yum install -y deepfactor-runtime${ver_str}
	else
		${sudo} yum upgrade -y deepfactor-runtime${ver_str}
	fi
  fi
 ;;
 "ubuntu"|"debian"|"linuxmint"|"pop"|"kali" )
  if ! non_pkg_install "glibc"; then
	ver_str=$(get_pkgver_str "debian"  ${reqver})
	if [ ! -f /usr/bin/dfctl ] ; then
		${sudo} apt update ; ${sudo} apt install -y curl gnupg
		echo "deb https://repo.deepfactor.io/repo/deb/ ./" | ${sudo} tee /etc/apt/sources.list.d/deepfactor.list
		curl https://repo.deepfactor.io/repo/keys/D5DC8225.asc | ${sudo} apt-key add -
	fi
	${sudo} apt update ; ${sudo} apt install -y deepfactor-runtime${ver_str}
  fi
 ;;
 "alpine" )
  if ! non_pkg_install "musl"; then
	ver_str=$(get_pkgver_str "alpine"  ${reqver})
	# We do not use sudo for alpine. Two reasons for it.
	# 1: Alpine being continer distro, this script should run as root
	#    inside container image.
	# 2: For app images build to run with non-root users, the install
	#    still happens in image which should allow root user.
	if [ ! -f /usr/bin/dfctl ] ; then
		if [ ! -f /etc/apk/keys/dfbuild@deepfactor.io-5f35ef3a.rsa.pub ] ; then
			cd /etc/apk/keys && wget https://repo.deepfactor.io/repo/alpine/keys/dfbuild@deepfactor.io-5f35ef3a.rsa.pub
			echo "https://repo.deepfactor.io/repo/alpine" >> /etc/apk/repositories
		fi
		apk add deepfactor-runtime${ver_str}
	else
		apk update && apk upgrade deepfactor-runtime${ver_str}
	fi
  fi
 ;;
 * )
	echo "Distro ${DISTRO} not supported"
	exit 1
 ;;
esac

# If user requested to skip docker volume initialization,
# we exit here with status 0.
if [ ${init_dckr_vol} = "false" ] ; then
	exit 0
fi

if [ ! "$(docker --version | grep podman)" = "" ] ; then
	podman_mount_type="type=volume,"
fi

# use /bin/echo if '-e' needed
if command -v docker > /dev/null ; then
	# we could docker version -f '{{ .Client.Version }}', but podman versions will be different
	if [ "$(docker run --help | grep -e '--mount')" = "" ]; then
		/bin/echo -e "Error, docker does not appear to support '--mount'\n" \
		  "\tPlease install docker version 17.06 or newer and re-run this script again.\n"

		[ "${OSSTR}" = "Darwin" ] && ${sudo} chmod 755 /opt/deepfactor/bin

		exit 1
	fi
	echo "Creating DF Runtime Volume..."
	echo "Initializing DF Runtime Volume..."
	if [ "$package_install" = "false" ]; then
		reqver=""
	elif [ -n "${reqver}" ] ; then
		reqver=":${reqver}"
	else
		reqver=":$(dfctl version | awk '{print $3}' | tr -d '"')"
	fi
	# always update :latest or :reqver tag
	${sudo} docker pull --platform linux/amd64 "${DF_RUNTIME_IMAGE}${reqver}" || \
	  (echo "Error, Initializing DF Runtime Volume failed" && false)

	if [ ! "$(${sudo} docker volume ls | grep df-runtime)" = "" ] ; then
		echo "Removing previous DF Runtime Volume..."
		# note: podman has volumes per user
		${sudo} docker volume rm df-runtime || \
		  (/bin/echo -e "Error, unable to remove df-runtime volume.\n" \
		  "\tPlease remove containers and perform install again." && false)
	fi

	# copy /opt/deepfactor to df-runtime volume
	# create soft links to future bind mount locations in /opt/deepfactor-init
	${sudo} docker run --platform linux/amd64 --rm --mount ${podman_mount_type}source=df-runtime,destination=/opt/deepfactor \
	  "${DF_RUNTIME_IMAGE}${reqver}" sh -c 'mkdir -p /opt/deepfactor/manifest
	  cp /bin/busybox.static /opt/deepfactor/busybox.static
	  ln -s /opt/deepfactor-init/lib/libdf.so /opt/deepfactor/lib/libdf.so
	  ln -s /opt/deepfactor-init/manifest/df-manifest.json /opt/deepfactor/manifest/df-manifest.json
	  ' || \
	  (echo "Error, Initializing DF Runtime Volume failed" && false)
	# install df-get-entrypoint.sh
	${sudo} docker run --platform linux/amd64 --user root --rm -v /opt/deepfactor/bin:/host-df-bin ${DF_RUNTIME_IMAGE}${reqver} \
	  sh -c 'cp /opt/deepfactor/bin/df-get-entrypoint.sh /host-df-bin/df-get-entrypoint.sh' || \
	  (echo 'Warning, unable to copy df-get-entrypoint.sh for Dockerfile.df build-arg DF_IMAGE_ENTRYPOINT support' && false)

	[ "${OSSTR}" = "Darwin" ] && ${sudo} chmod 755 /opt/deepfactor/bin
else
	/bin/echo -e "Warning: docker not found.\n" \
		"\tUse of dfctl with --docker-run will produce an error.\n" \
		"\tPlease re-run this script again after installing docker to resolve.\n"
fi

