mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-11-08 04:18:06 +00:00
* fix(tilt): make the dev setup work on a clean checkout and on arm64
Following tilt.md from a clean checkout failed during Tiltfile load:
Error in default_registry: validating defaultRegistry: host: Required value
The docs correctly say to leave default_registry empty for a local cluster,
where Tilt loads the image into the cluster and nothing is pushed, but
default_registry("") is rejected. Only call it when a value is set. For the
build, hack/build.sh also refuses an empty REGISTRY; that value is only the
image prefix baked into the binary, so fall back to the stock one.
Working past that, both binary builds failed with "GOBIN: unbound variable",
which hack/build.sh has required since b1d95cf2a. Pass it.
Everything was also hardcoded to amd64 -- the three binary builds, the
downloaded kubectl helper, the runtime base image, and both docker_build
calls -- so the setup was broken on an arm64 host. Resolve cluster_goarch
once, from an explicit setting, then what `kubectl get nodes` reports, then
the local architecture, and use it throughout. The local CLI build follows
the host instead, since it is meant to be run there.
The provider path deliberately does not get GOBIN: released plugins ship
their own hack/build.sh, which builds ${PKG}/${BIN} and does not require it.
Only its amd64 assumptions change here.
Finally, pin the Delve version. @latest meant the debugger could change
between rebuilds with no change to the checkout.
Verified: Tiltfile loads with an empty and a non-empty registry, with debug
on and off, continue-on-start on and off, and with an explicit
cluster_goarch override; the generated Dockerfiles carry the right arch,
dlv pin, kubectl and docker CLI URLs; the provider path was exercised
against velero-plugin-for-aws; and hack/build.sh produced an aarch64 binary
when GOARCH=arm64.
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
* docs(tilt): correct the settings reference and the examples
The settings example is not valid JSON: a trailing comma follows the azure
entry, so copying it gives a parse error on the next `tilt up`.
It also enables "csi" in enable_providers while giving it no entry under
providers, so the example advertises a provider it does not define.
provider_repos is documented as a settings field but nothing reads it; the
list of plugins to load is providers. Replace it with cluster_goarch, which
the Tiltfile does read, and say what an empty default_registry means, since
leaving it empty is what a local cluster wants.
The Tilt version floor moves to v0.30.0, the first with
docker_build(platform=...), without which the arm64 support does not load.
Drop the Kubernetes v1.16 floor, which no longer means anything here.
The example deployment gets 3Gi when debugging. delve indexes the DWARF of
the unoptimized binary, and against a 512Mi limit the container is killed
before the debugger finishes starting.
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
* changelog: add an entry for the Tilt dev setup fixes
The filename is keyed to the PR number, which only exists once the PR does.
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
* fix(tilt): use pullable MinIO images in the dev setup example
The example tilt-settings.json ships "setup-minio": true, and tilt.md tells
contributors that this creates "a running instance of MinIO inside your
cluster", after which they can "create backups/restores and fully operate
Velero". That is no longer reachable: minio/minio:latest and minio/mc:latest
are no longer pullable from Docker Hub, so the MinIO deployment and its setup
Job both sit in ImagePullBackOff and no backup storage location can validate.
$ docker pull minio/minio:latest
Error response from daemon: {"message":"denied: requested access to the
resource is denied"}
The kind e2e workflow already stopped using these images and builds MinIO from
a reviewed bitnami/containers commit instead. Follow the same namespace here
rather than building from source, since this example runs on a contributor's
laptop: the bitnami legacy mirrors are pullable and need no Dockerfile.
bitnami splits the server and client into separate images, so the setup Job's
minio/mc must move to bitnamilegacy/minio-client, which provides mc on PATH.
Verified both images pull, run as non-root against the emptyDir mounts, and
that the Job completes ("Bucket created successfully `velero/velero`"). With
these images the backup storage location reports Available and a backup
completes and lands in the bucket.
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
* fix(tilt): extract kubectl where the Dockerfile copies it from
The helper stage unpacks the kubectl tarball without -C, so it lands in the
golang image's WORKDIR (/go) rather than /tmp, but the COPY that follows reads
from /tmp. The build fails with:
checking on sources under ".../tmp/kubernetes/client/bin/kubectl"
Unpack to /tmp, matching the docker CLI download on the next line and the
COPY --from path.
While here, note next to the dlv pin that it has to move with the golang
image: delve refuses a binary built by a newer Go than it understands
("Version of Delve is too old for Go version go1.x.y"), so the pin goes stale
quietly on the next Go bump.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
* fix(tilt): glob the CRDs instead of listing them
The hardcoded list has to be edited whenever a branch adds a CRD, and silently
drops it from the cluster until someone notices. Glob config/crd/*/bases/*.yaml
instead; it resolves to the same 13 files today.
The glob is a local() call, and Tilt refuses local() while the current kube
context might be a production one, so the k8s_yaml() sits after
allow_k8s_contexts() rather than at the top of the file with the other
manifests.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Note: Posted using claude code
Model: rits/deepseek-ai/DeepSeek-V4.1-Flash-1017
Signed-off-by: Joseph <jvaikath@redhat.com>
---------
Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph Antony Vaikath <jvaikath@redhat.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
314 lines
12 KiB
Python
314 lines
12 KiB
Python
# -*- mode: Python -*-
|
|
|
|
# The CRDs are globbed rather than listed, so that a dev branch adding one is
|
|
# picked up without editing this file. Globbing needs a local() call, which Tilt
|
|
# refuses while the current kube context might be a production one, so the
|
|
# k8s_yaml() for it lives below allow_k8s_contexts().
|
|
|
|
# default values
|
|
settings = {
|
|
"default_registry": "docker.io/velero",
|
|
"use_node_agent": False,
|
|
"enable_debug": False,
|
|
"debug_continue_on_start": True, # Continue the velero process by default when in debug mode
|
|
"create_backup_locations": False,
|
|
"setup-minio": False,
|
|
# Both are detected when left unset; set them only to override:
|
|
# cluster_goarch: "amd64" or "arm64" -- the target cluster's node arch
|
|
}
|
|
|
|
# global settings
|
|
settings.update(read_json(
|
|
"tilt-resources/tilt-settings.json",
|
|
default = {},
|
|
))
|
|
|
|
k8s_yaml(kustomize('tilt-resources'))
|
|
k8s_yaml('tilt-resources/deployment.yaml')
|
|
if settings.get("enable_debug"):
|
|
k8s_resource('velero', port_forwards = '2345')
|
|
# TODO: Need to figure out how to apply port forwards for all node-agent pods
|
|
if settings.get("use_node_agent"):
|
|
k8s_yaml('tilt-resources/node-agent.yaml')
|
|
if settings.get("create_backup_locations"):
|
|
k8s_yaml('tilt-resources/velero_v1_backupstoragelocation.yaml')
|
|
if settings.get("setup-minio"):
|
|
k8s_yaml('examples/minio/00-minio-deployment.yaml', allow_duplicates = True)
|
|
|
|
# By default, Tilt automatically allows Minikube, Docker for Desktop, Microk8s, Red Hat CodeReady Containers, Kind, K3D, and Krucible.
|
|
allow_k8s_contexts(settings.get("allowed_contexts"))
|
|
|
|
# Every CRD under config/crd, so a branch that adds one needs no edit here.
|
|
# Deliberately after allow_k8s_contexts(): see the note at the top of the file.
|
|
k8s_yaml(str(local('ls config/crd/*/bases/*.yaml', quiet = True, echo_off = True)).splitlines())
|
|
|
|
# An empty registry means "local cluster, don't push" (kind loads the image
|
|
# directly), and Tilt rejects default_registry("") as a missing host.
|
|
if settings.get("default_registry"):
|
|
default_registry(settings.get("default_registry"))
|
|
|
|
local_goos = str(local("go env GOOS", quiet = True, echo_off = True)).strip()
|
|
local_goarch = str(local("go env GOARCH", quiet = True, echo_off = True)).strip()
|
|
git_sha = str(local("git rev-parse HEAD", quiet = True, echo_off = True)).strip()
|
|
|
|
|
|
def detect_cluster_goarch():
|
|
"""
|
|
Best-effort node architecture of the target cluster.
|
|
|
|
Every binary in the image and the base image must match the node arch, and
|
|
getting it wrong shows up only later as an "exec format error" in the pod.
|
|
The cluster usually knows the answer, so ask it. Any failure (no cluster
|
|
yet, no nodes, kubectl missing) yields "" and the caller falls back to the
|
|
local architecture, which is correct when the cluster shares the machine
|
|
(kind, minikube, Docker Desktop).
|
|
"""
|
|
probe = "kubectl get nodes -o jsonpath='{.items[0].status.nodeInfo.architecture}' 2>/dev/null || true"
|
|
return str(local(probe, quiet = True, echo_off = True)).strip()
|
|
|
|
|
|
cluster_goarch = settings.get("cluster_goarch") or detect_cluster_goarch() or local_goarch
|
|
|
|
|
|
def get_build_registry():
|
|
"""
|
|
Value for hack/build.sh's REGISTRY, which refuses an empty one. It is only
|
|
baked into the binary as the default image prefix; it is not where Tilt
|
|
pushes. An empty default_registry means "local cluster, don't push", so
|
|
fall back to the stock prefix for the build.
|
|
"""
|
|
return settings.get("default_registry") or "docker.io/velero"
|
|
|
|
|
|
# Docker's static CLI download archives use their own arch names.
|
|
docker_cli_arch = {"amd64": "x86_64", "arm64": "aarch64"}.get(cluster_goarch, cluster_goarch)
|
|
|
|
print("Tilt: cluster_goarch={} (local {})".format(cluster_goarch, local_goarch))
|
|
|
|
tilt_helper_dockerfile_header = """
|
|
# Tilt image
|
|
FROM golang:1.27-trixie as tilt-helper
|
|
|
|
# Support live reloading with Tilt
|
|
RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/restart.sh && \
|
|
wget --output-document /start.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/start.sh && \
|
|
chmod +x /start.sh && chmod +x /restart.sh
|
|
"""
|
|
|
|
# Pinned so the debugger in the image does not change under you between
|
|
# builds; @latest made every rebuild a different dlv.
|
|
#
|
|
# Delve refuses a binary built by a newer Go than it understands ("Version of
|
|
# Delve is too old for Go version go1.x.y"), so this pin has to move together
|
|
# with the golang image below.
|
|
DLV_VERSION = "v1.27.2"
|
|
|
|
additional_docker_helper_commands = """
|
|
# Install delve to allow debugging. A cross-compiled `go install` places the
|
|
# binary in $GOPATH/bin/linux_<arch>/ rather than $GOPATH/bin/.
|
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=%s go install github.com/go-delve/delve/cmd/dlv@%s && \\
|
|
if [ -x "$(go env GOPATH)/bin/dlv" ]; then cp "$(go env GOPATH)/bin/dlv" /usr/local/bin/dlv; \\
|
|
else cp "$(go env GOPATH)/bin/linux_%s/dlv" /usr/local/bin/dlv; fi
|
|
|
|
RUN wget -qO- https://dl.k8s.io/v1.25.2/kubernetes-client-linux-%s.tar.gz | tar xvz -C /tmp
|
|
RUN wget -qO- https://download.docker.com/linux/static/stable/%s/docker-27.5.1.tgz | tar xvz -C /tmp && \\
|
|
install -D /tmp/docker/docker /usr/local/bin/docker
|
|
""" % (cluster_goarch, DLV_VERSION, cluster_goarch, cluster_goarch, docker_cli_arch)
|
|
|
|
additional_docker_build_commands = """
|
|
COPY --from=tilt-helper /usr/local/bin/dlv /usr/bin/dlv
|
|
COPY --from=tilt-helper /usr/local/bin/docker /usr/bin/docker
|
|
COPY --from=tilt-helper /tmp/kubernetes/client/bin/kubectl /usr/bin/kubectl
|
|
"""
|
|
|
|
##############################
|
|
# Setup Velero
|
|
##############################
|
|
|
|
def get_debug_flag():
|
|
"""
|
|
Returns the flag to enable debug building of Velero if debug
|
|
mode is enabled.
|
|
"""
|
|
|
|
if settings.get('enable_debug'):
|
|
return "DEBUG=1"
|
|
return ""
|
|
|
|
|
|
# Set up a local_resource build of the Velero binary. The binary is written to _tiltbuild/velero.
|
|
# GOBIN is required by hack/build.sh and is not otherwise set in a fresh shell.
|
|
local_resource(
|
|
"velero_server_binary",
|
|
cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild;PKG=. BIN=velero GOBIN=$(pwd)/_tiltbuild GOOS=linux GOARCH=' + cluster_goarch + ' GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild ' + get_debug_flag() + ' REGISTRY=' + get_build_registry() + ' ./hack/build.sh',
|
|
deps = ["cmd", "internal", "pkg"],
|
|
ignore = ["pkg/cmd"],
|
|
)
|
|
|
|
local_resource(
|
|
"velero_local_binary",
|
|
cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild/local;PKG=. BIN=velero GOBIN=$(pwd)/_tiltbuild/local GOOS=' + local_goos + ' GOARCH=' + local_goarch + ' GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild/local ' + get_debug_flag() + ' REGISTRY=' + get_build_registry() + ' ./hack/build.sh',
|
|
deps = ["internal", "pkg/cmd"],
|
|
)
|
|
|
|
# Note: we need a distro with a bash shell to exec into the Velero container.
|
|
# The runtime stage is built for the cluster's architecture; its apt-get RUN
|
|
# executes under emulation (Rosetta/qemu) when that differs from the build
|
|
# machine's.
|
|
tilt_dockerfile_header = """
|
|
FROM --platform=linux/%s ubuntu:22.04 as tilt
|
|
|
|
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y ca-certificates tzdata && rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /
|
|
COPY --from=tilt-helper /start.sh .
|
|
COPY --from=tilt-helper /restart.sh .
|
|
COPY velero .
|
|
""" % cluster_goarch
|
|
|
|
dockerfile_contents = "\n".join([
|
|
tilt_helper_dockerfile_header,
|
|
additional_docker_helper_commands,
|
|
tilt_dockerfile_header,
|
|
additional_docker_build_commands,
|
|
])
|
|
|
|
def get_velero_entrypoint():
|
|
"""
|
|
Returns the entrypoint for the Velero container image.
|
|
"""
|
|
|
|
entrypoint = ["sh", "/start.sh"]
|
|
|
|
if settings.get("enable_debug"):
|
|
# If debug mode is enabled, start the velero process using Delve
|
|
entrypoint.extend(
|
|
["dlv", "--listen=:2345", "--headless=true", "--api-version=2", "--accept-multiclient", "exec"])
|
|
|
|
# Set whether or not to continue the debugged process on start
|
|
# See https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_exec.md
|
|
if settings.get("debug_continue_on_start"):
|
|
entrypoint.append("--continue")
|
|
|
|
entrypoint.append("--")
|
|
|
|
entrypoint.append("/velero")
|
|
|
|
return entrypoint
|
|
|
|
|
|
# Set up an image build for Velero. The live update configuration syncs the output from the local_resource
|
|
# build into the container.
|
|
docker_build(
|
|
ref = "velero/velero",
|
|
context = "_tiltbuild",
|
|
dockerfile_contents = dockerfile_contents,
|
|
target = "tilt",
|
|
platform = "linux/" + cluster_goarch,
|
|
entrypoint = get_velero_entrypoint(),
|
|
live_update = [
|
|
sync("./_tiltbuild/velero", "/velero"),
|
|
run("sh /restart.sh"),
|
|
])
|
|
|
|
|
|
##############################
|
|
# Setup plugins
|
|
##############################
|
|
|
|
def load_provider_tiltfiles():
|
|
all_providers = settings.get("providers", {})
|
|
enable_providers = settings.get("enable_providers", [])
|
|
providers = []
|
|
|
|
## Load settings only for providers to enable
|
|
for name in enable_providers:
|
|
repo = all_providers.get(name)
|
|
if not repo:
|
|
print("Enabled provider '{}' does not exist in list of supported providers".format(name))
|
|
continue
|
|
file = repo + "/tilt-provider.json"
|
|
if not os.path.exists(file):
|
|
print("Provider settings not found for \"{}\". Please ensure this plugin repository has a tilt-provider.json file included.".format(name))
|
|
continue
|
|
provider_details = read_json(file, default = {})
|
|
if type(provider_details) == "dict":
|
|
provider_details["name"] = name
|
|
if "context" in provider_details:
|
|
provider_details["context"] = os.path.join(repo, "/", provider_details["context"])
|
|
else:
|
|
provider_details["context"] = repo
|
|
if "go_main" not in provider_details:
|
|
provider_details["go_main"] = "main.go"
|
|
providers.append(provider_details)
|
|
|
|
return providers
|
|
|
|
|
|
# Enable each provider
|
|
def enable_providers(providers):
|
|
if not providers:
|
|
print("No providers to enable.")
|
|
return
|
|
for p in providers:
|
|
enable_provider(p)
|
|
|
|
|
|
# Configures a provider by doing the following:
|
|
#
|
|
# 1. Enables a local_resource go build of the provider's local binary
|
|
# 2. Configures a docker build for the provider, with live updating of the local binary
|
|
def enable_provider(provider):
|
|
name = provider.get("name")
|
|
plugin_name = provider.get("plugin_name")
|
|
|
|
# Note: we need a distro with a shell to do a copy of the plugin binary
|
|
tilt_dockerfile_header = """
|
|
FROM --platform=linux/""" + cluster_goarch + """ ubuntu:22.04 as tilt
|
|
WORKDIR /
|
|
COPY --from=tilt-helper /start.sh .
|
|
COPY --from=tilt-helper /restart.sh .
|
|
COPY """ + plugin_name + """ .
|
|
"""
|
|
|
|
dockerfile_contents = "\n".join([
|
|
tilt_helper_dockerfile_header,
|
|
additional_docker_helper_commands,
|
|
tilt_dockerfile_header,
|
|
additional_docker_build_commands,
|
|
])
|
|
|
|
context = provider.get("context")
|
|
go_main = provider.get("go_main", "main.go")
|
|
|
|
live_reload_deps = []
|
|
for d in provider.get("live_reload_deps", []):
|
|
live_reload_deps.append(os.path.join(context, "/", d))
|
|
|
|
# Set up a local_resource build of the plugin binary. The main.go path must be provided via go_main option. The binary is written to _tiltbuild/<NAME>.
|
|
local_resource(
|
|
name + "_plugin",
|
|
cmd = 'cd ' + context + ';mkdir -p _tiltbuild;PKG=' + context + ' BIN=' + go_main + ' GOOS=linux GOARCH=' + cluster_goarch + ' OUTPUT_DIR=_tiltbuild ./hack/build.sh',
|
|
deps = live_reload_deps,
|
|
)
|
|
|
|
# Set up an image build for the plugin. The live update configuration syncs the output from the local_resource
|
|
# build into the init container, and that restarts the Velero container.
|
|
docker_build(
|
|
ref = provider.get("image"),
|
|
context = os.path.join(context, "/_tiltbuild/"),
|
|
dockerfile_contents = dockerfile_contents,
|
|
target = "tilt",
|
|
entrypoint = ["/bin/bash", "-c", "cp /" + plugin_name + " /target/."],
|
|
live_update = [
|
|
sync(os.path.join(context, "/_tiltbuild/", plugin_name), os.path.join("/", plugin_name))
|
|
]
|
|
)
|
|
|
|
|
|
##############################
|
|
# Start
|
|
#############################
|
|
|
|
enable_providers(load_provider_tiltfiles())
|