Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ on:
permissions: read-all

env:
GO_VERSION: '1.26.4'
GO_VERSION: '1.26.5'

jobs:
grep-gates:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
permissions: read-all

env:
GO_VERSION: '1.26.4'
GO_VERSION: '1.26.5'

jobs:
analyze:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/govulncheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
permissions: read-all

env:
GO_VERSION: '1.26.4'
GO_VERSION: '1.26.5'

jobs:
govulncheck:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
workflow_dispatch: {}

env:
GO_VERSION: '1.26.4'
GO_VERSION: '1.26.5'

jobs:
release:
Expand Down
2 changes: 1 addition & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# golangci-lint v2 — Go 1.26.4, module github.com/eclipse-iofog/iofogctl
# golangci-lint v2 — Go 1.26.5, module github.com/eclipse-iofog/iofogctl
#
# Layers:
# 1. edgelet/.golangci.yaml parity (govet, revive, staticcheck, errcheck, misspell, errorlint)
Expand Down
46 changes: 45 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,51 @@ All notable changes to potctl / iofogctl are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.8.0-rc.1] — June 2026
## [v3.8.1] — July 2026

Stable v3.8 patch release. Bumps SDK, operator, and edgelet pins; adds fog node OTA semver targeting and hardens edgelet redeploy/containerd orchestration.

### Added

- `upgrade agent` / `rollback agent --semver` for targeted fog node version OTA via SDK `UpgradeNode` / `RollbackNode`
- ConfigMap `useVault` in deploy, describe, and `get configmaps`
- SSH keep-alive and streamed output for long-running remote edgelet installs
- `version --ecn`: NATS and debugger component image lines

### Changed

- Bump Go to **1.26.5**; **iofog-go-sdk** and **iofog-operator** to **v3.8.1**
- ConfigMap `immutable` is optional in YAML; updates preserve existing `immutable` / `useVault` when omitted
- Edgelet install redeploy: detect active engine and installed version; defer and deduplicate `edgelet-containerd` restarts (WASM + OTA)
- Edgelet readiness scripts: case-insensitive daemon status parsing and embedded-engine `runtime.engineReady` gate
- Offline/airgap image transfer: shared container-engine handling via airgap package

### Fixed

- Redundant `edgelet-containerd` restart on redeploy/OTA when WASM install already restarted the engine
- ConfigMap PATCH semantics when `immutable` or `useVault` are not set in deploy YAML

### Security

- Documented govulncheck exception **GO-2026-5932** (`golang.org/x/crypto/openpgp` via `go.podman.io/image/v5` image signature handling) until upstream migrates off the deprecated package; see `SECURITY.md`.

### Known limitations

- **GO-2026-5932**: CLI builds use `containers_image_openpgp` for cgo-free release binaries; `golang.org/x/crypto/openpgp` remains on the call path for airgap/offline image copy with no upstream fix available.

### Component pairing

| Component | Pin |
|-----------|-----|
| CLI | `v3.8.1` |
| operator | `3.8.1` |
| controller | `3.8.1` |
| router | `3.8.1` |
| nats | `2.14.3-1` |
| edgelet binary | `v1.0.1` |
| edgelet image | `ghcr.io/<registry>/edgelet:1.0.1` |

## [v3.8.0] — June 2026


First greenfield v3.8 release candidate. Dual-flavor build (`potctl` / `iofogctl`) from a single codebase; no in-place upgrade from potctl- or v3.7.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![CLI CI](https://github.com/eclipse-iofog/iofogctl/actions/workflows/ci.yml/badge.svg)](https://github.com/eclipse-iofog/iofogctl/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/eclipse-iofog/iofogctl?include_prereleases)](https://github.com/eclipse-iofog/iofogctl/releases)
[![Go](https://img.shields.io/badge/Go-1.26.4-blue.svg)](https://go.dev/)
[![Go](https://img.shields.io/badge/Go-1.26.5-blue.svg)](https://go.dev/)
[![License](https://img.shields.io/badge/License-EPL--2.0-blue.svg)](LICENSE)
[![govulncheck](https://github.com/eclipse-iofog/iofogctl/actions/workflows/govulncheck.yml/badge.svg)](https://github.com/eclipse-iofog/iofogctl/actions/workflows/govulncheck.yml)
[![CodeQL](https://github.com/eclipse-iofog/iofogctl/actions/workflows/codeql.yml/badge.svg)](https://github.com/eclipse-iofog/iofogctl/actions/workflows/codeql.yml)
Expand All @@ -18,7 +18,7 @@ Upstream: [eclipse-iofog/iofogctl](https://github.com/eclipse-iofog/iofogctl) ·

**iofogctl** and **potctl** are dual-flavor CLIs for installing, configuring, and operating ioFog [Edge Compute Networks](https://iofog.org/docs/2/getting-started/core-concepts.html) (ECNs). v3.8 is a greenfield release: configuration lives under `~/.iofog/v3`, and there is no in-place upgrade path from legacy potctl- or v3.7 deployments.

Release binaries ship for **linux** (amd64, arm64, armv6, armv7), **macOS** (amd64, arm64), and **Windows** (amd64). Built with **Go 1.26.4** (see `go.mod`).
Release binaries ship for **linux** (amd64, arm64, armv6, armv7), **macOS** (amd64, arm64), and **Windows** (amd64). Built with **Go 1.26.5** (see `go.mod`).

## Install — iofogctl

Expand Down Expand Up @@ -90,7 +90,7 @@ Shell autocompletion: `iofogctl autocomplete bash` (or `zsh`), then follow the p

## Build from source

Requires Go **1.26.4+** (matches the Go badge and `go.mod`). Build outside `$GOPATH` (Go modules):
Requires Go **1.26.5+** (matches the Go badge and `go.mod`). Build outside `$GOPATH` (Go modules):

```bash
make FLAVOR=iofog build # iofogctl → bin/iofogctl
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Build, test, goreleaser, and govulncheck share the same Go build tags via `GOTAG

| GO ID | CVE | Component | Rationale | Fix timeline |
|-------|-----|-----------|-----------|--------------|
| *(none)* | | | | |
| GO-2026-5932 | — | `golang.org/x/crypto/openpgp` via `go.podman.io/image/v5` | Required by `containers_image_openpgp` build tag for cgo-free cross-platform builds (macOS, Windows, CI). Used for container image signature parsing in airgap/offline flows. Upstream `go.podman.io/image/v5` v5.40.0 explicitly retains deprecated openpgp; no patched version exists (`Fixed in: N/A`). | Remove when `go.podman.io/image` migrates to a maintained fork (e.g. `github.com/ProtonMail/go-crypto/openpgp`). |

No documented exceptions at launch. `make vulncheck` must pass with zero findings affecting CLI call paths.
`make vulncheck` must pass with zero undocumented findings affecting CLI call paths.

## Exception policy

Expand Down
9 changes: 7 additions & 2 deletions assets/edgelet/scripts/configure_container_edgelet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ wait_edgelet_api_running() {
_iter=$((_iter + 1))
continue
fi
if echo "$_out" | grep -q 'edgeletDaemon: RUNNING'; then
if echo "$_out" | grep -qi 'LOCAL_API_STARTING\|Local API is starting'; then
sleep 1
_iter=$((_iter + 1))
continue
fi
if echo "$_out" | grep -qi 'edgeletDaemon:[[:space:]]*RUNNING\|edgeletDaemon:[[:space:]]*running'; then
return 0
fi
if echo "$_out" | grep -q 'runtime.agentPhase: running'; then
if echo "$_out" | grep -qi 'runtime.agentPhase:[[:space:]]*running'; then
return 0
fi
sleep 1
Expand Down
4 changes: 4 additions & 0 deletions assets/edgelet/scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ if [ "$ACTION" = "upgrade" ]; then
[ "$AIRGAP" = true ] && _method="upgrade-airgap"
write_install_receipt "$EDGELET_VERSION" "$OS" "$ARCH" "$CONTAINER_ENGINE" "$(compute_source_url)" "$_sha" "$_method"
"$SCRIPT_DIR/bundled.sh" || true
if [ "$SKIP_START" = true ]; then
info "Skipping daemon start (--skip-start); use start_edgelet.sh"
exit 0
fi
_run_post_install
info "Upgrade to ${EDGELET_VERSION} complete."
exit 0
Expand Down
11 changes: 9 additions & 2 deletions assets/edgelet/scripts/install_init_units.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,18 @@ Documentation=https://github.com/eclipse-iofog/edgelet
Before=edgelet.service
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
# Intentionally NOT PartOf=edgelet.service: control restart/stop must not
# stop the data plane (Plan 11 attach-only). Full teardown: stop both units.

[Service]
Type=simple
ExecStartPre=/bin/sh -c 'mountpoint -q /sys/fs/bpf || mount -t bpf bpf /sys/fs/bpf 2>/dev/null || true'
ExecStart=/usr/local/bin/edgelet runtime-bootstrap
ExecStopPost=-/usr/local/bin/edgelet runtime reap-orphans
Restart=always
RestartSec=2s
RestartSec=5s
# Data-plane stop: drain MS via runtime-bootstrap SIGTERM handler + shutdownGracePeriodSeconds
TimeoutStopSec=120s
KillMode=process
Expand Down Expand Up @@ -247,7 +250,10 @@ name="edgelet-containerd"
description="Edgelet embedded containerd (data plane)"
command="/usr/local/bin/edgelet"
command_args="runtime-bootstrap"
command_background=true
supervisor="supervise-daemon"
respawn_delay=5
respawn_max=5
respawn_period=300
command_user="root"
pidfile="/run/${RC_SVCNAME}.pid"
output_log="/var/log/edgelet/containerd.log"
Expand Down Expand Up @@ -309,6 +315,7 @@ stop() {
fi
fi
rm -f "${pidfile}" 2>/dev/null || true
/usr/local/bin/edgelet runtime reap-orphans || ewarn "orphan reap exited non-zero"
eend 0
}
EDGELET_OPENRC_EDGELET_CONTAINERD_INIT_EOF
Expand Down
37 changes: 7 additions & 30 deletions assets/edgelet/scripts/install_wasm_runtimes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set -e

SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
. "$SCRIPT_DIR/lib/common.sh"
. "$SCRIPT_DIR/lib/service.sh"

if [ "${EDGELET_WASM_INSTALL:-}" != "1" ]; then
exit 0
Expand Down Expand Up @@ -79,30 +80,6 @@ install_from_env() {
done
}

wait_edgelet_containerd_socket() {
_timeout="${EDGELET_ATTACH_WAIT_SEC:-120}"
_elapsed=0
_sock="/run/edgelet/containerd.sock"
while [ "$_elapsed" -lt "$_timeout" ]; do
if [ -S "$_sock" ] || [ -S /var/run/edgelet/containerd.sock ]; then
[ -S "$_sock" ] || _sock="/var/run/edgelet/containerd.sock"
_ctr=""
if [ -x /var/lib/edgelet/data/current/bin/ctr ]; then
_ctr=/var/lib/edgelet/data/current/bin/ctr
elif command -v ctr >/dev/null 2>&1; then
_ctr=ctr
fi
if [ -z "$_ctr" ] || "$_ctr" --address "$_sock" version >/dev/null 2>&1; then
return 0
fi
fi
sleep 2
_elapsed=$(( _elapsed + 2 ))
done
echo "ERROR: edgelet-containerd socket not ready after ${_timeout}s" >&2
return 1
}

wait_docker_ready() {
_timeout="${EDGELET_DOCKER_WAIT_SEC:-120}"
_elapsed=0
Expand Down Expand Up @@ -132,15 +109,15 @@ restart_engine_if_needed() {
info "Skipping engine restart (fresh install or pre-start)"
return 0
fi
if [ "${EDGELET_WASM_DEFER_ENGINE_RESTART:-}" = "1" ]; then
info "Deferring engine restart to potctl (WASM shims installed)"
return 0
fi
case "$CONTAINER_ENGINE" in
edgelet)
info "Restarting edgelet-containerd after WASM shim update"
case "${INIT_SYSTEM:-unknown}" in
systemd) maybe_sudo systemctl restart edgelet-containerd ;;
openrc) maybe_sudo rc-service edgelet-containerd restart ;;
*) maybe_sudo systemctl restart edgelet-containerd 2>/dev/null || maybe_sudo service edgelet-containerd restart 2>/dev/null || true ;;
esac
wait_edgelet_containerd_socket
restart_edgelet_containerd_service
mark_containerd_restarted
;;
docker)
info "Restarting docker after WASM shim update"
Expand Down
Loading
Loading