You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by nd...@apache.org on 2023/06/19 13:31:17 UTC

[hbase-kustomize] branch main updated: HBASE-27829 Introduce build for kuttl image, basis for dev/test environment

This is an automated email from the ASF dual-hosted git repository.

ndimiduk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hbase-kustomize.git


The following commit(s) were added to refs/heads/main by this push:
     new a300942  HBASE-27829 Introduce build for kuttl image, basis for dev/test environment
a300942 is described below

commit a30094255ad72047568542c55fba1bd13760d80a
Author: Nick Dimiduk <nd...@apache.org>
AuthorDate: Fri Jun 16 11:01:36 2023 +0200

    HBASE-27829 Introduce build for kuttl image, basis for dev/test environment
    
    Signed-off-by: Sean Busbey <bu...@apache.org>
    
    address pre-commit issues
---
 .asf.yaml                                          |  12 +-
 .codespellrc                                       |  18 +++
 .markdownlint.yaml                                 |  18 +++
 .yamllint.yaml                                     |  21 +++
 dev-support/jenkins/gather_machine_environment.sh  |   2 +
 .../jenkins/jenkins_precommit_github_yetus.sh      |   4 +-
 dockerfiles/kuttl/Dockerfile                       | 161 +++++++++++++++++++++
 dockerfiles/kuttl/README.md                        |  71 +++++++++
 dockerfiles/kuttl/docker-bake.hcl                  |  92 ++++++++++++
 dockerfiles/kuttl/docker-bake.override.hcl         | 103 +++++++++++++
 dockerfiles/kuttl/entrypoint.sh                    |  29 ++++
 11 files changed, 524 insertions(+), 7 deletions(-)

diff --git a/.asf.yaml b/.asf.yaml
index 75f3261..c1a0e63 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -19,6 +19,8 @@
 # details. Be careful when changing the contents of this file since it may affect many developers
 # of the project and make sure to discuss the changes with dev@ before committing.
 
+# yamllint disable rule:document-start
+
 github:
   description: "Apache HBase deployments on Kubernetes using Kustomize"
   homepage: https://hbase.apache.org/
@@ -32,11 +34,11 @@ github:
     issues: false
     projects: false
   enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  true
+    squash: true
+    merge: false
+    rebase: true
 notifications:
-  commits:      commits@hbase.apache.org
-  issues:       issues@hbase.apache.org
+  commits: commits@hbase.apache.org
+  issues: issues@hbase.apache.org
   pullrequests: issues@hbase.apache.org
   jira_options: link
diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 0000000..0863336
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+[codespell]
+skip = LICENSE.txt
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
new file mode 100644
index 0000000..e379db1
--- /dev/null
+++ b/.markdownlint.yaml
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+---
+MD013:
+  line_length: 100
diff --git a/.yamllint.yaml b/.yamllint.yaml
new file mode 100644
index 0000000..5d92049
--- /dev/null
+++ b/.yamllint.yaml
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+---
+extends: default
+
+rules:
+  line-length:
+    max: 100
diff --git a/dev-support/jenkins/gather_machine_environment.sh b/dev-support/jenkins/gather_machine_environment.sh
index cabd158..9666e81 100755
--- a/dev-support/jenkins/gather_machine_environment.sh
+++ b/dev-support/jenkins/gather_machine_environment.sh
@@ -16,6 +16,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
+# SHELLDOC-IGNORE
+
 set -e
 function usage {
   echo "Usage: ${0} /path/for/output/dir"
diff --git a/dev-support/jenkins/jenkins_precommit_github_yetus.sh b/dev-support/jenkins/jenkins_precommit_github_yetus.sh
index ca92e20..3e736fd 100755
--- a/dev-support/jenkins/jenkins_precommit_github_yetus.sh
+++ b/dev-support/jenkins/jenkins_precommit_github_yetus.sh
@@ -16,6 +16,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
+# SHELLDOC-IGNORE
+
 set -e
 
 # place ourselves in the directory containing the hbase and yetus checkouts
@@ -110,8 +112,6 @@ YETUS_ARGS+=("--tests-filter=test4tests")
 YETUS_ARGS+=("--docker")
 # our jenkins workers don't have buildkit installed (INFRA-24704)
 YETUS_ARGS+=('--docker-buildkit=false')
-# effectively treat dev-support as a custom maven module
-YETUS_ARGS+=("--skip-dirs=dev-support")
 # help keep the ASF boxes clean
 YETUS_ARGS+=("--sentinel")
 YETUS_ARGS+=("--github-token=${GITHUB_TOKEN}")
diff --git a/dockerfiles/kuttl/Dockerfile b/dockerfiles/kuttl/Dockerfile
new file mode 100644
index 0000000..bf199f8
--- /dev/null
+++ b/dockerfiles/kuttl/Dockerfile
@@ -0,0 +1,161 @@
+# syntax=docker/dockerfile:1.4
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+# hadolint global ignore=DL3020
+
+ARG IMG_BASE='golang'
+ARG IMG_BASE_TAG='1.19-alpine'
+ARG BASE_IMG_ALPINE='alpine'
+ARG BASE_IMG_TAG_ALPINE='latest'
+ARG YQ_IMG='mikefarah/yq'
+ARG YQ_IMG_TAG='latest'
+
+FROM ${BASE_IMG_ALPINE}:${BASE_IMG_TAG_ALPINE} as alpine
+RUN apk add --no-cache bash~=5
+
+FROM ${YQ_IMG}:${YQ_IMG_TAG} as yq
+
+## -- Stages kubectl_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kubectl_amd64
+ARG KUBECTL_SHA_AMD64_URL
+ARG KUBECTL_SHA_AMD64
+ARG KUBECTL_BIN_AMD64_URL
+ARG KUBECTL_BIN_AMD64
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUBECTL_SHA_AMD64_URL} /tmp/
+ADD --link ${KUBECTL_BIN_AMD64_URL} /tmp/
+RUN echo "$(cat "${KUBECTL_SHA_AMD64}")  ${KUBECTL_BIN_AMD64}" | sha512sum -c
+ENV KUBECTL_BIN "${KUBECTL_BIN_AMD64}"
+
+FROM alpine as kubectl_arm64
+ARG KUBECTL_SHA_ARM64_URL
+ARG KUBECTL_SHA_ARM64
+ARG KUBECTL_BIN_ARM64_URL
+ARG KUBECTL_BIN_ARM64
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUBECTL_SHA_ARM64_URL} /tmp/
+ADD --link ${KUBECTL_BIN_ARM64_URL} /tmp/
+RUN echo "$(cat "${KUBECTL_SHA_ARM64}")  ${KUBECTL_BIN_ARM64}" | sha512sum -c
+ENV KUBECTL_BIN "${KUBECTL_BIN_ARM64}"
+
+ARG TARGETARCH
+# hadolint ignore=DL3006
+FROM kubectl_${TARGETARCH} as kubectl
+RUN mv "/tmp/${KUBECTL_BIN}" /tmp/kubectl \
+    && chmod a+x /tmp/kubectl
+
+## -- Stages kuttl_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kuttl_amd64
+ARG KUTTL_CHECKSUMS_URL
+ARG KUTTL_CHECKSUMS
+ARG KUTTL_BIN_AMD64_URL
+ARG KUTTL_BIN_AMD64
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUTTL_CHECKSUMS_URL} /tmp/
+ADD --link ${KUTTL_BIN_AMD64_URL} /tmp/
+RUN sha256sum -c <(grep "${KUTTL_BIN_AMD64}" "${KUTTL_CHECKSUMS}")
+ENV KUTTL_BIN "${KUTTL_BIN_AMD64}"
+
+FROM alpine as kuttl_arm64
+ARG KUTTL_CHECKSUMS_URL
+ARG KUTTL_CHECKSUMS
+ARG KUTTL_BIN_ARM64_URL
+ARG KUTTL_BIN_ARM64
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUTTL_CHECKSUMS_URL} /tmp/
+ADD --link ${KUTTL_BIN_ARM64_URL} /tmp/
+RUN sha256sum -c <(grep "${KUTTL_BIN_ARM64}" "${KUTTL_CHECKSUMS}")
+ENV KUTTL_BIN "${KUTTL_BIN_ARM64}"
+
+ARG TARGETARCH
+# hadolint ignore=DL3006
+FROM kuttl_${TARGETARCH} as kuttl
+RUN mv "/tmp/${KUTTL_BIN}" /tmp/kubectl-kuttl \
+    && chmod a+x /tmp/kubectl-kuttl
+
+## -- Stages kustomize_${TARGETARCH} --
+# Define stages that facilitate bringing in platform-specific binaries.
+FROM alpine as kustomize_amd64
+ARG KUSTOMIZE_CHECKSUMS_URL
+ARG KUSTOMIZE_CHECKSUMS
+ARG KUSTOMIZE_BIN_AMD64_TGZ_URL
+ARG KUSTOMIZE_BIN_AMD64_TGZ
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUSTOMIZE_CHECKSUMS_URL} /tmp/
+ADD --link ${KUSTOMIZE_BIN_AMD64_TGZ_URL} /tmp/
+RUN sha256sum -c <(grep "${KUSTOMIZE_BIN_AMD64_TGZ}" "${KUSTOMIZE_CHECKSUMS}")
+ENV KUSTOMIZE_BIN_TGZ "${KUSTOMIZE_BIN_AMD64_TGZ}"
+
+FROM alpine as kustomize_arm64
+ARG KUSTOMIZE_CHECKSUMS_URL
+ARG KUSTOMIZE_CHECKSUMS
+ARG KUSTOMIZE_BIN_ARM64_TGZ_URL
+ARG KUSTOMIZE_BIN_ARM64_TGZ
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+WORKDIR /tmp
+ADD --link ${KUSTOMIZE_CHECKSUMS_URL} /tmp/
+ADD --link ${KUSTOMIZE_BIN_ARM64_TGZ_URL} /tmp/
+RUN sha256sum -c <(grep "${KUSTOMIZE_BIN_ARM64_TGZ}" "${KUSTOMIZE_CHECKSUMS}")
+ENV KUSTOMIZE_BIN_TGZ "${KUSTOMIZE_BIN_ARM64_TGZ}"
+
+ARG TARGETARCH
+# hadolint ignore=DL3006
+FROM kustomize_${TARGETARCH} as kustomize
+RUN tar xzf "/tmp/${KUSTOMIZE_BIN_TGZ}" \
+    && chmod a+x /tmp/kustomize
+
+FROM ${IMG_BASE}:${IMG_BASE_TAG} as final
+ARG IMG_BASE
+ARG IMG_BASE_TAG
+
+COPY --from=yq /usr/bin/yq /usr/bin/yq
+COPY --from=kubectl /tmp/kubectl /usr/local/bin/
+COPY --from=kuttl /tmp/kubectl-kuttl /usr/local/bin/
+COPY --from=kustomize /tmp/kustomize /usr/local/bin/
+COPY dockerfiles/kuttl/entrypoint.sh /bin/
+
+# nonroot user as defined in https://github.com/GoogleContainerTools/distroless
+ENV NON_ROOT_USER=nonroot
+ENV NON_ROOT_USER_ID=65532
+ENV NON_ROOT_USER_HOME=/home/nonroot
+
+# hadolint ignore=DL3018
+RUN apk add --update --no-cache \
+        bash~=5 \
+        docker-cli \
+    && adduser -D -u "${NON_ROOT_USER_ID}" -h "${NON_ROOT_USER_HOME}" "${NON_ROOT_USER}"
+
+# replicate the test-related bits generated by `kubebuilder` into its Makefile.
+ENV GOBIN="${GOPATH}/bin"
+ENV ENVTEST_K8S_VERSION='1.23.x'
+RUN chmod a+x /bin/entrypoint.sh \
+    && go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
+WORKDIR "${NON_ROOT_USER_HOME}"
+USER "${NON_ROOT_USER}"
+RUN "${GOBIN}/setup-envtest" use "${ENVTEST_K8S_VERSION}"
+# disable downloading remote content henceforth
+ENV ENVTEST_INSTALLED_ONLY=true
+
+ENTRYPOINT ["/bin/entrypoint.sh"]
diff --git a/dockerfiles/kuttl/README.md b/dockerfiles/kuttl/README.md
new file mode 100644
index 0000000..a04ba5e
--- /dev/null
+++ b/dockerfiles/kuttl/README.md
@@ -0,0 +1,71 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you 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.
+-->
+
+# dockerfiles/kuttl
+
+This directory builds a docker image containing everything required to run `kubectl-kuttl`. It
+includes all the dependencies to run in "mocked control plane" mode as well as targeting a full
+cluster. This image is used as the basis for both dev and test environments.
+
+## Build
+
+Building the docker image locally is a little picky because there's lots of input arguments. These
+are managed via the [docker-bake.override.hcl](./docker-bake.override.hcl).
+
+Start by creating a buildx context that supports (optionally) multi-platform images. If you've
+created this context previously, it's enough to ensure that it's active via `docker buildx ls`.
+
+```shell
+docker buildx create \
+  --driver docker-container \
+  --platform linux/amd64,linux/arm64 \
+  --use \
+  --bootstrap
+```
+
+Finally, build the image using:
+
+```shell
+docker buildx bake \
+  --file src/main/docker/docker-bake.hcl \
+  --file src/main/docker/docker-bake.override.hcl \
+  --pull \
+  --load \
+  --set '*.platform=linux/arm64'
+```
+
+This exports an image to your local repository that is tagged as `${USER}/hbase/kustomize/kuttl:latest`.
+
+## Usage
+
+The image is configured with `kuttl` as the entrypoint.
+
+```shell
+docker container run --rm -it ${USER}/hbase/kustomize/kuttl:latest --help
+```
+
+Running tests in the image requires mounting the workspace into the container image and passing
+appropriate parameters to `kuttl`. For example, run the "small" tests like this:
+
+```shell
+docker container run \
+  --mount type=bind,source=$(pwd),target=/workspace \
+  --workdir /workspace \
+  ${USER}/hbase/kustomize/kuttl:latest \
+  --config tests/kuttl-test-small.yaml
+```
diff --git a/dockerfiles/kuttl/docker-bake.hcl b/dockerfiles/kuttl/docker-bake.hcl
new file mode 100644
index 0000000..0526f48
--- /dev/null
+++ b/dockerfiles/kuttl/docker-bake.hcl
@@ -0,0 +1,92 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# A convenience script for build the kuttl image.
+# See hbase-kubernetes-deployment/dockerfiles/kuttl/README.md
+#
+
+# input variables
+variable KUBECTL_VERSION { default = "1.24.10" }
+variable KUSTOMIZE_VERSION { default = "4.5.4" }
+variable KUTTL_VERSION { default = "0.15.0" }
+
+variable KUBECTL_SHA_AMD64_URL {}
+variable KUBECTL_SHA_AMD64 {}
+variable KUBECTL_BIN_AMD64_URL {}
+variable KUBECTL_BIN_AMD64 {}
+variable KUBECTL_SHA_ARM64_URL {}
+variable KUBECTL_SHA_ARM64 {}
+variable KUBECTL_BIN_ARM64_URL {}
+variable KUBECTL_BIN_ARM64 {}
+variable KUTTL_CHECKSUMS_URL {}
+variable KUTTL_CHECKSUMS {}
+variable KUTTL_BIN_AMD64_URL {}
+variable KUTTL_BIN_AMD64 {}
+variable KUTTL_BIN_ARM64_URL {}
+variable KUTTL_BIN_ARM64 {}
+variable KUSTOMIZE_CHECKSUMS_URL {}
+variable KUSTOMIZE_CHECKSUMS {}
+variable KUSTOMIZE_BIN_AMD64_TGZ_URL {}
+variable KUSTOMIZE_BIN_AMD64_TGZ {}
+variable KUSTOMIZE_BIN_ARM64_TGZ_URL {}
+variable KUSTOMIZE_BIN_ARM64_TGZ {}
+
+# output variables
+variable USER {
+  default = "apache"
+}
+variable IMAGE_TAG {
+  default = "latest"
+}
+variable IMAGE_NAME {
+  default = "${USER}/hbase/kustomize/kuttl"
+}
+
+group default {
+  targets = [ "kuttl" ]
+}
+
+target kuttl {
+  dockerfile = "dockerfiles/kuttl/Dockerfile"
+  args = {
+    KUBECTL_SHA_AMD64_URL = KUBECTL_SHA_AMD64_URL
+    KUBECTL_SHA_AMD64 = KUBECTL_SHA_AMD64
+    KUBECTL_BIN_AMD64_URL = KUBECTL_BIN_AMD64_URL
+    KUBECTL_BIN_AMD64 = KUBECTL_BIN_AMD64
+    KUBECTL_SHA_ARM64_URL = KUBECTL_SHA_ARM64_URL
+    KUBECTL_SHA_ARM64 = KUBECTL_SHA_ARM64
+    KUBECTL_BIN_ARM64_URL = KUBECTL_BIN_ARM64_URL
+    KUBECTL_BIN_ARM64 = KUBECTL_BIN_ARM64
+    KUTTL_CHECKSUMS_URL = KUTTL_CHECKSUMS_URL
+    KUTTL_CHECKSUMS = KUTTL_CHECKSUMS
+    KUTTL_BIN_AMD64_URL = KUTTL_BIN_AMD64_URL
+    KUTTL_BIN_AMD64 = KUTTL_BIN_AMD64
+    KUTTL_BIN_ARM64_URL = KUTTL_BIN_ARM64_URL
+    KUTTL_BIN_ARM64 = KUTTL_BIN_ARM64
+    KUSTOMIZE_CHECKSUMS_URL = KUSTOMIZE_CHECKSUMS_URL
+    KUSTOMIZE_CHECKSUMS = KUSTOMIZE_CHECKSUMS
+    KUSTOMIZE_BIN_AMD64_TGZ_URL = KUSTOMIZE_BIN_AMD64_TGZ_URL
+    KUSTOMIZE_BIN_AMD64_TGZ = KUSTOMIZE_BIN_AMD64_TGZ
+    KUSTOMIZE_BIN_ARM64_TGZ_URL = KUSTOMIZE_BIN_ARM64_TGZ_URL
+    KUSTOMIZE_BIN_ARM64_TGZ = KUSTOMIZE_BIN_ARM64_TGZ
+  }
+  target = "final"
+  platforms = [
+    "linux/amd64",
+    "linux/arm64"
+  ]
+  tags = [ "${IMAGE_NAME}:${IMAGE_TAG}" ]
+}
diff --git a/dockerfiles/kuttl/docker-bake.override.hcl b/dockerfiles/kuttl/docker-bake.override.hcl
new file mode 100644
index 0000000..bceddbb
--- /dev/null
+++ b/dockerfiles/kuttl/docker-bake.override.hcl
@@ -0,0 +1,103 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# Externalize default values of build parameters and document how to retrieve them.
+#
+
+function "basename" {
+  params = [a]
+  result = split("/", a)[length(split("/", a)) - 1]
+}
+
+variable KUBECTL_SHA_AMD64_URL {
+  default = "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl.sha512"
+}
+
+variable KUBECTL_SHA_AMD64 {
+  default = "${basename(KUBECTL_SHA_AMD64_URL)}"
+}
+
+variable KUBECTL_BIN_AMD64_URL {
+  default = "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
+}
+
+variable KUBECTL_BIN_AMD64 {
+  default = "${basename(KUBECTL_BIN_AMD64_URL)}"
+}
+
+variable KUBECTL_SHA_ARM64_URL {
+  default = "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/arm64/kubectl.sha512"
+}
+
+variable KUBECTL_SHA_ARM64 {
+  default = "${basename(KUBECTL_SHA_ARM64_URL)}"
+}
+
+variable KUBECTL_BIN_ARM64_URL {
+  default = "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/arm64/kubectl"
+}
+
+variable KUBECTL_BIN_ARM64 {
+  default = "${basename(KUBECTL_BIN_ARM64_URL)}"
+}
+
+variable KUTTL_CHECKSUMS_URL {
+  default = "https://github.com/kudobuilder/kuttl/releases/download/v${KUTTL_VERSION}/checksums.txt"
+}
+
+variable KUTTL_CHECKSUMS {
+  default = "${basename(KUTTL_CHECKSUMS_URL)}"
+}
+
+variable KUTTL_BIN_AMD64_URL {
+  default = "https://github.com/kudobuilder/kuttl/releases/download/v${KUTTL_VERSION}/kubectl-kuttl_${KUTTL_VERSION}_linux_x86_64"
+}
+
+variable KUTTL_BIN_AMD64 {
+  default = "${basename(KUTTL_BIN_AMD64_URL)}"
+}
+
+variable KUTTL_BIN_ARM64_URL {
+  default = "https://github.com/kudobuilder/kuttl/releases/download/v${KUTTL_VERSION}/kubectl-kuttl_${KUTTL_VERSION}_linux_arm64"
+}
+
+variable KUTTL_BIN_ARM64 {
+  default = "${basename(KUTTL_BIN_ARM64_URL)}"
+}
+
+variable KUSTOMIZE_CHECKSUMS_URL {
+  default = "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VERSION}/checksums.txt"
+}
+
+variable KUSTOMIZE_CHECKSUMS {
+  default = "${basename(KUSTOMIZE_CHECKSUMS_URL)}"
+}
+
+variable KUSTOMIZE_BIN_AMD64_TGZ_URL {
+  default = "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VERSION}/kustomize_v${KUSTOMIZE_VERSION}_linux_amd64.tar.gz"
+}
+
+variable KUSTOMIZE_BIN_AMD64_TGZ {
+  default = "${basename(KUSTOMIZE_BIN_AMD64_TGZ_URL)}"
+}
+
+variable KUSTOMIZE_BIN_ARM64_TGZ_URL {
+  default = "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VERSION}/kustomize_v${KUSTOMIZE_VERSION}_linux_arm64.tar.gz"
+}
+
+variable KUSTOMIZE_BIN_ARM64_TGZ {
+  default = "${basename(KUSTOMIZE_BIN_ARM64_TGZ_URL)}"
+}
diff --git a/dockerfiles/kuttl/entrypoint.sh b/dockerfiles/kuttl/entrypoint.sh
new file mode 100755
index 0000000..8436e82
--- /dev/null
+++ b/dockerfiles/kuttl/entrypoint.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+
+set -e
+set -o pipefail
+set -x
+
+declare ENVTEST_K8S_VERSION
+
+declare KUBEBUILDER_ASSETS
+KUBEBUILDER_ASSETS="$(setup-envtest use -i "${ENVTEST_K8S_VERSION}" -p path)"
+export KUBEBUILDER_ASSETS
+
+/usr/local/bin/kubectl kuttl test "$@"