Initial commit: EDGE Ignition gateway docker-compose build
Custom Dockerfile-based build for an Ignition Edge gateway with pre-baked base gwbk, module registration, and admin password provisioning, backed by MariaDB.
This commit is contained in:
74
gw-build/Dockerfile
Normal file
74
gw-build/Dockerfile
Normal file
@@ -0,0 +1,74 @@
|
||||
# Draw from environment (see .env file) for Ignition version/tag to source from
|
||||
ARG IGNITION_VERSION=${IGNITION_VERSION}
|
||||
FROM inductiveautomation/ignition:${IGNITION_VERSION} as prep
|
||||
|
||||
# Switch to root user for base image updates
|
||||
USER root
|
||||
|
||||
# Install some prerequisite packages
|
||||
RUN apt-get update && apt-get install -y wget jq zip unzip sqlite3
|
||||
|
||||
ARG SUPPLEMENTAL_AWSINJECTOR_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.24/AWS-Injector-signed.modl"
|
||||
ARG SUPPLEMENTAL_AWSINJECTOR_DOWNLOAD_SHA256="5aa6ab27829e6dfa67026358553a3e5e5d1b8ec689e5ffaae3cdaddbc9a3c252"
|
||||
ARG SUPPLEMENTAL_AZUREIOTINJECTOR_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.24/Azure-Injector-signed.modl"
|
||||
ARG SUPPLEMENTAL_AZUREIOTINJECTOR_DOWNLOAD_SHA256="90cee320d98fa9c1d8c0f3786586c8cd8dd256803e08ed3fcfc772acccdf3dbd"
|
||||
ARG SUPPLEMENTAL_GCPINJECTOR_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.24/Google-Cloud-Injector-signed.modl"
|
||||
ARG SUPPLEMENTAL_GCPINJECTOR_DOWNLOAD_SHA256="72078b25fb3c6853d85a76c212fb63a8c1277707666b492f67fb91ea333775b8"
|
||||
ARG SUPPLEMENTAL_MQTTTRANSMISSION_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.24/MQTT-Transmission-signed.modl"
|
||||
ARG SUPPLEMENTAL_MQTTTRANSMISSION_DOWNLOAD_SHA256="cb5d620513110c23b618989b56c5c2a67c45c36944a25d127586e8e303f0273a"
|
||||
ARG SUPPLEMENTAL_MQTTTRANSMISSIONNIGHTLY_DOWNLOAD_URL="https://ignition-modules-nightly.s3.amazonaws.com/Ignition8/MQTT-Transmission-signed.modl"
|
||||
ARG SUPPLEMENTAL_MQTTTRANSMISSIONNIGHTLY_DOWNLOAD_SHA256="notused"
|
||||
ARG SUPPLEMENTAL_MODULES
|
||||
|
||||
# Set working directory for this prep image and ensure that exits from sub-shells bubble up and report an error
|
||||
WORKDIR /root
|
||||
SHELL [ "/usr/bin/env", "-S", "bash", "-euo", "pipefail", "-O", "inherit_errexit", "-c" ]
|
||||
|
||||
# Retrieve all targeted modules and verify their integrity
|
||||
COPY --chmod=0755 retrieve-modules.sh .
|
||||
RUN if [ -n "${SUPPLEMENTAL_MODULES:-}" ]; then ./retrieve-modules.sh -m "${SUPPLEMENTAL_MODULES}"; fi
|
||||
|
||||
# Set CERTIFICATES/EULAS acceptance in gateway backup config db
|
||||
COPY *.gwbk ./
|
||||
COPY --chmod=0755 register-module.sh register-password.sh ./
|
||||
ARG GATEWAY_ADMIN_USERNAME="admin"
|
||||
ARG BASE_GWBK_NAME="base.gwbk"
|
||||
RUN --mount=type=secret,id=gateway-admin-password \
|
||||
unzip -q "${BASE_GWBK_NAME}" db_backup_sqlite.idb && \
|
||||
shopt -s nullglob; \
|
||||
for module in *.modl; do \
|
||||
./register-module.sh \
|
||||
-f "${module}" \
|
||||
-d db_backup_sqlite.idb; \
|
||||
done; \
|
||||
shopt -u nullglob && \
|
||||
./register-password.sh \
|
||||
-u "${GATEWAY_ADMIN_USERNAME}" \
|
||||
-f /run/secrets/gateway-admin-password \
|
||||
-d db_backup_sqlite.idb && \
|
||||
zip -q -f "${BASE_GWBK_NAME}" db_backup_sqlite.idb || \
|
||||
if [[ ${ZIP_EXIT_CODE:=$?} == 12 ]]; then \
|
||||
echo "No changes to internal database needed during module registration."; \
|
||||
else \
|
||||
echo "Unknown error (${ZIP_EXIT_CODE}) encountered during re-packaging of config db, exiting." && \
|
||||
exit ${ZIP_EXIT_CODE}; \
|
||||
fi
|
||||
|
||||
# Final Image
|
||||
FROM inductiveautomation/ignition:${IGNITION_VERSION} as final
|
||||
ARG BASE_GWBK_NAME="base.gwbk"
|
||||
ARG IGNITION_EDITION="edge"
|
||||
|
||||
# Embed modules and base gwbk from prep image as well as entrypoint shim
|
||||
COPY --from=prep --chown=ignition:ignition /root/*.modl ${IGNITION_INSTALL_LOCATION}/user-lib/modules/
|
||||
COPY --from=prep --chown=ignition:ignition /root/${BASE_GWBK_NAME} ${IGNITION_INSTALL_LOCATION}/base.gwbk
|
||||
COPY --chmod=0755 --chown=root:root docker-entrypoint-shim.sh /usr/local/bin/
|
||||
|
||||
# Return to ignition user
|
||||
USER ignition
|
||||
|
||||
# Set Ignition Edition default based on build argument
|
||||
ENV IGNITION_EDITION="${IGNITION_EDITION}"
|
||||
|
||||
# Target the entrypoint shim for any custom logic prior to gateway launch
|
||||
ENTRYPOINT [ "docker-entrypoint-shim.sh" ]
|
||||
BIN
gw-build/base.gwbk
Normal file
BIN
gw-build/base.gwbk
Normal file
Binary file not shown.
5
gw-build/docker-entrypoint-shim.sh
Normal file
5
gw-build/docker-entrypoint-shim.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Kick off the built-in entrypoint, with an in-built restore (-r <gwbk path>) directive
|
||||
exec docker-entrypoint.sh -r base.gwbk "$@"
|
||||
125
gw-build/register-module.sh
Executable file
125
gw-build/register-module.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit
|
||||
|
||||
###############################################################################
|
||||
# Performs auto-acceptance of EULA and import of certificates for third-party modules
|
||||
###############################################################################
|
||||
function main() {
|
||||
if [ ! -f "${MODULE_LOCATION}" ]; then
|
||||
echo ""
|
||||
return 0 # Silently exit if there is no /modules path
|
||||
elif [ ! -f "${DB_LOCATION}" ]; then
|
||||
echo "WARNING: ${DB_FILE} not found, skipping module registration"
|
||||
return 0
|
||||
fi
|
||||
|
||||
register_module
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Register the module with the target Config DB
|
||||
###############################################################################
|
||||
function register_module() {
|
||||
local SQLITE3=( sqlite3 "${DB_LOCATION}" )
|
||||
|
||||
# Tie into db
|
||||
local keytool module_sourcepath
|
||||
module_basename=$(basename "${MODULE_LOCATION}")
|
||||
module_sourcepath=${MODULE_LOCATION}
|
||||
keytool=$(which keytool)
|
||||
|
||||
echo "Processing Module: ${module_basename}"
|
||||
|
||||
# Populate CERTIFICATES table
|
||||
local cert_info subject_name thumbprint next_certificates_id thumbprint_already_exists
|
||||
cert_info=$( unzip -qq -c "${module_sourcepath}" certificates.p7b | $keytool -printcert -v | head -n 9 )
|
||||
thumbprint=$( echo "${cert_info}" | grep -A 2 "Certificate fingerprints" | grep SHA1 | cut -d : -f 2- | sed -e 's/\://g' | awk '{$1=$1;print tolower($0)}' )
|
||||
subject_name=$( echo "${cert_info}" | grep -m 1 -Po '^Owner: CN=\K(.+?)(?=, (OU|O|L|ST|C)=)' | sed -e 's/"//g' )
|
||||
echo " Thumbprint: ${thumbprint}"
|
||||
echo " Subject Name: ${subject_name}"
|
||||
next_certificates_id=$( "${SQLITE3[@]}" "SELECT COALESCE(MAX(CERTIFICATES_ID)+1,1) FROM CERTIFICATES" )
|
||||
thumbprint_already_exists=$( "${SQLITE3[@]}" "SELECT 1 FROM CERTIFICATES WHERE lower(hex(THUMBPRINT)) = '${thumbprint}'" )
|
||||
if [ "${thumbprint_already_exists}" != "1" ]; then
|
||||
echo " Accepting Certificate as CERTIFICATES_ID=${next_certificates_id}"
|
||||
"${SQLITE3[@]}" "INSERT INTO CERTIFICATES (CERTIFICATES_ID, THUMBPRINT, SUBJECTNAME) VALUES (${next_certificates_id}, x'${thumbprint}', '${subject_name}'); UPDATE SEQUENCES SET val=${next_certificates_id} WHERE name='CERTIFICATES_SEQ'"
|
||||
else
|
||||
echo " Thumbprint already found in CERTIFICATES table, skipping INSERT"
|
||||
fi
|
||||
|
||||
# Populate EULAS table
|
||||
local next_eulas_id license_crc32 module_id
|
||||
local -i module_id_check
|
||||
next_eulas_id=$( "${SQLITE3[@]}" "SELECT COALESCE(MAX(EULAS_ID)+1,1) FROM EULAS" )
|
||||
license_filename=$( unzip -qq -c "${module_sourcepath}" module.xml | grep -oP '(?<=<license>).*(?=</license)' )
|
||||
license_crc32=$( unzip -qq -c "${module_sourcepath}" "${license_filename}" | gzip -c | tail -c8 | od -t u4 -N 4 -A n | cut -c 2- )
|
||||
module_id=$( unzip -qq -c "${module_sourcepath}" module.xml | grep -oP '(?<=<id>).*(?=</id)' )
|
||||
module_id_check=$( "${SQLITE3[@]}" "SELECT CASE WHEN CRC=${license_crc32} THEN -1 ELSE 1 END FROM EULAS WHERE MODULEID='${module_id}'" )
|
||||
if (( module_id_check == 1 )); then
|
||||
echo " Removing previous EULAS entries for MODULEID='${module_id}'"
|
||||
"${SQLITE3[@]}" "DELETE FROM EULAS WHERE MODULEID='${module_id}'"
|
||||
fi
|
||||
if (( module_id_check >= 0 )); then
|
||||
echo " Accepting License on your behalf as EULAS_ID=${next_eulas_id}"
|
||||
"${SQLITE3[@]}" "INSERT INTO EULAS (EULAS_ID, MODULEID, CRC) VALUES (${next_eulas_id}, '${module_id}', ${license_crc32}); UPDATE SEQUENCES SET val=${next_eulas_id} WHERE name='EULAS_SEQ'"
|
||||
else
|
||||
echo " License EULA already found in EULAS table, skipping INSERT"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Outputs to stderr
|
||||
###############################################################################
|
||||
function debug() {
|
||||
# shellcheck disable=SC2236
|
||||
if [ ! -z ${verbose+x} ]; then
|
||||
>&2 echo " DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Print usage information
|
||||
###############################################################################
|
||||
function usage() {
|
||||
>&2 echo "Usage: $0 -f <path/to/module> -d <path/to/db>"
|
||||
}
|
||||
|
||||
# Argument Processing
|
||||
while getopts ":hvf:d:" opt; do
|
||||
case "$opt" in
|
||||
v)
|
||||
verbose=1
|
||||
;;
|
||||
f)
|
||||
MODULE_LOCATION="${OPTARG}"
|
||||
;;
|
||||
d)
|
||||
DB_LOCATION="${OPTARG}"
|
||||
DB_FILE=$(basename "${DB_LOCATION}")
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG}" >&2
|
||||
exit 1
|
||||
;;
|
||||
:)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG} requires an argument" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# shift positional args based on number consumed by getopts
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ -z "${MODULE_LOCATION:-}" ] || [ -z "${DB_LOCATION:-}" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
main
|
||||
88
gw-build/register-modules.sh
Normal file
88
gw-build/register-modules.sh
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit
|
||||
|
||||
###############################################################################
|
||||
# Retrieves third-party modules and verifies their checksums
|
||||
###############################################################################
|
||||
function main() {
|
||||
if [ -z "${SUPPLEMENTAL_MODULES}" ]; then
|
||||
return 0 # Silently exit if there are no supplemental modules to target
|
||||
fi
|
||||
|
||||
retrieve_modules
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Download the modules
|
||||
###############################################################################
|
||||
function retrieve_modules() {
|
||||
IFS=', ' read -r -a module_install_key_arr <<< "${SUPPLEMENTAL_MODULES}"
|
||||
for module_install_key in "${module_install_key_arr[@]}"; do
|
||||
download_url_env="SUPPLEMENTAL_${module_install_key^^}_DOWNLOAD_URL"
|
||||
download_sha256_env="SUPPLEMENTAL_${module_install_key^^}_DOWNLOAD_SHA256"
|
||||
if [ -n "${!download_url_env:-}" ] && [ -n "${!download_sha256_env:-}" ]; then
|
||||
download_basename=$(basename "${!download_url_env}")
|
||||
wget --ca-certificate=/etc/ssl/certs/ca-certificates.crt --referer https://inductiveautomation.com/* "${!download_url_env}" && \
|
||||
[[ "notused" == "${!download_sha256_env}" ]] || echo "${!download_sha256_env}" "${download_basename}" | sha256sum -c -
|
||||
else
|
||||
echo "Error finding specified module ${module_install_key} in build args, aborting..."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Outputs to stderr
|
||||
###############################################################################
|
||||
function debug() {
|
||||
# shellcheck disable=SC2236
|
||||
if [ ! -z ${verbose+x} ]; then
|
||||
>&2 echo " DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Print usage information
|
||||
###############################################################################
|
||||
function usage() {
|
||||
>&2 echo "Usage: $0 -m \"space-separated modules list\""
|
||||
>&2 echo " -m: space-separated list of module identifiers to download"
|
||||
}
|
||||
|
||||
# Argument Processing
|
||||
while getopts ":hvm:" opt; do
|
||||
case "$opt" in
|
||||
v)
|
||||
verbose=1
|
||||
;;
|
||||
m)
|
||||
SUPPLEMENTAL_MODULES="${OPTARG}"
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG}" >&2
|
||||
exit 1
|
||||
;;
|
||||
:)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG} requires an argument" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# shift positional args based on number consumed by getopts
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# exit on missing required args
|
||||
if [ -z "${SUPPLEMENTAL_MODULES:-}" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
main
|
||||
148
gw-build/register-password.sh
Executable file
148
gw-build/register-password.sh
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit
|
||||
|
||||
# Global variables
|
||||
declare -u AUTH_SALT
|
||||
|
||||
###############################################################################
|
||||
# Update an Ignition SQLite Configuration DB with a baseline username/password
|
||||
# ----------------------------------------------------------------------------
|
||||
# ref: https://gist.github.com/thirdgen88/c4257bd4c47b6cc7194d1f5e7cbd6444
|
||||
###############################################################################
|
||||
function main() {
|
||||
if [ ! -f "${SECRET_LOCATION}" ]; then
|
||||
echo ""
|
||||
return 0 # Silently exit if there is no secret at target path
|
||||
elif [ ! -f "${DB_LOCATION}" ]; then
|
||||
echo "WARNING: ${DB_FILE} not found, skipping password registration"
|
||||
return 0
|
||||
fi
|
||||
|
||||
register_password
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Updates the target Config DB with the target username and salted pw hash
|
||||
###############################################################################
|
||||
function register_password() {
|
||||
local SQLITE3=( sqlite3 "${DB_LOCATION}" ) password_hash password_input
|
||||
|
||||
echo "Registering Admin Password with Configuration DB"
|
||||
|
||||
# Generate Salted PW Hash
|
||||
password_input="$(< "${SECRET_LOCATION}")"
|
||||
if [[ "${password_input}" =~ ^\[[0-9A-F]{8,}][0-9a-f]{64}$ ]]; then
|
||||
debug "Password is already hashed"
|
||||
password_hash="${password_input}"
|
||||
else
|
||||
password_hash=$(generate_salted_hash "$(<"${SECRET_LOCATION}")")
|
||||
fi
|
||||
|
||||
# Update INTERNALUSERTABLE
|
||||
echo " Setting default admin user to USERNAME='${GATEWAY_ADMIN_USERNAME}' and PASSWORD='${password_hash}'"
|
||||
"${SQLITE3[@]}" "UPDATE INTERNALUSERTABLE SET USERNAME='${GATEWAY_ADMIN_USERNAME}', PASSWORD='${password_hash}' WHERE PROFILEID=1 AND USERID=1"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Processes password input and translates to salted hash
|
||||
###############################################################################
|
||||
function generate_salted_hash() {
|
||||
local auth_pwhash auth_pwsalthash auth_password password_input
|
||||
password_input="${1}"
|
||||
|
||||
debug "auth_salt is ${AUTH_SALT}"
|
||||
auth_pwhash=$(printf %s "${password_input}" | sha256sum - | cut -c -64)
|
||||
debug "auth_pwhash is ${auth_pwhash}"
|
||||
auth_pwsalthash=$(printf %s "${password_input}${AUTH_SALT}" | sha256sum - | cut -c -64)
|
||||
debug "auth_pwsalthash is ${auth_pwsalthash}"
|
||||
auth_password="[${AUTH_SALT}]${auth_pwsalthash}"
|
||||
|
||||
echo "${auth_password}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Outputs to stderr
|
||||
###############################################################################
|
||||
function debug() {
|
||||
# shellcheck disable=SC2236
|
||||
if [ ! -z ${verbose+x} ]; then
|
||||
>&2 echo " DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Print usage information
|
||||
###############################################################################
|
||||
function usage() {
|
||||
>&2 echo "Usage: $0 -u <string> -f <path/to/file> -d <path/to/db> [...]"
|
||||
>&2 echo " -u <string> Gateway Admin Username"
|
||||
>&2 echo " -f <path/to/file> Path to secret file containing password or salted hash"
|
||||
>&2 echo " -d <path/to/db> Path to Ignition Configuration DB"
|
||||
>&2 echo " -s <salt method> Salt method, either 'timestamp' or 'random' (default)"
|
||||
}
|
||||
|
||||
# Argument Processing
|
||||
while getopts ":hvu:f:d:s:" opt; do
|
||||
case "$opt" in
|
||||
v)
|
||||
verbose=1
|
||||
;;
|
||||
u)
|
||||
GATEWAY_ADMIN_USERNAME="${OPTARG}"
|
||||
;;
|
||||
f)
|
||||
SECRET_LOCATION="${OPTARG}"
|
||||
;;
|
||||
d)
|
||||
DB_LOCATION="${OPTARG}"
|
||||
DB_FILE=$(basename "${DB_LOCATION}")
|
||||
;;
|
||||
s)
|
||||
# Compute AUTH_SALT based on timestamp or random
|
||||
case "${OPTARG}" in
|
||||
timestamp)
|
||||
AUTH_SALT=$(date +%s | sha256sum | head -c 8)
|
||||
;;
|
||||
random)
|
||||
# no-op, default will be set below
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
echo "Invalid salt method: ${OPTARG}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG}" >&2
|
||||
exit 1
|
||||
;;
|
||||
:)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG} requires an argument" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# shift positional args based on number consumed by getopts
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# Check for required defaults
|
||||
if [ -z "${GATEWAY_ADMIN_USERNAME:-}" ] || [ -z "${SECRET_LOCATION:-}" ] || [ -z "${DB_LOCATION:-}" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# set defaults for unset optional args
|
||||
if [[ -z ${AUTH_SALT+x} ]]; then
|
||||
AUTH_SALT=$(od -An -v -t x1 -N 4 /dev/random | tr -d ' ')
|
||||
fi
|
||||
|
||||
main
|
||||
88
gw-build/retrieve-modules.sh
Executable file
88
gw-build/retrieve-modules.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit
|
||||
|
||||
###############################################################################
|
||||
# Retrieves third-party modules and verifies their checksums
|
||||
###############################################################################
|
||||
function main() {
|
||||
if [ -z "${SUPPLEMENTAL_MODULES}" ]; then
|
||||
return 0 # Silently exit if there are no supplemental modules to target
|
||||
fi
|
||||
|
||||
retrieve_modules
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Download the modules
|
||||
###############################################################################
|
||||
function retrieve_modules() {
|
||||
IFS=', ' read -r -a module_install_key_arr <<< "${SUPPLEMENTAL_MODULES}"
|
||||
for module_install_key in "${module_install_key_arr[@]}"; do
|
||||
download_url_env="SUPPLEMENTAL_${module_install_key^^}_DOWNLOAD_URL"
|
||||
download_sha256_env="SUPPLEMENTAL_${module_install_key^^}_DOWNLOAD_SHA256"
|
||||
if [ -n "${!download_url_env:-}" ] && [ -n "${!download_sha256_env:-}" ]; then
|
||||
download_basename=$(basename "${!download_url_env}")
|
||||
wget --ca-certificate=/etc/ssl/certs/ca-certificates.crt --referer https://inductiveautomation.com/* "${!download_url_env}" && \
|
||||
[[ "notused" == "${!download_sha256_env}" ]] || echo "${!download_sha256_env}" "${download_basename}" | sha256sum -c -
|
||||
else
|
||||
echo "Error finding specified module ${module_install_key} in build args, aborting..."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Outputs to stderr
|
||||
###############################################################################
|
||||
function debug() {
|
||||
# shellcheck disable=SC2236
|
||||
if [ ! -z ${verbose+x} ]; then
|
||||
>&2 echo " DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Print usage information
|
||||
###############################################################################
|
||||
function usage() {
|
||||
>&2 echo "Usage: $0 -m \"space-separated modules list\""
|
||||
>&2 echo " -m: space-separated list of module identifiers to download"
|
||||
}
|
||||
|
||||
# Argument Processing
|
||||
while getopts ":hvm:" opt; do
|
||||
case "$opt" in
|
||||
v)
|
||||
verbose=1
|
||||
;;
|
||||
m)
|
||||
SUPPLEMENTAL_MODULES="${OPTARG}"
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG}" >&2
|
||||
exit 1
|
||||
;;
|
||||
:)
|
||||
usage
|
||||
echo "Invalid option: -${OPTARG} requires an argument" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# shift positional args based on number consumed by getopts
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# exit on missing required args
|
||||
if [ -z "${SUPPLEMENTAL_MODULES:-}" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
main
|
||||
Reference in New Issue
Block a user