From f9a57f560b249317b1ab25052326e383b699979a Mon Sep 17 00:00:00 2001 From: Dan Pock Date: Fri, 30 Aug 2024 14:38:03 -0400 Subject: [PATCH] Init main branch from POC repo --- .github/scripts/branch-tags.sh | 49 +++++++ .github/workflows/head-build.yml | 64 ++++++++ .github/workflows/release-publish.yml | 42 ++++++ .gitignore | 9 ++ LICENSE | 201 ++++++++++++++++++++++++++ Makefile | 43 ++++++ README.md | 64 ++++++++ hack/make/build.mk | 45 ++++++ hack/make/deps.mk | 29 ++++ package/Dockerfile | 44 ++++++ scripts/add-new-versions.sh | 30 ++++ scripts/check-kuberlr-versions.sh | 15 ++ scripts/new-kuberlr-versions.sh | 19 +++ 13 files changed, 654 insertions(+) create mode 100644 .github/scripts/branch-tags.sh create mode 100644 .github/workflows/head-build.yml create mode 100644 .github/workflows/release-publish.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 hack/make/build.mk create mode 100644 hack/make/deps.mk create mode 100644 package/Dockerfile create mode 100755 scripts/add-new-versions.sh create mode 100755 scripts/check-kuberlr-versions.sh create mode 100755 scripts/new-kuberlr-versions.sh diff --git a/.github/scripts/branch-tags.sh b/.github/scripts/branch-tags.sh new file mode 100644 index 0000000..8456894 --- /dev/null +++ b/.github/scripts/branch-tags.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -e + +# Function to get the previous tag +getPreviousTag() { + local tagPrefix="$1" + # List all tags and filter ones that start with tagPrefix, sort by creation date + git tag --sort=-creatordate | grep "^${tagPrefix}" | head -n 1 +} + +# Determine if we're in a GitHub Actions environment +if [ -n "$GITHUB_REF" ] && [ -n "$GITHUB_SHA" ]; then + # Use GHA environment variables + ref="$GITHUB_REF" + commitSha="${GITHUB_SHA:0:7}" +else + # Fallback to local Git repo + if [ ! -d ".git" ]; then + echo "This script must be run from the root of a Git repository or GitHub Actions." + exit 1 + fi + ref=$(git symbolic-ref HEAD) + commitSha=$(git rev-parse --short HEAD) +fi + +branchTag="" +branchStaticTag="" +prevTag="" + +if [ "$ref" == "refs/heads/main" ]; then + branchTag="head" + branchStaticTag="main-${commitSha}" + prevTag=$(getPreviousTag "main-") +elif [[ "$ref" == refs/heads/release/* ]]; then + version="${ref#refs/heads/release/}" # Extract "vX.0" + branchTag="${version}-head" + branchStaticTag="${version}-head-${commitSha}" + prevTag=$(getPreviousTag "${version}-head-") +else + echo "Unsupported branch pattern. Expected 'main' or 'release/*'." + exit 1 +fi + +# Output the results +echo "branch_tag=${branchTag}" +echo "branch_static_tag=${branchStaticTag}" +echo "prev_static_tag=${prevTag}" \ No newline at end of file diff --git a/.github/workflows/head-build.yml b/.github/workflows/head-build.yml new file mode 100644 index 0000000..b63063e --- /dev/null +++ b/.github/workflows/head-build.yml @@ -0,0 +1,64 @@ +name : Branch head Prerelease Images + +on: + push: + branches: + - main + - release/v[0-9]+.0 + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write # Upload artefacts to release. + +env: + PUBLIC_REGISTRY: docker.io + +jobs: + prebuild-env: + name: Prebuild needed Env vars + runs-on: ubuntu-latest + steps: + - name: Check out the repository to the runner + uses: actions/checkout@v4 + - name: Set Branch Tag and Other Variables + id: set-vars + run: bash ./.github/scripts/branch-tags.sh >> $GITHUB_OUTPUT + outputs: + branch_tag: ${{ steps.set-vars.outputs.branch_tag }} + branch_static_tag: ${{ steps.set-vars.outputs.branch_static_tag }} + prev_tag: ${{ steps.set-vars.outputs.prev_tag }} + + publish-public: + runs-on: ubuntu-latest + needs: + - prebuild-env + steps: + - name: Check out repository code + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + + - name: Build and push all image variations + uses: rancher/ecm-distro-tools/actions/publish-image@master + with: + image: ${{ vars.IMAGE_NAME || 'kuberlr-kubectl' }} + tag: ${{ needs.prebuild-env.outputs.branch_static_tag }} + platforms: "linux/amd64,linux/arm64,linux/s390x" + + public-registry: ${{ env.PUBLIC_REGISTRY }} + public-repo: ${{ vars.REPO || github.repository_owner }} + public-username: ${{ vars.DOCKER_USERNAME || github.repository_owner }} + public-password: ${{ secrets.DOCKER_PASSWORD }} + + push-to-prime: false + + - name: Re-tag the static head image using the rolling tag + env: + FULL_IMAGE_URL: ${{ env.PUBLIC_REGISTRY }}/${{ vars.REPO || github.repository_owner }}/${{ vars.IMAGE_NAME || 'kuberlr-kubectl' }} + run: | + VERSION="1.2.0" + curl -LO "https://github.com/oras-project/oras/releases/download/v${VERSION}/oras_${VERSION}_linux_amd64.tar.gz" + mkdir -p oras-install/ + tar -zxf oras_${VERSION}_*.tar.gz -C oras-install/ + oras-install/oras copy ${{ env.FULL_IMAGE_URL }}:${{ needs.prebuild-env.outputs.branch_static_tag }} ${{ env.FULL_IMAGE_URL }}:${{ needs.prebuild-env.outputs.branch_tag }} diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 0000000..9249db0 --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,42 @@ +name: Stable Image Releases + +on: + push: + tags: + - '*' + +env: + IMAGE_REPO: "rancher/kuberlr-kubectl" + +# GitHub settings / example values: +# +# org level vars: +# - PUBLIC_REGISTRY: docker.io +# repo level vars: +# - PUBLIC_REGISTRY_REPO: rancher +# repo level secrets: +# - PUBLIC_REGISTRY_USERNAME +# - PUBLIC_REGISTRY_PASSWORD + +permissions: + contents: write # Upload artefacts to release. + +jobs: + + publish-public: + runs-on: ubuntu-latest + + steps: + - name: Build and push all platforms + uses: rancher/ecm-distro-tools/actions/publish-image@master + with: + image: kuberlr-kubectl + tag: ${{ github.ref_name }} + platforms: "linux/amd64,linux/arm64,linux/s390x" + + public-registry: ${{ env.PUBLIC_REGISTRY }} + public-repo: ${{ vars.REPO || github.repository_owner }} + public-username: ${{ vars.DOCKER_USERNAME || github.repository_owner }} + public-password: ${{ secrets.DOCKER_PASSWORD }} + + push-to-prime: false \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..334f999 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +/.dapper +/.cache +/.trash-cache +/bin +/dist +*.swp +.idea +versions.txt +new-versions.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..56f0a6e --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +# To avoid polluting the Makefile, versions and checksums for tooling and +# dependencies are defined at hack/make/deps.mk. +include hack/make/deps.mk + +# Include logic that can be reused across projects. +include hack/make/build.mk + +# Define target platforms, image builder and the fully qualified image name. +TARGET_PLATFORMS ?= linux/amd64,linux/arm64,linux/s390x + +REPO ?= rancher +IMAGE ?= kuberlr-kubectl +IMAGE_NAME = $(REPO)/$(IMAGE) +FULL_IMAGE_TAG = $(IMAGE_NAME):$(TAG) +BUILD_ACTION = --load + +.DEFAULT_GOAL := ci +ci: validate ## run the targets needed to validate a PR in CI. + +clean: ## clean up project. + rm -rf build + +build-image: buildx-machine ## build (and load) the container image targeting the current platform. + $(IMAGE_BUILDER) build -f package/Dockerfile \ + --builder $(MACHINE) $(IMAGE_ARGS) \ + --build-arg VERSION=$(VERSION) -t "$(FULL_IMAGE_TAG)" $(BUILD_ACTION) . + @echo "Built $(FULL_IMAGE_TAG)" + +push-image: buildx-machine ## build the container image targeting all platforms defined by TARGET_PLATFORMS and push to a registry. + $(IMAGE_BUILDER) build -f package/Dockerfile \ + --builder $(MACHINE) $(IMAGE_ARGS) $(IID_FILE_FLAG) $(BUILDX_ARGS) \ + --build-arg VERSION=$(VERSION) --platform=$(TARGET_PLATFORMS) -t "$(FULL_IMAGE_TAG)" --push . + @echo "Pushed $(FULL_IMAGE_TAG)" + +validate: validate-dirty ## Run validation checks. + +validate-dirty: +ifdef DIRTY + @echo Git is dirty + @git --no-pager status + @git --no-pager diff + @exit 1 +endif \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..53e87b3 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# rancher/kuberlr-kubectl +A simple way to invoke the correct [kubectl](https://github.com/rancher/kubectl) version on a Rancher managed cluster using [kuberlr](https://github.com/flavio/kuberlr). + +Images found at: https://hub.docker.com/r/rancher/kuberlr-kubectl + +## Details +This repo produces a Rancher specific version of the `flavio/kuberlr` image. + + - This container is analogous to the current `rancher/kubectl` container, but based on [kuberlr](https://github.com/flavio/kuberlr) + - Unlike `rancher/kubectl`, this image targets specific Rancher minor release branches. + - Each release pre-bundles all necessary [kubectl](https://github.com/rancher/kubectl) versions supported by the Rancher version the release supports. + +## Branches, Releases, and Rancher +| branch | Release | Rancher | +|----------------------|---------------|---------| +| main (release/v2.10) | head (v3.Y.Z) | 2.10.Z | +| release/v2.9 | v2.Y.Z | 2.9.Z | +| release/v2.8 | v1.Y.Z | 2.8.Z | + +### Notes: +- The current main branch is for 2.9 since that's the primary dev target. + - Upon rehoming to `rancher` we will: + - a `release/v2.9` will be created with not changes needed; + - `release/v2.8` will be created and PR'd to match kubectl versions; + - `main` can then be PR'd to use 2.10 target kubectls. +- Each minor Rancher release will get a `rancher/kuberlr-kubectl` branch: + - Each branch will get an image tag major to match it. + - This gives us full "Y" and "Z" control on versioning the component to target Rancher minors. + - E.x. Rancher 2.8.x releases will get varying versions of 1.Y.Z + +### Compatability + +The base `flavio/kuberlr` image comes from the upstream repo and is essentially universally compatible like `kuberlr`. +However, for it to work it relies on an internet connection to fetch kubectl binaries on the fly. + +In contrast, our `rancher/kuberlr-kubectl` bundles the necessary `kubectl` binaries into each image. +In this way the image is ready to work on any supported k8s versions for that Rancher release in an air-gap out the box. +Given that k8s provides a slight version drift, as the Rancher minor lifecycle progresses we reduce inclusion of older `kubectl` versions. + + +```mermaid + +gantt + title `rancher/rancher` and `rancher/kuberlr-kubectl` + todayMarker off + dateFormat X + axisFormat 1.%S + tickInterval 1second + section Rancher + 2.8.X :25,28 + 2.9.X :27,30 + section kuberlr-kubectl image + 1.Y.Z (for Rancher 2.8) :25,28 + 2.Y.Z (for Rancher 2.9) :27,30 + section Kubectl Drift + 1.25 :24,26 + 1.26 :25,27 + 1.27 :26,28 + 1.28 :27,29 + 1.29 :28,30 + 1.30 :29,31 +``` + +> Note: Over-time, as new `kuberlr` binaries are released we can still bump the Y or Z of each `rancher/kuberlr-kubectl` release to update all supported Rancher releases. \ No newline at end of file diff --git a/hack/make/build.mk b/hack/make/build.mk new file mode 100644 index 0000000..60fd87b --- /dev/null +++ b/hack/make/build.mk @@ -0,0 +1,45 @@ +ifeq ($(VERSION),) + # Define VERSION, which is used for image tags or to bake it into the + # compiled binary to enable the printing of the application version, + # via the --version flag. + CHANGES = $(shell git status --porcelain --untracked-files=no) + ifneq ($(CHANGES),) + DIRTY = -dirty + endif + + GIT_TAG = $(shell git tag -l --contains HEAD | head -n 1) + COMMIT = $(shell git rev-parse --short HEAD) + VERSION = $(COMMIT)$(DIRTY) + + # Override VERSION with the Git tag if the current HEAD has a tag pointing to + # it AND the worktree isn't dirty. + ifneq ($(GIT_TAG),) + ifeq ($(DIRTY),) + VERSION = $(GIT_TAG) + endif + endif +endif + +ifeq ($(TAG),) + TAG = $(VERSION) + ifneq ($(DIRTY),) + TAG = dev + endif +endif + +RUNNER := docker +IMAGE_BUILDER := $(RUNNER) buildx +MACHINE := rancher + +# Define the target platforms that can be used across the ecosystem. +# Note that what would actually be used for a given project will be +# defined in TARGET_PLATFORMS, and must be a subset of the below: +DEFAULT_PLATFORMS := linux/amd64,linux/arm64,linux/x390s,linux/riscv64 + +.PHONY: help +help: ## display Makefile's help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +buildx-machine: ## create rancher dockerbuildx machine targeting platform defined by DEFAULT_PLATFORMS. + @docker buildx ls | grep $(MACHINE) || \ + docker buildx create --name=$(MACHINE) --platform=$(DEFAULT_PLATFORMS) \ No newline at end of file diff --git a/hack/make/deps.mk b/hack/make/deps.mk new file mode 100644 index 0000000..10d23a1 --- /dev/null +++ b/hack/make/deps.mk @@ -0,0 +1,29 @@ +KUBECTL27_VERSION := v1.27.16 +KUBECTL27_SUM_arm64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL27_VERSION)/bin/linux/arm64/kubectl.sha256") +KUBECTL27_SUM_amd64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL27_VERSION)/bin/linux/amd64/kubectl.sha256") +KUBECTL27_SUM_s390x ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL27_VERSION)/bin/linux/s390x/kubectl.sha256") + +KUBECTL28_VERSION := v1.28.13 +KUBECTL28_SUM_arm64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL28_VERSION)/bin/linux/arm64/kubectl.sha256") +KUBECTL28_SUM_amd64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL28_VERSION)/bin/linux/amd64/kubectl.sha256") +KUBECTL28_SUM_s390x ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL28_VERSION)/bin/linux/s390x/kubectl.sha256") + +KUBECTL29_VERSION := v1.29.8 +KUBECTL29_SUM_arm64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL29_VERSION)/bin/linux/arm64/kubectl.sha256") +KUBECTL29_SUM_amd64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL29_VERSION)/bin/linux/amd64/kubectl.sha256") +KUBECTL29_SUM_s390x ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL29_VERSION)/bin/linux/s390x/kubectl.sha256") + +KUBECTL30_VERSION := v1.30.4 +KUBECTL30_SUM_arm64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL30_VERSION)/bin/linux/arm64/kubectl.sha256") +KUBECTL30_SUM_amd64 ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL30_VERSION)/bin/linux/amd64/kubectl.sha256") +KUBECTL30_SUM_s390x ?= $(shell curl -L "https://dl.k8s.io/release/$(KUBECTL30_VERSION)/bin/linux/s390x/kubectl.sha256") + +KUBECTL27 := "$(KUBECTL27_VERSION):$(KUBECTL27_SUM_arm64):$(KUBECTL27_SUM_amd64):$(KUBECTL27_SUM_s390x)" +KUBECTL28 := "$(KUBECTL28_VERSION):$(KUBECTL28_SUM_arm64):$(KUBECTL28_SUM_amd64):$(KUBECTL28_SUM_s390x)" +KUBECTL29 := "$(KUBECTL29_VERSION):$(KUBECTL29_SUM_arm64):$(KUBECTL29_SUM_amd64):$(KUBECTL29_SUM_s390x)" +KUBECTL30 := "$(KUBECTL30_VERSION):$(KUBECTL30_SUM_arm64):$(KUBECTL30_SUM_amd64):$(KUBECTL30_SUM_s390x)" + +KUBECTL_VERSION_INFO := "$(KUBECTL27) $(KUBECTL28) $(KUBECTL29) $(KUBECTL30)" + +# Reduces the code duplication on Makefile by keeping all args into a single variable. +IMAGE_ARGS := --build-arg KUBECTL_VERSION_INFO=$(KUBECTL_VERSION_INFO) \ No newline at end of file diff --git a/package/Dockerfile b/package/Dockerfile new file mode 100644 index 0000000..cf74979 --- /dev/null +++ b/package/Dockerfile @@ -0,0 +1,44 @@ +ARG BCI_VERSION=15.6 +FROM --platform=$BUILDPLATFORM registry.suse.com/bci/bci-base:${BCI_VERSION} AS build + +ARG TARGETPLATFORM +ARG TARGETARCH + +WORKDIR /tmp + +# Define build arguments +ARG KUBECTL_VERSION_INFO + +SHELL ["/bin/bash", "-c"] +RUN set -fx; versions=($KUBECTL_VERSION_INFO); \ + for i in "${!versions[@]}"; do \ + echo "The index is $i and the value is ${versions[$i]}"; \ + version=$(echo ${versions[$i]} | cut -d: -f1); \ + kubectl_url="https://dl.k8s.io/release/${version}/bin/linux/${TARGETARCH}/kubectl"; \ + kubectl_target="/tmp/kubectl${version:1}"; \ + echo "Downloading kubectl version ${version} from ${kubectl_url}"; \ + echo "Targeting ${kubectl_target}"; \ + curl -fsSL "$kubectl_url" -o "$kubectl_target"; \ + chmod 0755 "$kubectl_target"; \ + done + +RUN set -fx; versions=($KUBECTL_VERSION_INFO); \ + for i in "${!versions[@]}"; do \ + version=$(echo ${versions[$i]} | cut -d: -f1); \ + arm64_sum=$(echo ${versions[$i]} | cut -d: -f2); \ + amd64_sum=$(echo ${versions[$i]} | cut -d: -f3); \ + s390x_sum=$(echo ${versions[$i]} | cut -d: -f4); \ + kubectl_target="/tmp/kubectl${version:1}"; \ + KUBE_SUM_NAME="${TARGETARCH}_sum"; \ + KUBE_SUM=${!KUBE_SUM_NAME}; \ + echo "${KUBE_SUM} ${kubectl_target}" | sha256sum -c -; \ + done + +FROM ghcr.io/flavio/kuberlr:v0.5.1 + +COPY --from=build /tmp/kubectl* /usr/bin/ + +USER kuberlr +WORKDIR /home/kuberlr +ENTRYPOINT ["/bin/kubectl"] +CMD ["help"] \ No newline at end of file diff --git a/scripts/add-new-versions.sh b/scripts/add-new-versions.sh new file mode 100755 index 0000000..8505b10 --- /dev/null +++ b/scripts/add-new-versions.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euxo pipefail +RELEASES=$(gh api graphql -F owner='flavio' -F name='kuberlr' -f query='query($name: String!, $owner: String!) {repository(owner: $owner, name: $name) {releases(first: 100) {nodes { tagName, isPrerelease }} }}' | jq -r '.data.repository.releases.nodes[] | select(.isPrerelease != true) | .tagName' | sort -V) +# Including v0.4.3 and higher +INCLUDE_VERSIONS="v0\.([4-9]{1}\.[3-9]{1}|[0-9]{2,}\.[0-9]{2,})$" +VERSIONS_FILE="${1:-versions.txt}" + +ADDED_VERSIONS=() + +for RELEASE in $RELEASES; do + if [[ $RELEASE =~ $INCLUDE_VERSIONS ]]; then + echo "Version ${RELEASE} matched include versions, checking if already present" + if ! grep -q "^${RELEASE}$" "${VERSIONS_FILE}"; then + echo "Version ${RELEASE} not present in versions file ${VERSIONS_FILE}, adding" + ADDED_VERSIONS+=( "${RELEASE}" ) + echo "${RELEASE}" >> "${VERSIONS_FILE}" + else + echo "Version ${RELEASE} already present in versions file ${VERSIONS_FILE}, skipping" + fi + else + echo "Version ${RELEASE} does not match include versions, skipping" + fi +done + +if [ "${#ADDED_VERSIONS[@]}" -gt 0 ]; then + echo "Added [${#ADDED_VERSIONS[@]}] versions: (${ADDED_VERSIONS[*]})" + sort -rV -o "${VERSIONS_FILE}" "${VERSIONS_FILE}" +else + echo "No new versions added" +fi \ No newline at end of file diff --git a/scripts/check-kuberlr-versions.sh b/scripts/check-kuberlr-versions.sh new file mode 100755 index 0000000..500182e --- /dev/null +++ b/scripts/check-kuberlr-versions.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e + +VERSIONS_FILE="${1:-versions.txt}" +ARCHES="amd64 arm64 s390x" + +while IFS= read -r release; do + for arch in $ARCHES; do + KUBERLR_URL="https://github.com/flavio/kuberlr/releases/download/${release}/kuberlr_${release:1}_linux_${arch}.tar.gz" + echo "Checking if file exists at ${KUBERLR_URL}" + curl --retry 10 --retry-connrefused -IL -o /dev/null -sS --fail "${KUBERLR_URL}" + done +done < "$VERSIONS_FILE" + +echo "All versions exists for ${ARCHES}" \ No newline at end of file diff --git a/scripts/new-kuberlr-versions.sh b/scripts/new-kuberlr-versions.sh new file mode 100755 index 0000000..a3632e9 --- /dev/null +++ b/scripts/new-kuberlr-versions.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +: "${IMAGE_REPO:=rancher/kubectl}" +: "${EXISTING_VERSIONS:=''}" + +while IFS= read -r RELEASE_VERSION; do + CHECK_VERSION="base-${RELEASE_VERSION}" + echo "Checking if image ${IMAGE_REPO}:${CHECK_VERSION} exists" + for EXISTING_VERSION in $EXISTING_VERSIONS; do + if [ "$CHECK_VERSION" == "$EXISTING_VERSION" ]; then + echo "Image ${IMAGE_REPO}:${CHECK_VERSION} already exists, skipping" + continue 2 + fi + done + + echo "Image ${IMAGE_REPO}:${CHECK_VERSION} does not exist, adding to new versions list" + echo "${RELEASE_VERSION}" >> new-versions.txt +done < base/versions.txt