Skip to content

Commit

Permalink
Merge pull request #43 from thin-edge/feat-update-docker-container-ng
Browse files Browse the repository at this point in the history
feat: use tedge-container-plugin-ng
  • Loading branch information
reubenmiller authored Nov 28, 2024
2 parents af09a70 + 1b99d40 commit f86e668
Show file tree
Hide file tree
Showing 17 changed files with 245 additions and 895 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
# podman
- { target: tedge-container-bundle, name: "podman", image: debian-systemd-podman-cli }
- { target: tedge-container-bundle, name: "podman v5", image: "podman-v5" }
# - { target: tedge-container-bundle, name: "podman v4", image: "podman-v4" }
- { target: tedge-container-bundle, name: "podman v4", image: "podman-v4" }
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
11 changes: 1 addition & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,6 @@ RUN wget -O - https://thin-edge.io/install-services.sh | sh -s -- s6_overlay \
&& apk add --no-cache \
c8y-command-plugin \
tedge-apk-plugin \
# Note: Adding docker and compose adds ~75MB to the image
# FIXME: Either create another client, or enforce users to mount
# the docker cli and lib into the image
# apk add --no-cache libltdl
# -v /usr/bin/docker:/usr/bin/docker
docker-cli \
# Enable easier management of containers using docker compose
# without requiring the cli to be installed on the host (as read-only filesystems)
# might not have access to it
Expand All @@ -55,7 +49,7 @@ RUN wget -O - https://thin-edge.io/install-services.sh | sh -s -- s6_overlay \
# Set permissions of all files under /etc/tedge
# TODO: Can thin-edge.io set permissions during installation?
RUN chown -R tedge:tedge /etc/tedge \
&& echo "tedge ALL = (ALL) NOPASSWD:SETENV: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init, /usr/bin/tedgectl, /usr/bin/docker, /usr/bin/tedge-container, /bin/kill" >/etc/sudoers.d/tedge
&& echo "tedge ALL = (ALL) NOPASSWD:SETENV: /usr/bin/tedge, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /sbin/init, /usr/bin/tedgectl, /bin/kill, /usr/bin/tedge-container, /usr/bin/docker, /usr/bin/podman, /usr/bin/podman-remote, /usr/bin/podman-compose" >/etc/sudoers.d/tedge
# Custom init. scripts - e.g. write env variables data to files
COPY cont-init.d/* /etc/cont-init.d/

Expand All @@ -72,11 +66,8 @@ COPY files/tedge/c8y_RemoteAccessConnect /etc/tedge/operations/c8y/
COPY files/tedge/c8y_RemoteAccessConnect /etc/tedge/operations/c8y/
COPY files/tedge/launch-remote-access.sh /usr/bin/
# Self update workflow
COPY files/tedge/self.sh /etc/tedge/sm-plugins/self
COPY files/tedge/software_update.toml /etc/tedge/operations/
COPY files/tedge/self_update.toml /etc/tedge/operations/
COPY files/tedge/self_update.sh /usr/bin/
COPY files/tedge/container_run.tpl /usr/share/tedge/
# Container log_upload customer handler
COPY files/tedge/container-logs.sh /usr/bin/
COPY files/tedge/log_upload.toml /etc/tedge/operations/
Expand Down
29 changes: 28 additions & 1 deletion cont-init.d/50_configure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
set -e
echo "Current User: $(whoami)"

MAX_CONNECT_ATTEMPTS=${MAX_CONNECT_ATTEMPTS:-5}
MAX_RANDOM_WAIT=${MAX_RANDOM_WAIT:-15}

#
# device certificate loaders
#
Expand Down Expand Up @@ -79,12 +82,36 @@ if [ -n "$C8Y_DOMAIN" ] && [ -z "${TEDGE_C8Y_URL:-}" ]; then
tedge config set c8y.url "$C8Y_DOMAIN"
fi

random_sleep() {
VALUE=$(awk "BEGIN { srand(); print int(rand()*32768 % $MAX_RANDOM_WAIT) }")
echo "Sleeping ${VALUE}s" >&2
sleep "$VALUE"
}

#
# Connect the mappers (if they are configured and not already connected)
#
MAPPERS="c8y az aws"
for MAPPER in $MAPPERS; do
if tedge config get "${MAPPER}.url" 2>/dev/null; then
tedge connect "$MAPPER" ||:

# Try a few
attempt=1
while :; do
if tedge reconnect "$MAPPER"; then
echo "Successfully connected to $MAPPER" >&2
break
fi
if [ "$attempt" -ge "$MAX_CONNECT_ATTEMPTS" ]; then
echo "Couldn't connect to $MAPPER but continuing anyway" >&2
break
fi
attempt=$((attempt + 1))
random_sleep
done
fi
done

# Check which bridges are present
echo "--- mosquitto-conf directory ---" >&2
ls -l /etc/tedge/mosquitto-conf/
34 changes: 21 additions & 13 deletions files/tedge/container-logs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,42 +42,50 @@ while [ $# -gt 0 ]; do
shift
done

DOCKER_CMD=docker
if ! docker ps >/dev/null 2>&1; then
if command -V sudo >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
SUDO=
if command -V sudo >/dev/null 2>&1; then
SUDO="sudo"
fi
LOGS_CMD="$SUDO tedge-container tools container-logs"

CONTAINER_NAME=${CONTAINER_NAME:-}

if [ -z "$CONTAINER_NAME" ]; then
# Use the name of the container rather than the hostname as it human friendly
# and strip any leading slash (/)
CONTAINER_NAME=$($DOCKER_CMD inspect "$(hostname)" --format "{{.Name}}" | sed 's|^/||g')
# Lookup current container name so it can be included in the log header (though technically it isn't needed)
CONTAINER_NAME=$($SUDO tedge-container self list 2>/dev/null | head -n1 | cut -f1)
fi

TMP_LOG_DIR=$(mktemp -d)
# Ensure directory is always deleted afterwards
trap 'rm -rf -- "$TMP_LOG_DIR"' EXIT
TMP_FILE="${TMP_LOG_DIR}/${TYPE}_${CONTAINER_NAME}_$(date -Iseconds).log"
TMP_FILE="${TMP_LOG_DIR}/${TYPE}_${CONTAINER_NAME}_$(date +%Y-%m-%dT%H:%M:%S%z).log"

# Add log header to give information about the contents
{
echo "---------------- log parameters ----------------------"
echo "container: $CONTAINER_NAME"
echo "container: ${CONTAINER_NAME:-current_container}"
echo "dateFrom: $DATE_FROM"
echo "dateTo: $DATE_TO"
echo "maxLines: $MAX_LINES"
echo "command: $DOCKER_CMD logs --tail \"$MAX_LINES\" --since \"$DATE_FROM\" --until \"$DATE_TO\" \"$CONTAINER_NAME\""
echo "command: $LOGS_CMD --tail \"$MAX_LINES\" --since \"$DATE_FROM\" --until \"$DATE_TO\" \"$CONTAINER_NAME\""
echo "------------------------------------------------------"
echo
} > "$TMP_FILE"

# Write logs to file (stripping any ansci colour codes)
$DOCKER_CMD logs --tail "$MAX_LINES" --since "$DATE_FROM" --until "$DATE_TO" "$CONTAINER_NAME" 2>&1 \
# Write logs to file (stripping any ansi codes)
# Since we're in posix shell, we can't use -o pipefail, so instead we have to
# use a marker file which exists when an error was encountered as outlined here: https://www.shellcheck.net/wiki/SC3040
LOG_FAILED="$TMP_LOG_DIR/failed"
# shellcheck disable=SC2086
{ $LOGS_CMD --tail "$MAX_LINES" --since "$DATE_FROM" --until "$DATE_TO" $CONTAINER_NAME 2>&1 || echo > "$LOG_FAILED"; } \
| sed -e 's/\x1b\[[0-9;]*m//g' \
| tee -a "$TMP_FILE"

if [ -f "$LOG_FAILED" ]; then
echo "Failed to get container logs" >&2
exit 1
fi

echo "Uploading log file to $UPLOAD_URL" >&2

# Use mtls if configured
Expand Down
105 changes: 0 additions & 105 deletions files/tedge/container_run.tpl

This file was deleted.

73 changes: 13 additions & 60 deletions files/tedge/launch-remote-access.sh
Original file line number Diff line number Diff line change
@@ -1,70 +1,23 @@
#!/bin/sh
set -e

# Disable spawning from a container
REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN=${REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN:-0}
REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN="${REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN:-0}"

if ! command -V docker >/dev/null 2>&1 || [ ! -e /var/run/docker.sock ] || [ "$REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN" = 1 ]; then
SUDO=
if command -V sudo >/dev/null 2>&1; then
SUDO="sudo -E"
fi

has_container_api_access() {
$SUDO tedge-container self list >/dev/null 2>&1
}

if [ "$REMOTE_ACCESS_DISABLE_CONTAINER_SPAWN" = 1 ] || ! has_container_api_access; then
echo "Launching session as a child process"
c8y-remote-access-plugin "$@"
exit 0
fi

echo "Launching session in an independent container"
DOCKER_CMD=docker
if ! docker ps >/dev/null 2>&1; then
if command -V sudo >/dev/null 2>&1; then
DOCKER_CMD="sudo docker"
fi
fi

CONTAINER_NAME=${CONTAINER_NAME:-}
if [ -z "$CONTAINER_NAME" ]; then
CONTAINER_NAME=$(hostname)
fi
CONTAINER_ID=$($DOCKER_CMD inspect "$CONTAINER_NAME" --format "{{.Id}}")

# use the same image as the current container
IMAGE=$($DOCKER_CMD inspect "$CONTAINER_ID" --format "{{.Config.Image}}")

# Inherit docker flags
# Note: The single quotes around 'EOT' prevents variable expansion
TEMPLATE=$(
cat <<'EOT'
{{- with .HostConfig}}
{{- range $e := .ExtraHosts}}
--add-host {{printf "%q" $e}} \
{{- end}}
{{- end}}
{{- with .NetworkSettings -}}
{{- range $n, $conf := .Networks}}
{{- with $conf }}
--network {{printf "%q" $n}} \
{{- end}}
{{- end}}
{{- end}}
EOT
)
OPTIONS=$($DOCKER_CMD inspect "$CONTAINER_ID" --format "$TEMPLATE" | tr -d "\n\\\"")

TEDGE_C8Y_URL=$(tedge config get c8y.url)

# Add a host alias so the spawned container can reference the MQTT broker in the current container
MQTT_CLIENT_HOST=$($DOCKER_CMD inspect "$CONTAINER_ID" --format "{{.NetworkSettings.IPAddress}}" ||:)
if [ -z "$MQTT_CLIENT_HOST" ]; then
echo "Getting container ip address from hostname"
MQTT_CLIENT_HOST=$(getent hosts "$CONTAINER_NAME" | cut -d' ' -f1)
fi

echo "Running command"
set -x
# Launch an independent container to handle the remote access session
# so that it can do things like restarting this container
# shellcheck disable=SC2086
$DOCKER_CMD run --rm -d \
$OPTIONS \
--add-host tedge:"$MQTT_CLIENT_HOST" \
-e TEDGE_MQTT_CLIENT_HOST=tedge \
-e TEDGE_C8Y_URL="$TEDGE_C8Y_URL" \
"$IMAGE" \
c8y-remote-access-plugin --child "$@"
$SUDO tedge-container tools run-in-context --rm -- c8y-remote-access-plugin --child "$@"
exit 0
Loading

7 comments on commit f86e668

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m35.327424s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.043 s Operations
Service is up 0.143 s Operations
Get Logfile Request 2.351 s Operations
Get Configuration File 4.695 s Operations
Execute Shell Command 2.357 s Operations
Install application using docker compose 17.441 s Operations
Get Container Logs 2.363 s Operations
Get Container Logs without explicit container name 2.378 s Operations
Get Container Logs For Non-existent container 2.361 s Operations
Trigger self update via local command 24.953 s Self-Update
Self update should only update if there is a new image 20.413 s Self-Update
Self update using software update operation 103.032 s Self-Update
Rollback when trying to install a non-tedge based image 24.853 s Self-Update
Cloud Connection is Online 0.163 s Telemetry
Service status 0.272 s Telemetry
Sends measurements 2.465 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m28.687344999s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.050 s Operations
Service is up 0.207 s Operations
Get Logfile Request 2.396 s Operations
Get Configuration File 4.807 s Operations
Execute Shell Command 2.407 s Operations
Install application using docker compose 17.608 s Operations
Get Container Logs 2.405 s Operations
Get Container Logs without explicit container name 2.401 s Operations
Get Container Logs For Non-existent container 2.410 s Operations
Trigger self update via local command 24.683 s Self-Update
Self update should only update if there is a new image 20.275 s Self-Update
Self update using software update operation 100.243 s Self-Update
Rollback when trying to install a non-tedge based image 20.672 s Self-Update
Cloud Connection is Online 0.223 s Telemetry
Service status 0.304 s Telemetry
Sends measurements 2.557 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m37.448354999s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.047 s Operations
Service is up 0.148 s Operations
Get Logfile Request 2.358 s Operations
Get Configuration File 4.728 s Operations
Execute Shell Command 2.374 s Operations
Install application using docker compose 15.343 s Operations
Get Container Logs 2.373 s Operations
Get Container Logs without explicit container name 2.379 s Operations
Get Container Logs For Non-existent container 2.374 s Operations
Trigger self update via local command 23.560 s Self-Update
Self update should only update if there is a new image 26.524 s Self-Update
Self update using software update operation 100.890 s Self-Update
Rollback when trying to install a non-tedge based image 26.392 s Self-Update
Cloud Connection is Online 0.156 s Telemetry
Service status 0.259 s Telemetry
Sends measurements 2.503 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m56.869428s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.042 s Operations
Service is up 0.150 s Operations
Get Logfile Request 14.978 s Operations
Get Configuration File 4.684 s Operations
Execute Shell Command 2.362 s Operations
Install application using docker compose 17.436 s Operations
Get Container Logs 2.363 s Operations
Get Container Logs without explicit container name 2.362 s Operations
Get Container Logs For Non-existent container 2.360 s Operations
Trigger self update via local command 25.376 s Self-Update
Self update should only update if there is a new image 20.932 s Self-Update
Self update using software update operation 110.572 s Self-Update
Rollback when trying to install a non-tedge based image 25.330 s Self-Update
Cloud Connection is Online 0.159 s Telemetry
Service status 0.248 s Telemetry
Sends measurements 2.472 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m43.621145s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.045 s Operations
Service is up 0.154 s Operations
Get Logfile Request 2.346 s Operations
Get Configuration File 4.687 s Operations
Execute Shell Command 2.358 s Operations
Install application using docker compose 15.342 s Operations
Get Container Logs 2.364 s Operations
Get Container Logs without explicit container name 2.366 s Operations
Get Container Logs For Non-existent container 2.370 s Operations
Trigger self update via local command 25.485 s Self-Update
Self update should only update if there is a new image 21.328 s Self-Update
Self update using software update operation 107.366 s Self-Update
Rollback when trying to install a non-tedge based image 29.447 s Self-Update
Cloud Connection is Online 0.166 s Telemetry
Service status 0.262 s Telemetry
Sends measurements 2.490 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m50.562919s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.045 s Operations
Service is up 0.219 s Operations
Get Logfile Request 2.539 s Operations
Get Configuration File 5.068 s Operations
Execute Shell Command 2.545 s Operations
Install application using docker compose 18.261 s Operations
Get Container Logs 4.726 s Operations
Get Container Logs without explicit container name 4.736 s Operations
Get Container Logs For Non-existent container 2.554 s Operations
Trigger self update via local command 26.506 s Self-Update
Self update should only update if there is a new image 21.440 s Self-Update
Self update using software update operation 104.807 s Self-Update
Rollback when trying to install a non-tedge based image 28.625 s Self-Update
Cloud Connection is Online 0.273 s Telemetry
Service status 0.405 s Telemetry
Sends measurements 2.774 s Telemetry

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
16 0 1 16 100 3m50.741664s

Passed Tests

Name ⏱️ Duration Suite
Grace period to allow container to startup 5.042 s Operations
Service is up 0.245 s Operations
Get Logfile Request 4.744 s Operations
Get Configuration File 5.119 s Operations
Execute Shell Command 2.578 s Operations
Install application using docker compose 20.575 s Operations
Get Container Logs 2.582 s Operations
Get Container Logs without explicit container name 2.580 s Operations
Get Container Logs For Non-existent container 2.584 s Operations
Trigger self update via local command 26.321 s Self-Update
Self update should only update if there is a new image 21.479 s Self-Update
Self update using software update operation 105.094 s Self-Update
Rollback when trying to install a non-tedge based image 28.381 s Self-Update
Cloud Connection is Online 0.229 s Telemetry
Service status 0.390 s Telemetry
Sends measurements 2.760 s Telemetry

Please sign in to comment.