diff --git a/Tiltfile b/Tiltfile index 4f596526c..0bc5e0019 100644 --- a/Tiltfile +++ b/Tiltfile @@ -1,25 +1,27 @@ # -*- mode: Python -*- k8s_yaml([ -'config/crd/bases/velero.io_backups.yaml', -'config/crd/bases/velero.io_backupstoragelocations.yaml', -'config/crd/bases/velero.io_deletebackuprequests.yaml', -'config/crd/bases/velero.io_downloadrequests.yaml', -'config/crd/bases/velero.io_podvolumebackups.yaml', -'config/crd/bases/velero.io_podvolumerestores.yaml', -'config/crd/bases/velero.io_resticrepositories.yaml', -'config/crd/bases/velero.io_restores.yaml', -'config/crd/bases/velero.io_schedules.yaml', -'config/crd/bases/velero.io_serverstatusrequests.yaml', -'config/crd/bases/velero.io_volumesnapshotlocations.yaml', + 'config/crd/bases/velero.io_backups.yaml', + 'config/crd/bases/velero.io_backupstoragelocations.yaml', + 'config/crd/bases/velero.io_deletebackuprequests.yaml', + 'config/crd/bases/velero.io_downloadrequests.yaml', + 'config/crd/bases/velero.io_podvolumebackups.yaml', + 'config/crd/bases/velero.io_podvolumerestores.yaml', + 'config/crd/bases/velero.io_resticrepositories.yaml', + 'config/crd/bases/velero.io_restores.yaml', + 'config/crd/bases/velero.io_schedules.yaml', + 'config/crd/bases/velero.io_serverstatusrequests.yaml', + 'config/crd/bases/velero.io_volumesnapshotlocations.yaml', ]) # default values settings = { - "default_registry": "", - "enable_restic": False, - "create_backup_locations": False, - "setup-minio": False, + "default_registry": "", + "enable_restic": 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, } # global settings @@ -30,23 +32,26 @@ settings.update(read_json( 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 restic pods if settings.get("enable_restic"): k8s_yaml('tilt-resources/restic.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) + 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")) default_registry(settings.get("default_registry")) -local_goos = str(local("go env GOOS", quiet=True, echo_off=True)).strip() -git_sha = str(local("git rev-parse HEAD", quiet=True, echo_off=True)).strip() - +local_goos = str(local("go env GOOS", quiet = True, echo_off = True)).strip() +git_sha = str(local("git rev-parse HEAD", quiet = True, echo_off = True)).strip() tilt_helper_dockerfile_header = """ # Tilt image FROM golang:1.15.3 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 && \ @@ -54,11 +59,15 @@ RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com """ additional_docker_helper_commands = """ +# Install delve to allow debugging +RUN go get github.com/go-delve/delve/cmd/dlv + RUN wget -qO- https://dl.k8s.io/v1.19.2/kubernetes-client-linux-amd64.tar.gz | tar xvz RUN wget -qO- https://get.docker.com | sh """ additional_docker_build_commands = """ +COPY --from=tilt-helper /go/bin/dlv /usr/bin/dlv COPY --from=tilt-helper /usr/bin/docker /usr/bin/docker COPY --from=tilt-helper /go/kubernetes/client/bin/kubectl /usr/bin/kubectl """ @@ -76,17 +85,28 @@ RUN mkdir -p /output/usr/bin && \ # 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. local_resource( "velero_server_binary", - cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild;PKG=. BIN=velero GOOS=linux GOARCH=amd64 GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild ./hack/build.sh', + cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild;PKG=. BIN=velero GOOS=linux GOARCH=amd64 GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild ' + get_debug_flag() + ' ./hack/build.sh', deps = ["cmd", "internal", "pkg"], ignore = ["pkg/cmd"], ) local_resource( "velero_local_binary", - cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild/local;PKG=. BIN=velero GOOS=' + local_goos + ' GOARCH=amd64 GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild/local ./hack/build.sh', + cmd = 'cd ' + '.' + ';mkdir -p _tiltbuild/local;PKG=. BIN=velero GOOS=' + local_goos + ' GOARCH=amd64 GIT_SHA=' + git_sha + ' VERSION=main GIT_TREE_STATE=dirty OUTPUT_DIR=_tiltbuild/local ' + get_debug_flag() + ' ./hack/build.sh', deps = ["internal", "pkg/cmd"], ) @@ -107,34 +127,60 @@ dockerfile_contents = "\n".join([ docker_build_download_restic_commands, ]) - # Set up an image build for Velero. The live update configuration syncs the output from the local_resource - # build into the container. + +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 = ".", dockerfile_contents = dockerfile_contents, target = "tilt", - entrypoint=["sh", "/start.sh", "/velero"], - live_update=[ + 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", {}) + all_providers = settings.get("providers", {}) enable_providers = settings.get("enable_providers", []) - 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 + 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)) @@ -152,6 +198,7 @@ def load_provider_tiltfiles(): return providers + # Enable each provider def enable_providers(providers): if not providers: @@ -160,6 +207,7 @@ def enable_providers(providers): 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 @@ -205,12 +253,13 @@ def enable_provider(provider): context = os.path.join(context, "/_tiltbuild/"), dockerfile_contents = dockerfile_contents, target = "tilt", - entrypoint=["/bin/bash", "-c", "cp /" + plugin_name + " /target/."], - live_update=[ + entrypoint = ["/bin/bash", "-c", "cp /" + plugin_name + " /target/."], + live_update = [ sync(os.path.join(context, "/_tiltbuild/", plugin_name), os.path.join("/", plugin_name)) ] ) + ############################## # Start ############################# diff --git a/hack/build.sh b/hack/build.sh index c28403fdf..d5492887c 100755 --- a/hack/build.sh +++ b/hack/build.sh @@ -51,6 +51,11 @@ if [[ -z "${GIT_TREE_STATE}" ]]; then exit 1 fi +GCFLAGS="" +if [[ ${DEBUG:-} = "1" ]]; then + GCFLAGS="all=-N -l" +fi + export CGO_ENABLED=0 LDFLAGS="-X ${PKG}/pkg/buildinfo.Version=${VERSION}" @@ -67,6 +72,7 @@ fi go build \ -o ${OUTPUT} \ + -gcflags "${GCFLAGS}" \ -installsuffix "static" \ -ldflags "${LDFLAGS}" \ - ${PKG}/cmd/${BIN} \ No newline at end of file + ${PKG}/cmd/${BIN} diff --git a/site/content/docs/main/tilt.md b/site/content/docs/main/tilt.md index ac0bd52b8..917240bcf 100644 --- a/site/content/docs/main/tilt.md +++ b/site/content/docs/main/tilt.md @@ -27,6 +27,7 @@ files in this directory are gitignored so you may configure your setup according 1. Clone any [provider plugin(s)](https://velero.io/plugins/) you want to make changes to and deploy (optional, must be configured to be deployed by the Velero Tilt's setup, [more info below](#provider-plugins)) Note: To properly configure any plugin you use, please follow the plugin's documentation. + ## Getting started ### tl;dr @@ -61,7 +62,9 @@ Here is an example: ], "enable_restic": false, "create_backup_locations": true, - "setup-minio": true + "setup-minio": true, + "enable_debug": false, + "debug_continue_on_start": true } ``` @@ -85,7 +88,11 @@ containing the configuration of the Velero restic DaemonSet. **create_backup_locations** (Bool, default=false): Indicate whether to create one or more backup storage locations. If set to `true`, Tilt will look for a `velero/tilt-resources/velero_v1_backupstoragelocation.yaml` file containing at least one configuration for a Velero backup storage location. -**setup-minio** (Bool, default=false): Configure this to `true` if you want to configure backup storage locations in a Minio instance running inside your cluster. +**setup-minio** (Bool, default=false): Configure this to `true` if you want to configure backup storage locations in a Minio instance running inside your cluster. + +**enable_debug** (Bool, default=false): Configure this to `true` if you want to debug the velero process using [Delve](https://github.com/go-delve/delve). + +**debug_continue_on_start** (Bool, default=true): Configure this to `true` if you want the velero process to continue on start when in debug mode. See [Delve CLI documentation](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv.md). ### Create Kubernetes resource files to deploy All needed Kubernetes resource files are provided as ready to use samples in the `velero/tilt-resources/examples` directory. You only have to move them to the `velero/tilt-resources` level. @@ -140,6 +147,26 @@ to learn what field/value pairs are required for your provider's credentials. Th There is a sample credentials file properly formatted for a MinIO storage credentials in `velero/tilt-resources/examples/cloud`. +### Configure debugging with Delve +If you would like to debug the Velero process, you can enable debug mode by setting the field `enable_debug` to `true` in your `tilt-resources/tile-settings.json` file. +This will enable you to debug the process using [Delve](https://github.com/go-delve/delve). +By enabling debug mode, the Velero executable will be built in debug mode (using the flags `-gcflags="-N -l"` which disables optimizations and inlining), and the process will be started in the Velero deployment using [`dlv exec`](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_exec.md). + +The debug server will accept connections on port 2345 and Tilt is configured to forward this port to the local machine. +Once Tilt is [running](#run-tilt) and the Velero resource is ready, you can connect to the debug server to begin debugging. +To connect to the session, you can use the Delve CLI locally by running `dlv connect 127.0.0.1:2345`. See the [Delve CLI documentation](https://github.com/go-delve/delve/tree/master/Documentation/cli) for more guidance on how to use Delve. +Delve can also be used within a number of [editors and IDEs](https://github.com/go-delve/delve/blob/master/Documentation/EditorIntegration.md). + +By default, the Velero process will continue on start when in debug mode. +This means that the process will run until a breakpoint is set. +You can disable this by setting the field `debug_continue_on_start` to `false` in your `tilt-resources/tile-settings.json` file. +When this setting is disabled, the Velero process will not continue to run until a `continue` instruction is issued through your Delve session. + +When exiting your debug session, the CLI and editor integrations will typically ask if the remote process should be stopped. +It is important to leave the remote process running and just disconnect from the debugging session. +By stopping the remote process, that will cause the Velero container to stop and the pod to restart. +If backups are in progress, these will be left in a stale state as they are not resumed when the Velero pod restarts. + ### Run Tilt! To launch your development environment, run: @@ -176,4 +203,4 @@ Each provider plugin configured to be deployed by Velero's Tilt setup has a `liv should monitor for changes. When a dependency is modified, Tilt rebuilds the provider's binary **on your local machine**, copies the binary to the init container, and triggers a restart of the Velero container. This is significantly faster than rebuilding the container image for each change. It also helps keep the size of each development image as small as -possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.). \ No newline at end of file +possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.). diff --git a/site/content/docs/v1.5/tilt.md b/site/content/docs/v1.5/tilt.md index ac0bd52b8..be335a497 100644 --- a/site/content/docs/v1.5/tilt.md +++ b/site/content/docs/v1.5/tilt.md @@ -61,7 +61,9 @@ Here is an example: ], "enable_restic": false, "create_backup_locations": true, - "setup-minio": true + "setup-minio": true, + "enable_debug": false, + "debug_continue_on_start": true } ``` @@ -85,7 +87,11 @@ containing the configuration of the Velero restic DaemonSet. **create_backup_locations** (Bool, default=false): Indicate whether to create one or more backup storage locations. If set to `true`, Tilt will look for a `velero/tilt-resources/velero_v1_backupstoragelocation.yaml` file containing at least one configuration for a Velero backup storage location. -**setup-minio** (Bool, default=false): Configure this to `true` if you want to configure backup storage locations in a Minio instance running inside your cluster. +**setup-minio** (Bool, default=false): Configure this to `true` if you want to configure backup storage locations in a Minio instance running inside your cluster. + +**enable_debug** (Bool, default=false): Configure this to `true` if you want to debug the velero process using [Delve](https://github.com/go-delve/delve). + +**debug_continue_on_start** (Bool, default=true): Configure this to `true` if you want the velero process to continue on start when in debug mode. See [Delve CLI documentation](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv.md). ### Create Kubernetes resource files to deploy All needed Kubernetes resource files are provided as ready to use samples in the `velero/tilt-resources/examples` directory. You only have to move them to the `velero/tilt-resources` level. @@ -140,6 +146,26 @@ to learn what field/value pairs are required for your provider's credentials. Th There is a sample credentials file properly formatted for a MinIO storage credentials in `velero/tilt-resources/examples/cloud`. +### Configure debugging with Delve +If you would like to debug the Velero process, you can enable debug mode by setting the field `enable_debug` to `true` in your `tilt-resources/tile-settings.json` file. +This will enable you to debug the process using [Delve](https://github.com/go-delve/delve). +By enabling debug mode, the Velero executable will be built in debug mode (using the flags `-gcflags="-N -l"` which disables optimizations and inlining), and the process will be started in the Velero deployment using [`dlv exec`](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_exec.md). + +The debug server will accept connections on port 2345 and Tilt is configured to forward this port to the local machine. +Once Tilt is [running](#run-tilt) and the Velero resource is ready, you can connect to the debug server to begin debugging. +To connect to the session, you can use the Delve CLI locally by running `dlv connect 127.0.0.1:2345`. See the [Delve CLI documentation](https://github.com/go-delve/delve/tree/master/Documentation/cli) for more guidance on how to use Delve. +Delve can also be used within a number of [editors and IDEs](https://github.com/go-delve/delve/blob/master/Documentation/EditorIntegration.md). + +By default, the Velero process will continue on start when in debug mode. +This means that the process will run until a breakpoint is set. +You can disable this by setting the field `debug_continue_on_start` to `false` in your `tilt-resources/tile-settings.json` file. +When this setting is disabled, the Velero process will not continue to run until a `continue` instruction is issued through your Delve session. + +When exiting your debug session, the CLI and editor integrations will typically ask if the remote process should be stopped. +It is important to leave the remote process running and just disconnect from the debugging session. +By stopping the remote process, that will cause the Velero container to stop and the pod to restart. +If backups are in progress, these will be left in a stale state as they are not resumed when the Velero pod restarts. + ### Run Tilt! To launch your development environment, run: @@ -176,4 +202,4 @@ Each provider plugin configured to be deployed by Velero's Tilt setup has a `liv should monitor for changes. When a dependency is modified, Tilt rebuilds the provider's binary **on your local machine**, copies the binary to the init container, and triggers a restart of the Velero container. This is significantly faster than rebuilding the container image for each change. It also helps keep the size of each development image as small as -possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.). \ No newline at end of file +possible (the container images do not need the entire go toolchain, source code, module dependencies, etc.). diff --git a/tilt-resources/examples/deployment.yaml b/tilt-resources/examples/deployment.yaml index 451e86073..292966a75 100644 --- a/tilt-resources/examples/deployment.yaml +++ b/tilt-resources/examples/deployment.yaml @@ -49,6 +49,8 @@ spec: ports: - containerPort: 8085 name: metrics + - containerPort: 2345 + name: delve resources: limits: cpu: "1" @@ -128,4 +130,4 @@ metadata: labels: component: velero name: velero -spec: {} \ No newline at end of file +spec: {} diff --git a/tilt-resources/examples/tilt-settings.json b/tilt-resources/examples/tilt-settings.json index 84247adfe..ffdb37b30 100644 --- a/tilt-resources/examples/tilt-settings.json +++ b/tilt-resources/examples/tilt-settings.json @@ -17,5 +17,7 @@ ], "enable_restic": false, "create_backup_locations": true, - "setup-minio": true + "setup-minio": true, + "enable_debug": false, + "debug_continue_on_start": true } \ No newline at end of file