Skip to content

Commit 21d38a2

Browse files
authored
Merge pull request #5 from AXONE-IO/docker-integration
Commissioning configuration file
2 parents 01a524d + 64a28f9 commit 21d38a2

32 files changed

+1659
-221
lines changed

docker/.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Environment Variables automatically loaded by Docker Compose.
2+
# ref: https://docs.docker.com/compose/reference/envvars/
3+
COMPOSE_PROJECT_NAME=ignition-devops
4+
COMPOSE_PATH_SEPARATOR=:
5+
#COMPOSE_FILE=docker-compose-automated.yml
6+
COMPOSE_FILE=docker-compose.yml
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# ICC 2022 - Docker Basics Workshop - Part II, Docker Compose
2+
# ref: https://github.com/compose-spec/compose-spec/blob/master/spec.md
3+
---
4+
services:
5+
gateway:
6+
build:
7+
context: gw-build
8+
dockerfile: Dockerfile
9+
args:
10+
IGNITION_VERSION: ${IGNITION_VERSION:-8.1.26}
11+
SUPPLEMENTAL_MODULES: "git"
12+
GATEWAY_ADMIN_USERNAME: admin
13+
secrets:
14+
- gateway-admin-password
15+
hostname: gateway
16+
ports:
17+
- 9088:8088
18+
environment:
19+
- ACCEPT_IGNITION_EULA=Y
20+
#- GATEWAY_ADMIN_USERNAME=admin
21+
#- GATEWAY_ADMIN_PASSWORD_FILE=/run/secrets/gateway-admin-password
22+
- GATEWAY_GIT_USER_SECRET_FILE=/run/secrets/gateway-git-user-secret
23+
- IGNITION_EDITION=standard
24+
networks:
25+
- default
26+
volumes:
27+
- gateway_data:/usr/local/bin/ignition/data
28+
- ./gw-init/git.conf:/usr/local/bin/ignition/data/git.conf
29+
secrets:
30+
- gateway-git-user-secret
31+
- gateway-admin-password
32+
command: >
33+
-n Ignition-DevOps
34+
35+
networks:
36+
default:
37+
38+
secrets:
39+
gateway-git-user-secret:
40+
file: gw-secrets/GATEWAY_GIT_USER_SECRET
41+
gateway-admin-password:
42+
file: gw-secrets/GATEWAY_ADMIN_PASSWORD
43+
44+
volumes:
45+
gateway_data:

docker/docker-compose.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# ICC 2022 - Docker Basics Workshop - Part II, Docker Compose
2+
# ref: https://github.com/compose-spec/compose-spec/blob/master/spec.md
3+
---
4+
services:
5+
gateway:
6+
image: inductiveautomation/ignition:8.1.26
7+
hostname: gateway
8+
ports:
9+
- 9088:8088
10+
environment:
11+
- ACCEPT_IGNITION_EULA=Y
12+
- GATEWAY_ADMIN_USERNAME=admin
13+
- GATEWAY_ADMIN_PASSWORD_FILE=/run/secrets/gateway-admin-password
14+
- GATEWAY_GIT_USER_SECRET_FILE=/run/secrets/gateway-git-user-secret
15+
- IGNITION_EDITION=standard
16+
networks:
17+
- default
18+
volumes:
19+
- gateway_data:/usr/local/bin/ignition/data
20+
- ./modules/Git-1.0.1.modl:/usr/local/bin/ignition/user-lib/modules/Git-1.0.1.modl
21+
- ./gw-init/git.conf:/usr/local/bin/ignition/data/git.conf
22+
secrets:
23+
- gateway-git-user-secret
24+
- gateway-admin-password
25+
command: >
26+
-n Ignition-DevOps
27+
28+
networks:
29+
default:
30+
31+
secrets:
32+
gateway-git-user-secret:
33+
file: gw-secrets/GATEWAY_GIT_USER_SECRET
34+
gateway-admin-password:
35+
file: gw-secrets/GATEWAY_ADMIN_PASSWORD
36+
37+
volumes:
38+
gateway_data:

docker/gw-build/Dockerfile

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# syntax=docker/dockerfile:1.5
2+
ARG IGNITION_VERSION=${IGNITION_VERSION}
3+
FROM inductiveautomation/ignition:${IGNITION_VERSION} as prep
4+
5+
# Temporarily become root for system-level updates (required for 8.1.26+)
6+
USER root
7+
8+
# Install some prerequisite packages
9+
RUN apt-get update && apt-get install -y wget ca-certificates jq zip unzip sqlite3
10+
11+
ARG SUPPLEMENTAL_AZUREIOTINJECTOR_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.15/Azure-Injector-signed.modl"
12+
ARG SUPPLEMENTAL_AZUREIOTINJECTOR_DOWNLOAD_SHA256="e952629cebaad75825cf6e57c09c01f5f1772065a6e87cc0cda45fdca4b29f13"
13+
ARG SUPPLEMENTAL_MQTTTRANSMISSION_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.15/MQTT-Transmission-signed.modl"
14+
ARG SUPPLEMENTAL_MQTTTRANSMISSION_DOWNLOAD_SHA256="1e1e7428cba02dce6e579e6c82e4b8ad30d892438a7504aa0481eff7a5f87952"
15+
ARG SUPPLEMENTAL_MQTTTRANSMISSIONNIGHTLY_DOWNLOAD_URL="https://ignition-modules-nightly.s3.amazonaws.com/Ignition8/MQTT-Transmission-signed.modl"
16+
ARG SUPPLEMENTAL_MQTTTRANSMISSIONNIGHTLY_DOWNLOAD_SHA256="notused"
17+
ARG SUPPLEMENTAL_MQTTENGINE_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.15/MQTT-Engine-signed.modl"
18+
ARG SUPPLEMENTAL_MQTTENGINE_DOWNLOAD_SHA256="5693c22b391e6da31351f2bb9245ad65e96dff9d02c0a322cb70eb11a2fb86b6"
19+
ARG SUPPLEMENTAL_MQTTENGINENIGHTLY_DOWNLOAD_URL="https://ignition-modules-nightly.s3.amazonaws.com/Ignition8/MQTT-Engine-signed.modl"
20+
ARG SUPPLEMENTAL_MQTTENGINENIGHTLY_DOWNLOAD_SHA256="notused"
21+
ARG SUPPLEMENTAL_MQTTDISTRIBUTOR_DOWNLOAD_URL="https://files.inductiveautomation.com/third-party/cirrus-link/4.0.15/MQTT-Distributor-signed.modl"
22+
ARG SUPPLEMENTAL_MQTTDISTRIBUTOR_DOWNLOAD_SHA256="5c81be13a9f749899825a99a109502c1eb28be940d060301a1ddf9967d488f9e"
23+
ARG SUPPLEMENTAL_MQTTDISTRIBUTORNIGHTLY_DOWNLOAD_URL="https://ignition-modules-nightly.s3.amazonaws.com/Ignition8/MQTT-Distributor-signed.modl"
24+
ARG SUPPLEMENTAL_MQTTDISTRIBUTORNIGHTLY_DOWNLOAD_SHA256="notused"
25+
ARG SUPPLEMENTAL_GIT_DOWNLOAD_URL="https://www.axone-io.com/Files/Modules/GIT/1.0.1/doc/module/Git-1.0.1.modl"
26+
ARG SUPPLEMENTAL_GIT_DOWNLOAD_SHA256="notused"
27+
ARG SUPPLEMENTAL_MODULES
28+
29+
# Set working directory for this prep image and ensure that exits from sub-shells bubble up and report an error
30+
WORKDIR /root
31+
SHELL [ "/usr/bin/env", "-S", "bash", "-euo", "pipefail", "-O", "inherit_errexit", "-c" ]
32+
33+
# Retrieve all targeted modules and verify their integrity
34+
COPY --chmod=0755 retrieve-modules.sh .
35+
RUN ./retrieve-modules.sh \
36+
-m "${SUPPLEMENTAL_MODULES:-}"
37+
38+
# Set CERTIFICATES/EULAS acceptance in gateway backup config db
39+
COPY base.gwbk .
40+
COPY --chmod=0755 register-module.sh register-password.sh ./
41+
ARG GATEWAY_ADMIN_USERNAME="admin"
42+
RUN --mount=type=secret,id=gateway-admin-password \
43+
unzip -q base.gwbk db_backup_sqlite.idb && \
44+
shopt -s nullglob; \
45+
for module in *.modl; do \
46+
./register-module.sh \
47+
-f "${module}" \
48+
-d db_backup_sqlite.idb; \
49+
done; \
50+
shopt -u nullglob && \
51+
./register-password.sh \
52+
-u "${GATEWAY_ADMIN_USERNAME}" \
53+
-f /run/secrets/gateway-admin-password \
54+
-d db_backup_sqlite.idb && \
55+
zip -q -f base.gwbk db_backup_sqlite.idb || \
56+
if [[ ${ZIP_EXIT_CODE:=$?} == 12 ]]; then \
57+
echo "No changes to internal database needed during module registration."; \
58+
else \
59+
echo "Unknown error (${ZIP_EXIT_CODE}) encountered during re-packaging of config db, exiting." && \
60+
exit ${ZIP_EXIT_CODE}; \
61+
fi
62+
63+
# Final Image
64+
FROM inductiveautomation/ignition:${IGNITION_VERSION} as final
65+
66+
# Temporarily become root for system-level updates (required for 8.1.26+)
67+
USER root
68+
69+
# Add supplemental packages, such as git if needed/desired
70+
RUN apt-get update && \
71+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
72+
git && \
73+
rm -rf /var/lib/apt/lists/*
74+
75+
# Embed modules and base gwbk from prep image as well as entrypoint shim
76+
COPY --from=prep --chown=ignition:ignition /root/*.modl ${IGNITION_INSTALL_LOCATION}/user-lib/modules/
77+
COPY --from=prep --chown=ignition:ignition /root/base.gwbk ${IGNITION_INSTALL_LOCATION}/base.gwbk
78+
COPY --chmod=0755 --chown=root:root docker-entrypoint-shim.sh /usr/local/bin/
79+
80+
# Return to ignition user
81+
USER ignition
82+
83+
# Supplement other default environment variables
84+
ENV ACCEPT_IGNITION_EULA=Y \
85+
IGNITION_EDITION=standard \
86+
GATEWAY_MODULES_ENABLED=all
87+
88+
# Target the entrypoint shim for any custom logic prior to gateway launch
89+
ENTRYPOINT [ "docker-entrypoint-shim.sh" ]

docker/gw-build/base.gwbk

5.47 MB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
### add other custom logic here that will run at container launch
5+
6+
# Kick off the built-in entrypoint, with an in-built restore (-r <gwbk path>) directive
7+
exec docker-entrypoint.sh -r base.gwbk "$@"

docker/gw-build/register-module.sh

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
shopt -s inherit_errexit
4+
5+
###############################################################################
6+
# Performs auto-acceptance of EULA and import of certificates for third-party modules
7+
###############################################################################
8+
function main() {
9+
if [ ! -f "${MODULE_LOCATION}" ]; then
10+
echo ""
11+
return 0 # Silently exit if there is no /modules path
12+
elif [ ! -f "${DB_LOCATION}" ]; then
13+
echo "WARNING: ${DB_FILE} not found, skipping module registration"
14+
return 0
15+
fi
16+
17+
register_module
18+
}
19+
20+
###############################################################################
21+
# Register the module with the target Config DB
22+
###############################################################################
23+
function register_module() {
24+
local SQLITE3=( sqlite3 "${DB_LOCATION}" )
25+
26+
# Tie into db
27+
local keytool module_sourcepath
28+
module_basename=$(basename "${MODULE_LOCATION}")
29+
module_sourcepath=${MODULE_LOCATION}
30+
keytool=$(which keytool)
31+
32+
echo "Processing Module: ${module_basename}"
33+
34+
# Populate CERTIFICATES table
35+
local cert_info subject_name thumbprint next_certificates_id thumbprint_already_exists
36+
cert_info=$( unzip -qq -c "${module_sourcepath}" certificates.p7b | $keytool -printcert -v | head -n 9 )
37+
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)}' )
38+
subject_name=$( echo "${cert_info}" | grep -m 1 -Po '^Owner: CN=\K(.+)(?=, OU)' | sed -e 's/"//g' )
39+
echo " Thumbprint: ${thumbprint}"
40+
echo " Subject Name: ${subject_name}"
41+
next_certificates_id=$( "${SQLITE3[@]}" "SELECT COALESCE(MAX(CERTIFICATES_ID)+1,1) FROM CERTIFICATES" )
42+
thumbprint_already_exists=$( "${SQLITE3[@]}" "SELECT 1 FROM CERTIFICATES WHERE lower(hex(THUMBPRINT)) = '${thumbprint}'" )
43+
if [ "${thumbprint_already_exists}" != "1" ]; then
44+
echo " Accepting Certificate as CERTIFICATES_ID=${next_certificates_id}"
45+
"${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'"
46+
else
47+
echo " Thumbprint already found in CERTIFICATES table, skipping INSERT"
48+
fi
49+
50+
# Populate EULAS table
51+
local next_eulas_id license_crc32 module_id module_id_already_exists
52+
next_eulas_id=$( "${SQLITE3[@]}" "SELECT COALESCE(MAX(EULAS_ID)+1,1) FROM EULAS" )
53+
license_crc32=$( unzip -qq -c "${module_sourcepath}" license.html | gzip -c | tail -c8 | od -t u4 -N 4 -A n | cut -c 2- )
54+
module_id=$( unzip -qq -c "${module_sourcepath}" module.xml | grep -oP '(?<=<id>).*(?=</id)' )
55+
module_id_already_exists=$( "${SQLITE3[@]}" "SELECT 1 FROM EULAS WHERE MODULEID='${module_id}' AND CRC=${license_crc32}" )
56+
if [ "${module_id_already_exists}" != "1" ]; then
57+
echo " Accepting License on your behalf as EULAS_ID=${next_eulas_id}"
58+
"${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'"
59+
else
60+
echo " License EULA already found in EULAS table, skipping INSERT"
61+
fi
62+
}
63+
64+
###############################################################################
65+
# Outputs to stderr
66+
###############################################################################
67+
function debug() {
68+
# shellcheck disable=SC2236
69+
if [ ! -z ${verbose+x} ]; then
70+
>&2 echo " DEBUG: $*"
71+
fi
72+
}
73+
74+
###############################################################################
75+
# Print usage information
76+
###############################################################################
77+
function usage() {
78+
>&2 echo "Usage: $0 -f <path/to/module> -d <path/to/db>"
79+
}
80+
81+
# Argument Processing
82+
while getopts ":hvf:d:" opt; do
83+
case "$opt" in
84+
v)
85+
verbose=1
86+
;;
87+
f)
88+
MODULE_LOCATION="${OPTARG}"
89+
;;
90+
d)
91+
DB_LOCATION="${OPTARG}"
92+
DB_FILE=$(basename "${DB_LOCATION}")
93+
;;
94+
h)
95+
usage
96+
exit 0
97+
;;
98+
\?)
99+
usage
100+
echo "Invalid option: -${OPTARG}" >&2
101+
exit 1
102+
;;
103+
:)
104+
usage
105+
echo "Invalid option: -${OPTARG} requires an argument" >&2
106+
exit 1
107+
;;
108+
esac
109+
done
110+
111+
# shift positional args based on number consumed by getopts
112+
shift $((OPTIND-1))
113+
114+
if [ -z "${MODULE_LOCATION:-}" ] || [ -z "${DB_LOCATION:-}" ]; then
115+
usage
116+
exit 1
117+
fi
118+
119+
main

0 commit comments

Comments
 (0)