diff --git a/.github/workflows/toolkit-base-build-push.yaml b/.github/workflows/toolkit-base-build-push.yaml new file mode 100644 index 00000000..1eda1332 --- /dev/null +++ b/.github/workflows/toolkit-base-build-push.yaml @@ -0,0 +1,84 @@ +name: Create and publish toolkit base image + +on: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository_owner }}/eks-toolkit-base + BUILD_CONTEXT: tests/images/toolkit-base/ + +jobs: + get_versions_job: + runs-on: ubuntu-latest + outputs: + k8s_versions: ${{ steps.determine_versions.outputs.k8s_versions }} + latest_tools: ${{ steps.determine_versions.outputs.latest_tools }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install jq + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Determine K8s Versions and Tool Versions + id: determine_versions + working-directory: ${{ env.BUILD_CONTEXT }} + run: | + chmod +x ./get_versions_matrix.sh # We need a new version of the script + ./get_versions_matrix.sh + + build_and_push_image: + needs: get_versions_job + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + + strategy: + fail-fast: false # Optional: Set to false if you want other builds to finish even if one fails + matrix: + k8s_tag: ${{ fromJson(needs.get_versions_job.outputs.k8s_versions) }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup docker buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set Image Tag for Matrix Run + id: tags + run: | + # Use the K8s version as the primary tag + echo "tag=${{ matrix.k8s_tag }}" >> $GITHUB_OUTPUT + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: ${{ env.BUILD_CONTEXT }} + platforms: linux/amd64,linux/arm64 + push: true + # The tags are set dynamically by the 'Set Image Tag' step + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ matrix.k8s_tag }} + + # Extract the static tool versions from the needs output + build-args: | + KUBECTL_VERSION=${{ matrix.k8s_tag }} + HELM_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).helm_version }} + KUSTOMIZE_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).kustomize_version }} + KUBESEAL_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).kubeseal_version }} + KREW_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).krew_version }} + VALS_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).vals_version }} + KUBECONFORM_VERSION=${{ fromJson(needs.get_versions_job.outputs.latest_tools).kubeconform_version }} diff --git a/tests/images/toolkit-base/Dockerfile b/tests/images/toolkit-base/Dockerfile new file mode 100644 index 00000000..b3db62c3 --- /dev/null +++ b/tests/images/toolkit-base/Dockerfile @@ -0,0 +1,112 @@ +FROM alpine + +ARG ARCH + +# Ignore to update versions here +# docker build --no-cache --build-arg KUBECTL_VERSION=${tag} --build-arg HELM_VERSION=${helm} --build-arg KUSTOMIZE_VERSION=${kustomize_version} -t ${image}:${tag} . +ARG HELM_VERSION=3.2.1 +ARG KUBECTL_VERSION=1.17.5 +ARG KUSTOMIZE_VERSION=v3.8.1 +ARG KUBESEAL_VERSION=0.18.1 +ARG KREW_VERSION=v0.4.4 +ARG VALS_VERSION=0.28.1 +ARG KUBECONFORM_VERSION=0.6.3 + +# Install helm (latest release) +# ENV BASE_URL="https://storage.googleapis.com/kubernetes-helm" +RUN case `uname -m` in \ + x86_64) ARCH=amd64; ;; \ + armv7l) ARCH=arm; ;; \ + aarch64) ARCH=arm64; ;; \ + ppc64le) ARCH=ppc64le; ;; \ + s390x) ARCH=s390x; ;; \ + *) echo "un-supported arch, exit ..."; exit 1; ;; \ + esac && \ + echo "export ARCH=$ARCH" > /envfile && \ + cat /envfile + +RUN . /envfile && echo $ARCH && \ + apk add --update --no-cache curl ca-certificates bash git && \ + curl -sL https://get.helm.sh/helm-v${HELM_VERSION}-linux-${ARCH}.tar.gz | tar -xvz && \ + mv linux-${ARCH}/helm /usr/bin/helm && \ + chmod +x /usr/bin/helm && \ + rm -rf linux-${ARCH} + +# add helm-diff +RUN helm plugin install https://github.com/databus23/helm-diff --verify=false && rm -rf /tmp/helm-* && \ + rm -rf ~/.cache/helm/plugins/https-github.com-databus23-helm-diff/.git + +# add helm-unittest +RUN helm plugin install https://github.com/helm-unittest/helm-unittest --verify=false && rm -rf /tmp/helm-* + +# add helm-push +RUN helm plugin install https://github.com/chartmuseum/helm-push --verify=false && \ + rm -rf /tmp/helm-* \ + /root/.local/share/helm/plugins/helm-push/testdata \ + /root/.cache/helm/plugins/https-github.com-chartmuseum-helm-push/testdata + +# Install kubectl +RUN . /envfile && echo $ARCH && \ + curl -sLO "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/${ARCH}/kubectl" && \ + mv kubectl /usr/bin/kubectl && \ + chmod +x /usr/bin/kubectl + +# Install kustomize (latest release) +RUN . /envfile && echo $ARCH && \ + curl -sLO https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_linux_${ARCH}.tar.gz && \ + tar xvzf kustomize_${KUSTOMIZE_VERSION}_linux_${ARCH}.tar.gz && \ + mv kustomize /usr/bin/kustomize && \ + chmod +x /usr/bin/kustomize && \ + rm kustomize_${KUSTOMIZE_VERSION}_linux_${ARCH}.tar.gz + +# Install eksctl (latest version) +RUN . /envfile && echo $ARCH && \ + curl -sL "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_${ARCH}.tar.gz" | tar xz -C /tmp && \ + mv /tmp/eksctl /usr/bin && \ + chmod +x /usr/bin/eksctl + +# Install awscli +# Temp fix to allow system-wide package installation: +# https://stackoverflow.com/a/76540031/3671801 +RUN apk add --update --no-cache py3-pip && \ + pip3 install --break-system-packages --upgrade pip setuptools && \ + pip3 install --break-system-packages awscli && \ + pip3 cache purge + +# Install jq +RUN apk add --update --no-cache jq yq + +# https://docs.aws.amazon.com/eks/latest/userguide/install-aws-iam-authenticator.html +# Install aws-iam-authenticator (latest version) +RUN . /envfile && echo $ARCH && \ + authenticator=$(curl -fs https://api.github.com/repos/kubernetes-sigs/aws-iam-authenticator/releases/latest | jq --raw-output '.name' | sed 's/^v//') && \ + curl -fL https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v${authenticator}/aws-iam-authenticator_${authenticator}_linux_${ARCH} -o /usr/bin/aws-iam-authenticator && \ + chmod +x /usr/bin/aws-iam-authenticator + +# Install for envsubst +RUN apk add --update --no-cache gettext + +# Install kubeseal +RUN . /envfile && echo $ARCH && \ + curl -L https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-${ARCH}.tar.gz -o - | tar xz -C /usr/bin/ && \ + chmod +x /usr/bin/kubeseal + +# Install vals +RUN . /envfile && echo $ARCH && \ + curl -L https://github.com/helmfile/vals/releases/download/v${VALS_VERSION}/vals_${VALS_VERSION}_linux_${ARCH}.tar.gz -o -| tar xz -C /usr/bin/ && \ + chmod +x /usr/bin/vals + +# Install krew (latest release) +RUN . /envfile && echo $ARCH && \ + curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/download/v${KREW_VERSION}/krew-linux_${ARCH}.tar.gz" && \ + tar zxvf krew-linux_${ARCH}.tar.gz && \ + ./krew-linux_${ARCH} install krew && \ + echo 'export PATH=/root/.krew/bin:$PATH' >> ~/.bashrc && \ + rm krew-linux_${ARCH}.tar.gz + +# Install kubeconform +RUN . /envfile && echo $ARCH && \ + curl -L https://github.com/yannh/kubeconform/releases/download/v${KUBECONFORM_VERSION}/kubeconform-linux-${ARCH}.tar.gz -o - | tar xz -C /usr/bin/ && \ + chmod +x /usr/bin/kubeconform + +WORKDIR /apps diff --git a/tests/images/toolkit-base/get_versions_matrix.sh b/tests/images/toolkit-base/get_versions_matrix.sh new file mode 100644 index 00000000..f8f1fc70 --- /dev/null +++ b/tests/images/toolkit-base/get_versions_matrix.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +set -e + +# --- 1. Find all Static Tool Versions (Combined into a single JSON object) --- + +HELM_VERSION=$(curl -s https://api.github.com/repos/helm/helm/releases | jq -r '.[].tag_name | select([startswith("v"), (contains("-") | not)] | all)' | sort -rV | head -n 1 | sed 's/v//') +KUSTOMIZE_RELEASE=$(curl -s https://api.github.com/repos/kubernetes-sigs/kustomize/releases | jq -r '.[].tag_name | select(contains("kustomize"))' | sort -rV | head -n 1) +KUSTOMIZE_VERSION=$(basename ${KUSTOMIZE_RELEASE}) +KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/releases | jq -r '.[].tag_name | select(startswith("v"))' | sort -rV | head -n 1 | sed 's/v//') +KREW_VERSION=$(curl -s https://api.github.com/repos/kubernetes-sigs/krew/releases | jq -r '.[].tag_name | select(startswith("v"))' | sort -rV | head -n 1 | sed 's/v//') +VALS_VERSION=$(curl -s https://api.github.com/repos/helmfile/vals/releases | jq -r '.[].tag_name | select(startswith("v"))' | sort -rV | head -n 1 | sed 's/v//') +KUBECONFORM_VERSION=$(curl -s https://api.github.com/repos/yannh/kubeconform/releases | jq -r '.[].tag_name | select(startswith("v"))' | sort -rV | head -n 1 | sed 's/v//') + + +# Construct a single, compacted JSON object without extra spaces +LATEST_TOOLS_JSON=$( + jq -n -c \ + --arg helm "$HELM_VERSION" \ + --arg kustomize "$KUSTOMIZE_VERSION" \ + --arg kubeseal "$KUBESEAL_VERSION" \ + --arg krew "$KREW_VERSION" \ + --arg vals "$VALS_VERSION" \ + --arg kubeconform "$KUBECONFORM_VERSION" \ + '{ + "helm_version": $helm, + "kustomize_version": $kustomize, + "kubeseal_version": $kubeseal, + "krew_version": $krew, + "vals_version": $vals, + "kubeconform_version": $kubeconform + }' +) + +# Use the 'LATEST_TOOLS_JSON' variable directly, ensuring no leading spaces +echo "latest_tools=$LATEST_TOOLS_JSON" >> $GITHUB_OUTPUT + +# Optional: Keep the echo for logging, but ONLY to stdout, not GITHUB_OUTPUT +echo "Found static tools: $LATEST_TOOLS_JSON" + + +# --- 2. Find the top 4 latest K8s minor versions (Output as a JSON Array) --- + +RELEASES=$(curl -s https://api.github.com/repos/kubernetes/kubernetes/releases | jq -r '.[].tag_name | select(test("alpha|beta|rc") | not)') + +MINOR_VERSIONS=() +for RELEASE in $RELEASES; do + MINOR_VERSION=$(echo $RELEASE | awk -F'.' '{print $1"."$2}') + if [[ ! " ${MINOR_VERSIONS[@]} " =~ " ${MINOR_VERSION} " ]]; then + MINOR_VERSIONS+=($MINOR_VERSION) + fi +done + +SORTED_MINOR_VERSIONS=($(echo "${MINOR_VERSIONS[@]}" | tr ' ' '\n' | sort -rV)) + +K8S_TAGS=() +for i in $(seq 0 3); do + MINOR_VERSION="${SORTED_MINOR_VERSIONS[$i]}" + LATEST_VERSION=$(echo "$RELEASES" | grep "^$MINOR_VERSION\." | sort -rV | head -1 | sed 's/v//') + K8S_TAGS+=("$LATEST_VERSION") +done + +# Convert the bash array into a single-line JSON array string (using -c flag for compact output) +K8S_TAGS_JSON=$(printf '%s\n' "${K8S_TAGS[@]}" | jq -R . | jq -s -c .) + +echo "k8s_versions=$K8S_TAGS_JSON" >> $GITHUB_OUTPUT +echo "Found K8s versions: ${K8S_TAGS[*]}"