From 8460a61f993ccb9604de95fa681859fcf4afcee4 Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Thu, 11 Sep 2025 12:58:04 +1000 Subject: [PATCH 01/13] Enable multi architecture compatibility between Tentacle and Script pods --- docker/kubernetes-agent-tentacle/Dockerfile | 19 +++++-- .../bootstrapRunner/select-bootstrapRunner.sh | 50 +++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100755 docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh diff --git a/docker/kubernetes-agent-tentacle/Dockerfile b/docker/kubernetes-agent-tentacle/Dockerfile index e6d28f6fb..c599ce42c 100644 --- a/docker/kubernetes-agent-tentacle/Dockerfile +++ b/docker/kubernetes-agent-tentacle/Dockerfile @@ -9,8 +9,19 @@ ARG TARGETOS COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ WORKDIR /bootstrapRunner +# Create bin directory for multiple architectures +RUN mkdir -p bin + +# Build for multiple architectures # Note: the given ldflags remove debug symbols -RUN go build -ldflags "-s -w" -o "bin/bootstrapRunner" +RUN GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-amd64" \ + && GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm64" \ + && GOOS=linux GOARCH=386 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-386" \ + && GOOS=linux GOARCH=arm go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm" + +# Copy the architecture detection script from source and make it executable +COPY docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh bin/ +RUN chmod +x bin/select-bootstrapRunner.sh FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag @@ -24,8 +35,8 @@ ARG TARGETVARIANT EXPOSE 10933 COPY docker/kubernetes-agent-tentacle/scripts/* /scripts/ -COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/bootstrapRunner /bootstrapRunner -RUN chmod +x /scripts/*.sh +COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/* /bootstrapRunner/ +RUN chmod +x /scripts/*.sh && chmod +x /bootstrapRunner/* WORKDIR /tmp @@ -60,7 +71,7 @@ RUN chgrp -R 0 /opt /usr /.dotnet && \ RUN chgrp 0 /etc /etc/ssl/certs && \ chmod g=u /etc /etc/ssl/certs -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/select-bootstrapRunner.sh ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh new file mode 100755 index 000000000..3bdc0be44 --- /dev/null +++ b/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -eu + +# Architecture detection and bootstrap runner selection script +# This script automatically detects the runtime architecture and selects +# the appropriate bootstrapRunner binary for execution. + +# Detect the current architecture +ARCH=$(uname -m) +OS=$(uname -s | tr '[:upper:]' '[:lower:]') + +# Map architecture names to Go architecture naming +case "$ARCH" in + x86_64) + GO_ARCH="amd64" + ;; + aarch64|arm64) + GO_ARCH="arm64" + ;; + i386|i686) + GO_ARCH="386" + ;; + armv7l|armv6l) + GO_ARCH="arm" + ;; + *) + echo "Error: Unsupported architecture: $ARCH" >&2 + echo "Supported architectures: x86_64, aarch64, arm64, i386, i686, armv7l, armv6l" >&2 + exit 1 + ;; +esac + +# Construct binary name +BINARY_NAME="bootstrapRunner-${OS}-${GO_ARCH}" +BINARY_PATH="$(dirname "$0")/$BINARY_NAME" + +# Check if the binary exists +if [ ! -f "$BINARY_PATH" ]; then + echo "Error: Bootstrap runner binary not found for architecture ${OS}-${GO_ARCH}" >&2 + echo "Looking for: $BINARY_PATH" >&2 + echo "Available binaries:" >&2 + ls -1 "$(dirname "$0")"/bootstrapRunner-* 2>/dev/null || echo " No bootstrap binaries found" >&2 + exit 1 +fi + +# Make sure the binary is executable +chmod +x "$BINARY_PATH" + +# Execute the appropriate binary with all arguments passed through +exec "$BINARY_PATH" "$@" \ No newline at end of file From f228955159866e098c6a8f97c8a0bd4f376cc3ef Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Fri, 12 Sep 2025 13:56:11 +1000 Subject: [PATCH 02/13] Hard code path --- .../bootstrapRunner/select-bootstrapRunner.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh index 3bdc0be44..cbef9032d 100755 --- a/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh +++ b/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh @@ -32,14 +32,14 @@ esac # Construct binary name BINARY_NAME="bootstrapRunner-${OS}-${GO_ARCH}" -BINARY_PATH="$(dirname "$0")/$BINARY_NAME" +BINARY_PATH="/bootstrapRunner/$BINARY_NAME" # Check if the binary exists if [ ! -f "$BINARY_PATH" ]; then echo "Error: Bootstrap runner binary not found for architecture ${OS}-${GO_ARCH}" >&2 echo "Looking for: $BINARY_PATH" >&2 echo "Available binaries:" >&2 - ls -1 "$(dirname "$0")"/bootstrapRunner-* 2>/dev/null || echo " No bootstrap binaries found" >&2 + ls -1 "/bootstrapRunner"/bootstrapRunner-* 2>/dev/null || echo " No bootstrap binaries found" >&2 exit 1 fi From 64eac1a0a6be6bab3cc741ea81d9e71ca593006d Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Wed, 4 Mar 2026 15:39:39 +1100 Subject: [PATCH 03/13] Update the development Dockerfile for testing --- .../kubernetes-agent-tentacle/dev/Dockerfile | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 73fac5398..90dde00eb 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -9,8 +9,19 @@ ARG TARGETOS COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ WORKDIR /bootstrapRunner +# Create bin directory for multiple architectures +RUN mkdir -p bin + +# Build for multiple architectures # Note: the given ldflags remove debug symbols -RUN go build -ldflags "-s -w" -o "bin/bootstrapRunner" +RUN GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-amd64" \ + && GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm64" \ + && GOOS=linux GOARCH=386 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-386" \ + && GOOS=linux GOARCH=arm go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm" + +# Copy the architecture detection script from source and make it executable +COPY docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh bin/ +RUN chmod +x bin/select-bootstrapRunner.sh FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag @@ -28,8 +39,8 @@ EXPOSE 10933 EXPOSE 7777 COPY docker/kubernetes-agent-tentacle/scripts/* /scripts/ -COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/bootstrapRunner /bootstrapRunner -RUN chmod +x /scripts/*.sh +COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/* /bootstrapRunner/ +RUN chmod +x /scripts/*.sh && chmod +x /bootstrapRunner/* COPY docker/kubernetes-agent-tentacle/dev/scripts/* /dev-scripts/ RUN chmod +x /dev-scripts/*.sh @@ -54,7 +65,7 @@ RUN \ # We know this won't reduce the image size at all. It's just to make the filesystem a little tidier. RUN rm -rf /tmp/* -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/select-bootstrapRunner.sh ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" From 9b123254c5d587eff8fe318b2c1ba708901e6c95 Mon Sep 17 00:00:00 2001 From: Trent Mohay Date: Wed, 4 Mar 2026 22:16:31 +1100 Subject: [PATCH 04/13] maybe its ok --- docker/kubernetes-agent-tentacle/Dockerfile | 4 ++-- .../Kubernetes/KubernetesScriptPodCreator.cs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/Dockerfile b/docker/kubernetes-agent-tentacle/Dockerfile index 695c77882..1c2ab7dd0 100644 --- a/docker/kubernetes-agent-tentacle/Dockerfile +++ b/docker/kubernetes-agent-tentacle/Dockerfile @@ -43,7 +43,7 @@ EXPOSE 10933 COPY docker/kubernetes-agent-tentacle/scripts/* /scripts/ COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/* /bootstrapRunner/ -RUN chmod +x /scripts/*.sh && chmod +x /bootstrapRunner/* +RUN chmod +x /scripts/*.sh WORKDIR /tmp @@ -78,7 +78,7 @@ RUN chgrp -R 0 /opt /usr /.dotnet && \ RUN chgrp 0 /etc /etc/ssl/certs && \ chmod g=u /etc /etc/ssl/certs -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/select-bootstrapRunner.sh +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs index 193aee856..6916a1aab 100644 --- a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs +++ b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs @@ -179,8 +179,15 @@ async Task CreatePod(StartKubernetesScriptCommandV1 command, IScriptWorkspace wo LogVerboseToBothLogs($"Creating Kubernetes Pod '{podName}'.", tentacleScriptLog); - workspace.CopyFile(KubernetesConfig.BootstrapRunnerExecutablePath, "bootstrapRunner", true); - + + //TODO(tmm): Need to copy over ALL the bootstrap files and bootstrap run selector. + //need to determine whate files are available + foreach(var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutablePath)) + { + var baseName = Path.GetFileName(file); + workspace.CopyFile(file, baseName, true); + } + var scriptName = Path.GetFileName(workspace.BootstrapScriptFilePath); var workspacePath = Path.Combine("Work", workspace.ScriptTicket.TaskId); @@ -295,10 +302,10 @@ void LogVerboseToBothLogs(string message, InMemoryTentacleScriptLog tentacleScri protected async Task CreateScriptContainer(StartKubernetesScriptCommandV1 command, string podName, string scriptName, string homeDir, string workspacePath, string[]? scriptArguments, InMemoryTentacleScriptLog tentacleScriptLog, V1Container? containerSpec) { var spaceInformation = kubernetesPhysicalFileSystem.GetStorageInformation(); - + var commandString = string.Join(" ", new[] { - $"{homeDir}/Work/{command.ScriptTicket.TaskId}/bootstrapRunner", + $"{homeDir}/Work/{command.ScriptTicket.TaskId}/execute-bootstrapRunner.sh", Path.Combine(homeDir, workspacePath), Path.Combine(homeDir, workspacePath, scriptName) }.Concat(scriptArguments ?? Array.Empty()) From 51eb445e4f90751abd4b1017ee86943fd31a136b Mon Sep 17 00:00:00 2001 From: Trent Mohay Date: Wed, 4 Mar 2026 22:52:06 +1100 Subject: [PATCH 05/13] might work? --- docker/kubernetes-agent-tentacle/Dockerfile | 25 ++++++++++--------- ...apRunner.sh => execute-bootstrapRunner.sh} | 0 2 files changed, 13 insertions(+), 12 deletions(-) rename docker/kubernetes-agent-tentacle/bootstrapRunner/{select-bootstrapRunner.sh => execute-bootstrapRunner.sh} (100%) diff --git a/docker/kubernetes-agent-tentacle/Dockerfile b/docker/kubernetes-agent-tentacle/Dockerfile index 1c2ab7dd0..0a20c8372 100644 --- a/docker/kubernetes-agent-tentacle/Dockerfile +++ b/docker/kubernetes-agent-tentacle/Dockerfile @@ -6,23 +6,20 @@ FROM golang:1.22 as bootstrapRunnerBuilder ARG TARGETARCH ARG TARGETOS +ARG platforms="linux" +ARG architectures="amd64 arm64 386 arm" + COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ WORKDIR /bootstrapRunner # Create bin directory for multiple architectures RUN mkdir -p bin -# Build for multiple architectures -# Note: the given ldflags remove debug symbols -RUN GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-amd64" \ - && GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm64" \ - && GOOS=linux GOARCH=386 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-386" \ - && GOOS=linux GOARCH=arm go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm" - -# Copy the architecture detection script from source and make it executable -COPY docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh bin/ -RUN chmod +x bin/select-bootstrapRunner.sh - +RUN for platform in $platforms; do \ + Run for arch in $architectures; do \ + GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch" \ + done; \ +done; FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag @@ -45,6 +42,10 @@ COPY docker/kubernetes-agent-tentacle/scripts/* /scripts/ COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/* /bootstrapRunner/ RUN chmod +x /scripts/*.sh +# Copy the architecture detection script from source and make it executable +COPY docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh /bootstrapRunner/ +RUN chmod +x /bootstrapRunner/execute-bootstrapRunner.sh + WORKDIR /tmp # Install Tentacle @@ -78,7 +79,7 @@ RUN chgrp -R 0 /opt /usr /.dotnet && \ RUN chgrp 0 /etc /etc/ssl/certs && \ chmod g=u /etc /etc/ssl/certs -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/ ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh similarity index 100% rename from docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh rename to docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh From 963e490dc7a70f7de3be6bfdd9fc944480d17f40 Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Thu, 5 Mar 2026 09:17:26 +1100 Subject: [PATCH 06/13] review comments --- docker/kubernetes-agent-tentacle/Dockerfile | 8 ++++---- .../bootstrapRunner/execute-bootstrapRunner.sh | 2 -- docker/kubernetes-agent-tentacle/dev/Dockerfile | 9 ++++----- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/Dockerfile b/docker/kubernetes-agent-tentacle/Dockerfile index 0a20c8372..ccd0e02e5 100644 --- a/docker/kubernetes-agent-tentacle/Dockerfile +++ b/docker/kubernetes-agent-tentacle/Dockerfile @@ -16,10 +16,10 @@ WORKDIR /bootstrapRunner RUN mkdir -p bin RUN for platform in $platforms; do \ - Run for arch in $architectures; do \ - GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch" \ - done; \ -done; + for arch in $architectures; do \ + GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch"; \ + done; \ + done FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh index cbef9032d..a525028d3 100755 --- a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh +++ b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh @@ -43,8 +43,6 @@ if [ ! -f "$BINARY_PATH" ]; then exit 1 fi -# Make sure the binary is executable -chmod +x "$BINARY_PATH" # Execute the appropriate binary with all arguments passed through exec "$BINARY_PATH" "$@" \ No newline at end of file diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 90dde00eb..551f3a65f 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -14,10 +14,9 @@ RUN mkdir -p bin # Build for multiple architectures # Note: the given ldflags remove debug symbols -RUN GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-amd64" \ - && GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm64" \ - && GOOS=linux GOARCH=386 go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-386" \ - && GOOS=linux GOARCH=arm go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-arm" +RUN for arch in amd64 arm64 386 arm; do \ + GOOS=linux GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-$arch"; \ + done # Copy the architecture detection script from source and make it executable COPY docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh bin/ @@ -65,7 +64,7 @@ RUN \ # We know this won't reduce the image size at all. It's just to make the filesystem a little tidier. RUN rm -rf /tmp/* -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/select-bootstrapRunner.sh +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/execute-bootstrapRunner.sh ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" From 17fc462e4a8b02ff11f70bd74085d6d6cf5ca30b Mon Sep 17 00:00:00 2001 From: Trent Mohay Date: Fri, 6 Mar 2026 13:01:13 +1100 Subject: [PATCH 07/13] support a subset of runtimeids for multi-arch containers --- build/Build.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index aaa8bb439..f0564681a 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -58,7 +58,7 @@ partial class Build : NukeBuild [Parameter(Name = "signing_certificate_path")] public static string SigningCertificatePath = RootDirectory / "certificates" / "OctopusDevelopment.pfx"; [Secret] [Parameter(Name = "signing_certificate_password")] public static string SigningCertificatePassword = "Password01!"; - [Parameter(Name = "RuntimeId")] public string? SpecificRuntimeId; + [Parameter(Name = "RuntimeIds")] public string? SpecificRuntimeIds; readonly AbsolutePath SourceDirectory = RootDirectory / "source"; readonly AbsolutePath ArtifactsDirectory = RootDirectory / "_artifacts"; @@ -70,8 +70,8 @@ partial class Build : NukeBuild const string NetCore = "net8.0"; const string NetCoreWindows = "net8.0-windows"; - IEnumerable RuntimeIds => SpecificRuntimeId != null - ? new[] { SpecificRuntimeId } + IEnumerable RuntimeIds => SpecificRuntimeIds != null + ? SpecificRuntimeIds.Split(",") : new[] { "win", "win-x86", "win-x64", "linux-x64", "linux-musl-x64", "linux-arm64", "linux-arm", "osx-x64", "osx-arm64" }; IEnumerable CrossPlatformBundleForServerRequiredRuntimes => ["win", "win-x86", "win-x64", "linux-x64", "linux-arm64", "linux-arm"]; From 5c84255703c539baf834de1dd7329d65a641e012 Mon Sep 17 00:00:00 2001 From: Trent Mohay Date: Fri, 6 Mar 2026 13:30:13 +1100 Subject: [PATCH 08/13] make it an array --- build/Build.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index f0564681a..cf860a36b 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -58,7 +58,7 @@ partial class Build : NukeBuild [Parameter(Name = "signing_certificate_path")] public static string SigningCertificatePath = RootDirectory / "certificates" / "OctopusDevelopment.pfx"; [Secret] [Parameter(Name = "signing_certificate_password")] public static string SigningCertificatePassword = "Password01!"; - [Parameter(Name = "RuntimeIds")] public string? SpecificRuntimeIds; + [Parameter(Name = "RuntimeIds")] public string[] SpecificRuntimeIds = []; readonly AbsolutePath SourceDirectory = RootDirectory / "source"; readonly AbsolutePath ArtifactsDirectory = RootDirectory / "_artifacts"; @@ -70,9 +70,9 @@ partial class Build : NukeBuild const string NetCore = "net8.0"; const string NetCoreWindows = "net8.0-windows"; - IEnumerable RuntimeIds => SpecificRuntimeIds != null - ? SpecificRuntimeIds.Split(",") - : new[] { "win", "win-x86", "win-x64", "linux-x64", "linux-musl-x64", "linux-arm64", "linux-arm", "osx-x64", "osx-arm64" }; + IEnumerable RuntimeIds => !SpecificRuntimeIds.IsEmpty() + ? SpecificRuntimeIds + : ["win", "win-x86", "win-x64", "linux-x64", "linux-musl-x64", "linux-arm64", "linux-arm", "osx-x64", "osx-arm64"]; IEnumerable CrossPlatformBundleForServerRequiredRuntimes => ["win", "win-x86", "win-x64", "linux-x64", "linux-arm64", "linux-arm"]; From dd107ba0a50eda815f98c3a7ec156d0a794a251c Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Fri, 6 Mar 2026 16:06:30 +1100 Subject: [PATCH 09/13] update tested script --- .../bootstrapRunner/execute-bootstrapRunner.sh | 15 +++------------ docker/kubernetes-agent-tentacle/dev/Dockerfile | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh index a525028d3..2c6a56394 100755 --- a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh +++ b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh @@ -2,7 +2,7 @@ set -eu # Architecture detection and bootstrap runner selection script -# This script automatically detects the runtime architecture and selects +# This script automatically detects the runtime architecture and selects # the appropriate bootstrapRunner binary for execution. # Detect the current architecture @@ -32,17 +32,8 @@ esac # Construct binary name BINARY_NAME="bootstrapRunner-${OS}-${GO_ARCH}" -BINARY_PATH="/bootstrapRunner/$BINARY_NAME" - -# Check if the binary exists -if [ ! -f "$BINARY_PATH" ]; then - echo "Error: Bootstrap runner binary not found for architecture ${OS}-${GO_ARCH}" >&2 - echo "Looking for: $BINARY_PATH" >&2 - echo "Available binaries:" >&2 - ls -1 "/bootstrapRunner"/bootstrapRunner-* 2>/dev/null || echo " No bootstrap binaries found" >&2 - exit 1 -fi +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # Execute the appropriate binary with all arguments passed through -exec "$BINARY_PATH" "$@" \ No newline at end of file +exec "$SCRIPT_DIR/$BINARY_NAME" "$@" \ No newline at end of file diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 551f3a65f..5cce2ab50 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -19,8 +19,8 @@ RUN for arch in amd64 arm64 386 arm; do \ done # Copy the architecture detection script from source and make it executable -COPY docker/kubernetes-agent-tentacle/bootstrapRunner/select-bootstrapRunner.sh bin/ -RUN chmod +x bin/select-bootstrapRunner.sh +COPY docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh bin/ +RUN chmod +x bin/execute-bootstrapRunner.sh FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag From 519ffb5d4135887152b33378d89298604f8fe727 Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Fri, 6 Mar 2026 16:11:39 +1100 Subject: [PATCH 10/13] cleanup --- docker/kubernetes-agent-tentacle/dev/Dockerfile | 16 ++++++++++------ .../Kubernetes/KubernetesScriptPodCreator.cs | 3 --- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 5cce2ab50..692637338 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -12,10 +12,10 @@ WORKDIR /bootstrapRunner # Create bin directory for multiple architectures RUN mkdir -p bin -# Build for multiple architectures -# Note: the given ldflags remove debug symbols -RUN for arch in amd64 arm64 386 arm; do \ - GOOS=linux GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-$arch"; \ +RUN for platform in $platforms; do \ + for arch in $architectures; do \ + GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch"; \ + done; \ done # Copy the architecture detection script from source and make it executable @@ -39,7 +39,11 @@ EXPOSE 7777 COPY docker/kubernetes-agent-tentacle/scripts/* /scripts/ COPY --from=bootstrapRunnerBuilder bootstrapRunner/bin/* /bootstrapRunner/ -RUN chmod +x /scripts/*.sh && chmod +x /bootstrapRunner/* +RUN chmod +x /scripts/*.sh + +# Copy the architecture detection script from source and make it executable +COPY docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh /bootstrapRunner/ +RUN chmod +x /bootstrapRunner/execute-bootstrapRunner.sh COPY docker/kubernetes-agent-tentacle/dev/scripts/* /dev-scripts/ RUN chmod +x /dev-scripts/*.sh @@ -64,7 +68,7 @@ RUN \ # We know this won't reduce the image size at all. It's just to make the filesystem a little tidier. RUN rm -rf /tmp/* -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/execute-bootstrapRunner.sh +ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/ ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs index 6916a1aab..439355a81 100644 --- a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs +++ b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs @@ -179,9 +179,6 @@ async Task CreatePod(StartKubernetesScriptCommandV1 command, IScriptWorkspace wo LogVerboseToBothLogs($"Creating Kubernetes Pod '{podName}'.", tentacleScriptLog); - - //TODO(tmm): Need to copy over ALL the bootstrap files and bootstrap run selector. - //need to determine whate files are available foreach(var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutablePath)) { var baseName = Path.GetFileName(file); From 26745a55679755910fee52f377d9d4d1d4303ccc Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Fri, 6 Mar 2026 16:12:59 +1100 Subject: [PATCH 11/13] revert --- build/Build.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/Build.cs b/build/Build.cs index cf860a36b..aaa8bb439 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -58,7 +58,7 @@ partial class Build : NukeBuild [Parameter(Name = "signing_certificate_path")] public static string SigningCertificatePath = RootDirectory / "certificates" / "OctopusDevelopment.pfx"; [Secret] [Parameter(Name = "signing_certificate_password")] public static string SigningCertificatePassword = "Password01!"; - [Parameter(Name = "RuntimeIds")] public string[] SpecificRuntimeIds = []; + [Parameter(Name = "RuntimeId")] public string? SpecificRuntimeId; readonly AbsolutePath SourceDirectory = RootDirectory / "source"; readonly AbsolutePath ArtifactsDirectory = RootDirectory / "_artifacts"; @@ -70,9 +70,9 @@ partial class Build : NukeBuild const string NetCore = "net8.0"; const string NetCoreWindows = "net8.0-windows"; - IEnumerable RuntimeIds => !SpecificRuntimeIds.IsEmpty() - ? SpecificRuntimeIds - : ["win", "win-x86", "win-x64", "linux-x64", "linux-musl-x64", "linux-arm64", "linux-arm", "osx-x64", "osx-arm64"]; + IEnumerable RuntimeIds => SpecificRuntimeId != null + ? new[] { SpecificRuntimeId } + : new[] { "win", "win-x86", "win-x64", "linux-x64", "linux-musl-x64", "linux-arm64", "linux-arm", "osx-x64", "osx-arm64" }; IEnumerable CrossPlatformBundleForServerRequiredRuntimes => ["win", "win-x86", "win-x64", "linux-x64", "linux-arm64", "linux-arm"]; From 1cc2970566613f95abc3ffc88f5a79524afe5ac1 Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Fri, 6 Mar 2026 17:01:34 +1100 Subject: [PATCH 12/13] set platform and architecture --- docker/kubernetes-agent-tentacle/dev/Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 692637338..1f174d2d7 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -6,6 +6,9 @@ FROM golang:1.22 as bootstrapRunnerBuilder ARG TARGETARCH ARG TARGETOS +ARG platforms="linux" +ARG architectures="amd64 arm64 386 arm" + COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ WORKDIR /bootstrapRunner @@ -18,10 +21,6 @@ RUN for platform in $platforms; do \ done; \ done -# Copy the architecture detection script from source and make it executable -COPY docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh bin/ -RUN chmod +x bin/execute-bootstrapRunner.sh - FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag From 78ecdc6e85d1ea79167b5a6acd52976c0b5a0470 Mon Sep 17 00:00:00 2001 From: Cal Luy Date: Thu, 12 Mar 2026 14:13:45 +1100 Subject: [PATCH 13/13] Review comments --- docker/kubernetes-agent-tentacle/Dockerfile | 9 +++------ .../bootstrapRunner/execute-bootstrapRunner.sh | 3 +-- docker/kubernetes-agent-tentacle/dev/Dockerfile | 9 +++------ source/Octopus.Tentacle/Kubernetes/KubernetesConfig.cs | 2 +- .../Kubernetes/KubernetesScriptPodCreator.cs | 2 +- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/docker/kubernetes-agent-tentacle/Dockerfile b/docker/kubernetes-agent-tentacle/Dockerfile index ccd0e02e5..46b1ddce7 100644 --- a/docker/kubernetes-agent-tentacle/Dockerfile +++ b/docker/kubernetes-agent-tentacle/Dockerfile @@ -6,7 +6,6 @@ FROM golang:1.22 as bootstrapRunnerBuilder ARG TARGETARCH ARG TARGETOS -ARG platforms="linux" ARG architectures="amd64 arm64 386 arm" COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ @@ -15,10 +14,8 @@ WORKDIR /bootstrapRunner # Create bin directory for multiple architectures RUN mkdir -p bin -RUN for platform in $platforms; do \ - for arch in $architectures; do \ - GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch"; \ - done; \ +RUN for arch in $architectures; do \ + GOOS=linux GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-$arch"; \ done FROM mcr.microsoft.com/dotnet/runtime-deps:$RuntimeDepsTag @@ -79,7 +76,7 @@ RUN chgrp -R 0 /opt /usr /.dotnet && \ RUN chgrp 0 /etc /etc/ssl/certs && \ chmod g=u /etc /etc/ssl/certs -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/ +ENV BOOTSTRAPRUNNEREXECUTABLEDIRECTORY=/bootstrapRunner/ ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh index 2c6a56394..bc71c3579 100755 --- a/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh +++ b/docker/kubernetes-agent-tentacle/bootstrapRunner/execute-bootstrapRunner.sh @@ -7,7 +7,6 @@ set -eu # Detect the current architecture ARCH=$(uname -m) -OS=$(uname -s | tr '[:upper:]' '[:lower:]') # Map architecture names to Go architecture naming case "$ARCH" in @@ -31,7 +30,7 @@ case "$ARCH" in esac # Construct binary name -BINARY_NAME="bootstrapRunner-${OS}-${GO_ARCH}" +BINARY_NAME="bootstrapRunner-linux-${GO_ARCH}" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" diff --git a/docker/kubernetes-agent-tentacle/dev/Dockerfile b/docker/kubernetes-agent-tentacle/dev/Dockerfile index 1f174d2d7..58c458825 100644 --- a/docker/kubernetes-agent-tentacle/dev/Dockerfile +++ b/docker/kubernetes-agent-tentacle/dev/Dockerfile @@ -6,7 +6,6 @@ FROM golang:1.22 as bootstrapRunnerBuilder ARG TARGETARCH ARG TARGETOS -ARG platforms="linux" ARG architectures="amd64 arm64 386 arm" COPY docker/kubernetes-agent-tentacle/bootstrapRunner/* /bootstrapRunner/ @@ -15,10 +14,8 @@ WORKDIR /bootstrapRunner # Create bin directory for multiple architectures RUN mkdir -p bin -RUN for platform in $platforms; do \ - for arch in $architectures; do \ - GOOS=$platform GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-$platform-$arch"; \ - done; \ +RUN for arch in $architectures; do \ + GOOS=linux GOARCH=$arch go build -ldflags "-s -w" -o "bin/bootstrapRunner-linux-$arch"; \ done @@ -67,7 +64,7 @@ RUN \ # We know this won't reduce the image size at all. It's just to make the filesystem a little tidier. RUN rm -rf /tmp/* -ENV BOOTSTRAPRUNNEREXECUTABLEPATH=/bootstrapRunner/ +ENV BOOTSTRAPRUNNEREXECUTABLEDIRECTORY=/bootstrapRunner/ ENV OCTOPUS_RUNNING_IN_CONTAINER=Y ENV ACCEPT_EULA=N ENV CustomPublicHostName="" diff --git a/source/Octopus.Tentacle/Kubernetes/KubernetesConfig.cs b/source/Octopus.Tentacle/Kubernetes/KubernetesConfig.cs index 72f942c29..6402dfa28 100644 --- a/source/Octopus.Tentacle/Kubernetes/KubernetesConfig.cs +++ b/source/Octopus.Tentacle/Kubernetes/KubernetesConfig.cs @@ -35,7 +35,7 @@ public static class KubernetesConfig public static string KubernetesMonitorEnabledVariableName => $"{EnvVarPrefix}__KUBERNETESMONITORENABLED"; public static string? KubernetesMonitorEnabled => Environment.GetEnvironmentVariable(KubernetesMonitorEnabledVariableName); - public static string BootstrapRunnerExecutablePath => GetRequiredEnvVar("BOOTSTRAPRUNNEREXECUTABLEPATH", "Unable to determine Bootstrap Runner Executable Path"); + public static string BootstrapRunnerExecutableDirectory => GetRequiredEnvVar("BOOTSTRAPRUNNEREXECUTABLEDIRECTORY", "Unable to determine Bootstrap Runner Executable Directory"); public static string PersistentVolumeSizeVariableName => $"{EnvVarPrefix}__PERSISTENTVOLUMESIZE"; public static string PersistentVolumeSize => GetRequiredEnvVar(PersistentVolumeSizeVariableName, "Unable to determine Persistent Volume Size"); diff --git a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs index 439355a81..dffa904f9 100644 --- a/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs +++ b/source/Octopus.Tentacle/Kubernetes/KubernetesScriptPodCreator.cs @@ -179,7 +179,7 @@ async Task CreatePod(StartKubernetesScriptCommandV1 command, IScriptWorkspace wo LogVerboseToBothLogs($"Creating Kubernetes Pod '{podName}'.", tentacleScriptLog); - foreach(var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutablePath)) + foreach(var file in kubernetesPhysicalFileSystem.EnumerateFiles(KubernetesConfig.BootstrapRunnerExecutableDirectory)) { var baseName = Path.GetFileName(file); workspace.CopyFile(file, baseName, true);