diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 53681db761..5659aecb5a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -41,3 +41,11 @@ updates: open-pull-requests-limit: 3 schedule: interval: daily + groups: + github-actions: + patterns: + - "^actions/*" + - "^github/codeql-action" + docker: + patterns: + - "docker/*" diff --git a/.github/workflows/atlas-image-build.yaml b/.github/workflows/atlas-image-build.yaml index c3655d7e46..0c73418342 100644 --- a/.github/workflows/atlas-image-build.yaml +++ b/.github/workflows/atlas-image-build.yaml @@ -18,10 +18,10 @@ jobs: outputs: changed: ${{ steps.changed-files.outputs.any_changed }} steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 0 - - uses: tj-actions/changed-files@41960309398d165631f08c5df47a11147e14712b # v39.1.2 + - uses: tj-actions/changed-files@db153baf731265ad02cd490b07f470e2d55e3345 # v39.2.1 name: Get changed files id: changed-files with: diff --git a/.github/workflows/dependendy-review.yml b/.github/workflows/dependendy-review.yml index cea9a68264..a09919aa5f 100644 --- a/.github/workflows/dependendy-review.yml +++ b/.github/workflows/dependendy-review.yml @@ -15,6 +15,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: 'Dependency Review' uses: actions/dependency-review-action@v3 diff --git a/.github/workflows/grype-vulnerability-scanner.yaml b/.github/workflows/grype-vulnerability-scanner.yaml index 44c19a3239..a913484c9b 100644 --- a/.github/workflows/grype-vulnerability-scanner.yaml +++ b/.github/workflows/grype-vulnerability-scanner.yaml @@ -7,7 +7,7 @@ jobs: - name: Create repo directory before checking out latest code run: mkdir -p repo - name: Checkout the latest code - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: ref: master path: repo @@ -51,7 +51,7 @@ jobs: - name: Create repo directory before checking out latest code run: mkdir -p repo - name: Checkout the latest code - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: ref: master path: repo diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 178dfb11b0..127151eee3 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -9,7 +9,7 @@ jobs: gomod: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - run: make go-mod-tidy - run: make go-mod-download - run: tar -cvf ./src.tar.gz ./ # preserve file permissions diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 171cad36a3..60268e978d 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -26,12 +26,12 @@ jobs: steps: - name: "Checkout repo" - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0 with: results_file: results.sarif results_format: sarif @@ -39,7 +39,7 @@ jobs: - # Upload the results to GitHub's code scanning dashboard. name: "Upload to results to dashboard" - uses: github/codeql-action/upload-sarif@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8 + uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9 with: sarif_file: results.sarif - diff --git a/.gitignore b/.gitignore index 608bec7637..384cc3e88d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /bin /dist **/*.swp +/.idea diff --git a/.goreleaser.yml b/.goreleaser.yml index 2590b4a84f..c13681d886 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -62,9 +62,9 @@ dockers: dockerfile: 'docker/tools/Dockerfile' build_flag_templates: - "--build-arg=kan_tools_version={{ .Tag }}" -# Refers to https://github.com/kopia/kopia/commit/3551f743d762f2ffe669523272d1c8d734120b79 - - "--build-arg=kopia_build_commit=3551f74" - - "--build-arg=kopia_repo_org=kopia" +# Refers to https://github.com/kastenhq/kopia/commit/663cbad414207f077c666637fabfb22b47855959 + - "--build-arg=kopia_build_commit=663cbad" + - "--build-arg=kopia_repo_org=kastenhq" extra_files: - 'LICENSE' - ids: diff --git a/Dockerfile.in b/Dockerfile.in index 8182913e3b..61616f9bab 100644 --- a/Dockerfile.in +++ b/Dockerfile.in @@ -1,4 +1,4 @@ -ARG base_image=registry.access.redhat.com/ubi9/ubi-minimal:9.2-750 +ARG base_image=registry.access.redhat.com/ubi9/ubi-minimal:9.2-750.1697534106 FROM ${base_image} ARG kanister_version diff --git a/Makefile b/Makefile index 12e816e5c8..4d922beb10 100644 --- a/Makefile +++ b/Makefile @@ -41,8 +41,6 @@ PWD := $$(pwd) # Whether to build inside a containerized build environment DOCKER_BUILD ?= "true" -DOCKER_CONFIG ?= "$(HOME)/.docker" - # Mention the vm-driver that should be used to install OpenShift vm-driver ?= "kvm" @@ -62,11 +60,6 @@ IMAGE_NAME := $(BIN) IMAGE := $(REGISTRY)/$(IMAGE_NAME) -BUILD_IMAGE ?= ghcr.io/kanisterio/build:v0.0.24 - -# tag 0.1.0 is, 0.0.1 (latest) + gh + aws + helm binary -DOCS_BUILD_IMAGE ?= ghcr.io/kanisterio/docker-sphinx:0.2.0 - DOCS_RELEASE_BUCKET ?= s3://docs.kanister.io GITHUB_TOKEN ?= "" @@ -100,39 +93,25 @@ all-push: $(addprefix push-, $(ALL_ARCH)) build: bin/$(ARCH)/$(BIN) build-controller: - @$(MAKE) run CMD='-c " \ + @$(MAKE) run CMD=" \ goreleaser build --id $(BIN) --rm-dist --debug --snapshot \ && cp dist/$(BIN)_linux_$(ARCH)_*/$(BIN) bin/$(ARCH)/$(BIN) \ - "' + " bin/$(ARCH)/$(BIN): @echo "building: $@" - @$(MAKE) run CMD='-c " \ + @$(MAKE) run CMD=" \ GOARCH=$(ARCH) \ VERSION=$(VERSION) \ PKG=$(PKG) \ BIN=$(BIN) \ GOBORING=$(GOBORING) \ ./build/build.sh \ - "' + " # Example: make shell CMD="-c 'date > datefile'" shell: build-dirs @echo "launching a shell in the containerized build environment" - @docker run \ - -ti \ - --rm \ - --privileged \ - --net host \ - -v "$(PWD)/.go/pkg:/go/pkg" \ - -v "$(PWD)/.go/cache:/go/.cache" \ - -v "${HOME}/.kube:/root/.kube" \ - -v "$(PWD):/go/src/$(PKG)" \ - -v "$(PWD)/bin/$(ARCH):/go/bin" \ - -v "$(DOCKER_CONFIG):/root/.docker" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -w /go/src/$(PKG) \ - $(BUILD_IMAGE) \ - /bin/sh + @PWD=$(PWD) ARCH=$(ARCH) PKG=$(PKG) GITHUB_TOKEN=$(GITHUB_TOKEN) CMD="/bin/bash $(CMD)" /bin/bash ./build/run_container.sh shell DOTFILE_IMAGE = $(subst :,_,$(subst /,_,$(IMAGE))-$(VERSION)) @@ -176,38 +155,31 @@ deploy: release-controller .deploy-$(DOTFILE_IMAGE) @kubectl apply -f .deploy-$(DOTFILE_IMAGE) test: build-dirs - @$(MAKE) run CMD='-c "./build/test.sh $(SRC_DIRS)"' + @$(MAKE) run CMD="./build/test.sh $(SRC_DIRS)" helm-test: build-dirs - @$(MAKE) run CMD='-c "./build/helm-test.sh $(SRC_DIRS)"' + @$(MAKE) run CMD="./build/helm-test.sh $(SRC_DIRS)" integration-test: build-dirs - @$(MAKE) run CMD='-c "./build/integration-test.sh short"' + @$(MAKE) run CMD="./build/integration-test.sh short" openshift-test: @/bin/bash ./build/integration-test.sh openshift $(ocp_version) golint: - @$(MAKE) run CMD='-c "./build/golint.sh"' + @$(MAKE) run CMD="./build/golint.sh" codegen: - @$(MAKE) run CMD='-c "./build/codegen.sh"' + @$(MAKE) run CMD="./build/codegen.sh" DOCS_CMD = "cd docs && make clean && \ doc8 --max-line-length 90 --ignore D000 . && \ - make spelling && make html \ - " + make spelling && make html" docs: ifeq ($(DOCKER_BUILD),"true") @echo "running DOCS_CMD in the containerized build environment" - @docker run \ - --entrypoint '' \ - --rm \ - -v "$(PWD):/repo" \ - -w /repo \ - $(DOCS_BUILD_IMAGE) \ - /bin/bash -c $(DOCS_CMD) + @PWD=$(PWD) ARCH=$(ARCH) CMD=$(DOCS_CMD) /bin/bash ./build/run_container.sh docs else @/bin/bash -c $(DOCS_CMD) endif @@ -216,19 +188,12 @@ API_DOCS_CMD = "gen-crd-api-reference-docs \ -config docs/api_docs/config.json \ -api-dir ./pkg/apis/cr/v1alpha1 \ -template-dir docs/api_docs/template \ - -out-file API.md \ -" + -out-file API.md" crd_docs: ifeq ($(DOCKER_BUILD),"true") @echo "running API_DOCS_CMD in the containerized build environment" - @docker run \ - --entrypoint '' \ - --rm \ - -v "$(PWD):/repo" \ - -w /repo \ - $(BUILD_IMAGE) \ - /bin/bash -c $(API_DOCS_CMD) + @PWD=$(PWD) ARCH=$(ARCH) CMD=$(API_DOCS_CMD) /bin/bash ./build/run_container.sh crd_docs else @/bin/bash -c $(API_DOCS_CMD) endif @@ -240,21 +205,7 @@ build-dirs: run: build-dirs ifeq ($(DOCKER_BUILD),"true") @echo "running CMD in the containerized build environment" - @docker run \ - --rm \ - --net host \ - -e GITHUB_TOKEN=$(GITHUB_TOKEN) \ - -v "${HOME}/.kube:/root/.kube" \ - -v "$(PWD)/.go/pkg:/go/pkg" \ - -v "$(PWD)/.go/cache:/go/.cache" \ - -v "$(PWD):/go/src/$(PKG)" \ - -v "$(PWD)/bin/$(ARCH):/go/bin" \ - -v "$(PWD)/.go/std/$(ARCH):/usr/local/go/pkg/linux_$(ARCH)" \ - -v "$(DOCKER_CONFIG):/root/.docker" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -w /go/src/$(PKG) \ - $(BUILD_IMAGE) \ - /bin/bash $(CMD) + @PWD=$(PWD) ARCH=$(ARCH) PKG=$(PKG) GITHUB_TOKEN=$(GITHUB_TOKEN) CMD="$(CMD)" /bin/bash ./build/run_container.sh run else @/bin/bash $(CMD) endif @@ -285,28 +236,28 @@ release-helm: @/bin/bash ./build/release_helm.sh $(VERSION) gorelease: - @$(MAKE) run CMD='-c "./build/gorelease.sh"' + @$(MAKE) run CMD="./build/gorelease.sh" release-snapshot: - @$(MAKE) run CMD='-c "GORELEASER_CURRENT_TAG=v9.99.9-dev goreleaser --debug release --rm-dist --snapshot --timeout=60m0s"' + @$(MAKE) run CMD="GORELEASER_CURRENT_TAG=v9.99.9-dev goreleaser --debug release --rm-dist --snapshot --timeout=60m0s" go-mod-download: - @$(MAKE) run CMD='-c "go mod download"' + @$(MAKE) run CMD="go mod download" start-kind: - @$(MAKE) run CMD='-c "./build/local_kubernetes.sh start_localkube"' + @$(MAKE) run CMD="./build/local_kubernetes.sh start_localkube" tiller: @/bin/bash ./build/init_tiller.sh install-minio: - @$(MAKE) run CMD='-c "./build/minio.sh install_minio"' + @$(MAKE) run CMD="./build/minio.sh install_minio" install-csi-hostpath-driver: - @$(MAKE) run CMD='-c "./build/local_kubernetes.sh install_csi_hostpath_driver"' + @$(MAKE) run CMD="./build/local_kubernetes.sh install_csi_hostpath_driver" uninstall-minio: - @$(MAKE) run CMD='-c "./build/minio.sh uninstall_minio"' + @$(MAKE) run CMD="./build/minio.sh uninstall_minio" start-minishift: @/bin/bash ./build/minishift.sh start_minishift $(vm-driver) @@ -315,21 +266,21 @@ stop-minishift: @/bin/bash ./build/minishift.sh stop_minishift stop-kind: - @$(MAKE) run CMD='-c "./build/local_kubernetes.sh stop_localkube"' + @$(MAKE) run CMD="./build/local_kubernetes.sh stop_localkube" check: @./build/check.sh go-mod-tidy: - @$(MAKE) run CMD='-c "./build/gomodtidy.sh"' + @$(MAKE) run CMD="./build/gomodtidy.sh" install-crds: ## Install CRDs into the K8s cluster specified in ~/.kube/config. - @$(MAKE) run CMD='-c "kubectl apply -f pkg/customresource/"' + @$(MAKE) run CMD="kubectl apply -f pkg/customresource/" uninstall-crds: ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. - @$(MAKE) run CMD='-c "kubectl delete -f pkg/customresource/"' + @$(MAKE) run CMD="kubectl delete -f pkg/customresource/" manifests: ## Generates CustomResourceDefinition objects. - @$(MAKE) run CMD='-c "./build/generate_crds.sh ${CONTROLLER_TOOLS_VERSION}"' + @$(MAKE) run CMD="./build/generate_crds.sh ${CONTROLLER_TOOLS_VERSION}" diff --git a/build/integration-test.sh b/build/integration-test.sh index a64eea8c59..419f745d54 100755 --- a/build/integration-test.sh +++ b/build/integration-test.sh @@ -26,7 +26,7 @@ TEST_TIMEOUT="30m" TEST_OPTIONS="-tags=integration -timeout ${TEST_TIMEOUT} -check.suitep ${DOP}" # Regex to match apps to run in short mode # Temporary disable ES test. Issue to track https://github.com/kanisterio/kanister/issues/1920 -SHORT_APPS="^PostgreSQL$|^MySQL$|^MongoDB$|Maria|^MSSQL$" +SHORT_APPS="^PostgreSQL$|^MySQL$|^MongoDB$|^MSSQL$" # OCAPPS has all the apps that are to be tested against openshift cluster OC_APPS3_11="MysqlDBDepConfig$|MongoDBDepConfig$|PostgreSQLDepConfig$" OC_APPS4_4="MysqlDBDepConfig4_4|MongoDBDepConfig4_4|PostgreSQLDepConfig4_4" diff --git a/build/local_kubernetes.sh b/build/local_kubernetes.sh index 97cc28c9d2..933ef22100 100755 --- a/build/local_kubernetes.sh +++ b/build/local_kubernetes.sh @@ -73,14 +73,43 @@ install_csi_hostpath_driver() { kubectl apply -fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/{rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml} # Deploy the CSI Hostpath Driver - cd /tmp - git clone https://github.com/kubernetes-csi/csi-driver-host-path.git - cd csi-driver-host-path - sed -i 's/mountPropagation: Bidirectional/\#mountPropagation: Bidirectional/g' deploy/kubernetes-latest/hostpath/csi-hostpath-plugin.yaml - ./deploy/kubernetes-latest/deploy.sh - - # Create StorageClass - kubectl apply -f ./examples/csi-storageclass.yaml + pushd /tmp + git clone https://github.com/kubernetes-csi/csi-driver-host-path.git + pushd csi-driver-host-path + sed -i 's/mountPropagation: Bidirectional/\#mountPropagation: Bidirectional/g' deploy/kubernetes-latest/hostpath/csi-hostpath-plugin.yaml + + ./deploy/kubernetes-latest/deploy.sh + + # Create StorageClass + kubectl apply -f ./examples/csi-storageclass.yaml + popd + popd +} + +check_csi_hostpath_driver_installed() { + # Check VolumeSnapshot CRDs are installed + if ! kubectl diff -fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/client/config/crd/snapshot.storage.k8s.io_{volumesnapshots.yaml,volumesnapshotclasses.yaml,volumesnapshotcontents.yaml} 2>&1 > /dev/null ; then + echo "VolumeSnapshot CRDs are not installed." + exit 1 + fi + + # Check snapshot controller created + if ! kubectl diff -fhttps://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/${SNAPSHOTTER_VERSION}/deploy/kubernetes/snapshot-controller/{rbac-snapshot-controller.yaml,setup-snapshot-controller.yaml} 2>&1 > /dev/null ; then + echo "Snapshot controller is not created." + exit 1 + fi + + # Deploy the CSI Hostpath Driver + pushd /tmp + git clone https://github.com/kubernetes-csi/csi-driver-host-path.git + pushd csi-driver-host-path + # Check StorageClass created + if ! kubectl diff -f ./examples/csi-storageclass.yaml 2>&1 > /dev/null ; then + echo "StorageClass is not created." + exit 1 + fi + popd + popd } stop_localkube() { @@ -158,6 +187,9 @@ EOM check_or_get_dependencies case "${1}" in # Alphabetically sorted + check_csi_hostpath_driver_installed) + time -p check_csi_hostpath_driver_installed + ;; get_localkube) time -p get_localkube ;; diff --git a/build/package.sh b/build/package.sh index 0362b10966..135b950c61 100755 --- a/build/package.sh +++ b/build/package.sh @@ -66,5 +66,5 @@ sed \ -e "s|ARG_ARCH|${ARCH}|g" \ -e "s|ARG_SOURCE_BIN|${SOURCE_BIN}|g" \ Dockerfile.in > .dockerfile-${ARCH} -docker build --pull ${baseimagearg:-} --build-arg kanister_version=${VERSION} -t ${IMAGE}:${VERSION} -f .dockerfile-${ARCH} . +docker buildx build --push --pull --sbom=true ${baseimagearg:-} --build-arg kanister_version=${VERSION} -t ${IMAGE}:${VERSION} -f .dockerfile-${ARCH} . docker images -q ${IMAGE}:${VERSION} diff --git a/build/run_container.sh b/build/run_container.sh new file mode 100755 index 0000000000..1f9ce3b807 --- /dev/null +++ b/build/run_container.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +# Copyright 2019 The Kanister Authors. +# +# Copyright 2016 The Kubernetes Authors. +# +# 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. + + +set -o errexit +set -o nounset + +PWD="${PWD:-$(pwd)}" + +DOCS_BUILD_IMAGE="${DOCS_BUILD_IMAGE:-ghcr.io/kanisterio/docker-sphinx:0.2.0}" +BUILD_IMAGE="${BUILD_IMAGE:-ghcr.io/kanisterio/build:v0.0.25}" +PKG="${PKG:-github.com/kanisterio/kanister}" + +ARCH="${ARCH:-amd64}" +PLATFORM="linux/${ARCH}" + +check_param() { + local arg_name=${1} + local value_of_arg="" + eval value_of_arg=\$$arg_name + if [ -z "${value_of_arg}" ]; then + echo "$arg_name must be set" + exit 1 + fi +} + + +run_build_container() { + local github_token="${GITHUB_TOKEN:-}" + local extra_params="${EXTRA_PARAMS:-}" + + local cmd=(/bin/bash -c "$CMD") + if [ -z "${CMD}" ]; then + cmd=(/bin/bash) + fi + + # In case of `minikube`, kube config stores full path to a certificates, + # thus the simples way to get working minikube in the build container is + # to bind original path to minikube settings to the container. + local minikube_dir_path="${HOME}/.minikube" + local minikube_dir_binding="-v ${minikube_dir_path}:${minikube_dir_path}" + if [ ! -d "${minikube_dir_path}" ]; then + minikube_dir_binding="" + fi + + docker run \ + --platform ${PLATFORM} \ + ${extra_params} \ + --rm \ + --net host \ + -e GITHUB_TOKEN="${github_token}" \ + ${minikube_dir_binding} \ + -v "${HOME}/.kube:/root/.kube" \ + -v "${PWD}/.go/pkg:/go/pkg" \ + -v "${PWD}/.go/cache:/go/.cache" \ + -v "${PWD}:/go/src/${PKG}" \ + -v "${PWD}/bin/${ARCH}:/go/bin" \ + -v "${PWD}/.go/std/${ARCH}:/usr/local/go/pkg/linux_${ARCH}" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -w /go/src/${PKG} \ + ${BUILD_IMAGE} \ + "${cmd[@]}" +} + +run_docs_container() { + check_param "IMAGE" + check_param "CMD" + + docker run \ + --platform ${PLATFORM} \ + --entrypoint '' \ + --rm \ + -v "${PWD}:/repo" \ + -w /repo \ + ${IMAGE} \ + /bin/bash -c "${CMD}" +} + +run() { + check_param "CMD" + + echo "Running command within build container..." + run_build_container +} + +shell() { + echo "Running build container in interactive shell mode..." + EXTRA_PARAMS="-ti" run_build_container +} + +docs() { + check_param "CMD" + + echo "Running docs container..." + IMAGE=${DOCS_BUILD_IMAGE} run_docs_container +} + +crd_docs() { + check_param "CMD" + + echo "Running crd docs container..." + IMAGE=${BUILD_IMAGE} run_docs_container +} + +usage() { + cat < +Where operation is one of the following: + build: run some command within a build container + crd_docs: build API docs within a container + docs: build docs within a container + shell: run build container in interactive shell mode +EOM + exit 1 +} + +[ ${#@} -gt 0 ] || usage +case "${1}" in + # Alphabetically sorted + crd_docs) + time -p crd_docs + ;; + docs) + time -p docs + ;; + run) + time -p run + ;; + shell) + time -p shell + ;; + *) + usage + exit 1 +esac diff --git a/build/test.sh b/build/test.sh index 176a82d538..eb50377d06 100755 --- a/build/test.sh +++ b/build/test.sh @@ -19,6 +19,7 @@ set -o errexit set -o nounset +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" export CGO_ENABLED=0 export GO111MODULE=on @@ -51,8 +52,8 @@ fi echo check_dependencies() { - # Check if minio is already deployed - if helm status minio -n minio > /dev/null 2>&1 ; then + # Check if minio is already deployed. We suppress only `stdout` and not `stderr` to make sure we catch errors if `helm status` fails + if helm status minio -n minio 1> /dev/null ; then # Setting env vars to access MinIO export S3_COMPLIANT_AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE" export S3_COMPLIANT_AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" @@ -63,11 +64,21 @@ check_dependencies() { echo "Please install MinIO using 'make install-minio' and try again." exit 1 fi + + # A test (CRDSuite) that runs as part of `make test` requires at least one CRD to + # be present on the cluster. That's why we are checking that `csi-hostpath-driver` + # installed before running tests. + if ! ${SCRIPT_DIR}/local_kubernetes.sh check_csi_hostpath_driver_installed ; then + echo "CRDs are not installed on the cluster but a test (CRDSuite) requires at least one CRD to be available on the cluster."\ + " One can be installed by running 'make install-csi-hostpath-driver' command." + exit 1 + fi } check_dependencies + echo "Running tests:" -go test -v -installsuffix "static" -i ${TARGETS} +go test -v -installsuffix "static" ${TARGETS} go test -v ${TARGETS} -list . go test -v -installsuffix "static" ${TARGETS} -check.v echo diff --git a/docker/build/Dockerfile b/docker/build/Dockerfile index b697bc746d..f5a800ac9e 100644 --- a/docker/build/Dockerfile +++ b/docker/build/Dockerfile @@ -1,5 +1,4 @@ -FROM golang:1.19-bullseye - +FROM golang:1.21-bullseye LABEL maintainer="Tom Manville" RUN apt-get update && apt-get -y install apt-transport-https ca-certificates bash git gnupg2 software-properties-common curl jq wget \ @@ -17,7 +16,7 @@ COPY --from=goreleaser/goreleaser:v1.12.3 /usr/bin/goreleaser /usr/local/bin/ COPY --from=alpine/helm:3.12.2 /usr/bin/helm /usr/local/bin/ -COPY --from=golangci/golangci-lint:v1.50 /usr/bin/golangci-lint /usr/local/bin/ +COPY --from=golangci/golangci-lint:v1.51.2 /usr/bin/golangci-lint /usr/local/bin/ RUN wget -O /usr/local/bin/kind https://github.com/kubernetes-sigs/kind/releases/download/v0.18.0/kind-linux-amd64 \ && chmod +x /usr/local/bin/kind diff --git a/docker/controller/Dockerfile b/docker/controller/Dockerfile index 558f8cbb35..9cb67fca0f 100644 --- a/docker/controller/Dockerfile +++ b/docker/controller/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750.1697534106 LABEL maintainer="Tom Manville" diff --git a/docker/mongodb-atlas/Dockerfile b/docker/mongodb-atlas/Dockerfile index bd8650f535..fa27a715d9 100644 --- a/docker/mongodb-atlas/Dockerfile +++ b/docker/mongodb-atlas/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750 +FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2-750.1697534106 RUN cat >/etc/yum.repos.d/mongodb.repo <` +* Kanister controller version 0.97.0 installed in your cluster, let's say in namespace `` * Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) To install kanister and related tools you can follow [this](https://docs.kanister.io/install.html#install) link. @@ -29,7 +29,7 @@ $ helm repo add bitnami https://charts.bitnami.com/bitnami $ helm repo update # remove app-namespace with the namespace you want to deploy the Cassandra app in $ kubectl create ns -$ helm install cassandra bitnami/cassandra --namespace --set image.repository=kanisterio/cassandra --set image.tag=0.96.0 --set cluster.replicaCount=2 --set image.registry=ghcr.io --set image.pullPolicy=Always +$ helm install cassandra bitnami/cassandra --namespace --set image.repository=kanisterio/cassandra --set image.tag=0.97.0 --set cluster.replicaCount=2 --set image.registry=ghcr.io --set image.pullPolicy=Always ``` diff --git a/examples/cassandra/cassandra-blueprint.yaml b/examples/cassandra/cassandra-blueprint.yaml index 69596dea1a..8009b13392 100644 --- a/examples/cassandra/cassandra-blueprint.yaml +++ b/examples/cassandra/cassandra-blueprint.yaml @@ -102,7 +102,7 @@ actions: name: restoreFromObjectStore args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 backupArtifactPrefix: "{{ .ArtifactsIn.params.KeyValue.backupPrefixLocation }}" pods: "{{ range .StatefulSet.Pods }} {{.}}{{end}}" restorePath: "{{ .ArtifactsIn.params.KeyValue.restorePathPrefix }}" diff --git a/examples/cockroachdb/cockroachdb-blueprint.yaml b/examples/cockroachdb/cockroachdb-blueprint.yaml index dbe21e35a1..aa1cf34421 100644 --- a/examples/cockroachdb/cockroachdb-blueprint.yaml +++ b/examples/cockroachdb/cockroachdb-blueprint.yaml @@ -151,7 +151,7 @@ actions: - func: KubeTask name: deleteFromS3Store args: - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/couchbase/blueprint-v2/couchbase-blueprint.yaml b/examples/couchbase/blueprint-v2/couchbase-blueprint.yaml index 8ade5b4fd6..93d0421721 100644 --- a/examples/couchbase/blueprint-v2/couchbase-blueprint.yaml +++ b/examples/couchbase/blueprint-v2/couchbase-blueprint.yaml @@ -21,7 +21,7 @@ actions: namespace: "{{ .Object.metadata.namespace }}" args: namespace: "{{ .Object.metadata.namespace }}" - image: ghcr.io/kanisterio/couchbase-tools:0.96.0 + image: ghcr.io/kanisterio/couchbase-tools:0.97.0 command: - bash - -o @@ -58,7 +58,7 @@ actions: namespace: "{{ .Object.metadata.namespace }}" args: namespace: "{{ .Object.metadata.namespace }}" - image: ghcr.io/kanisterio/couchbase-tools:0.96.0 + image: ghcr.io/kanisterio/couchbase-tools:0.97.0 command: - bash - -o @@ -89,7 +89,7 @@ actions: name: deleteBackup args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/couchbase-tools:0.96.0 + image: ghcr.io/kanisterio/couchbase-tools:0.97.0 command: - bash - -o diff --git a/examples/couchbase/couchbase-blueprint.yaml b/examples/couchbase/couchbase-blueprint.yaml index 73f6b0576e..cfef906642 100644 --- a/examples/couchbase/couchbase-blueprint.yaml +++ b/examples/couchbase/couchbase-blueprint.yaml @@ -79,7 +79,7 @@ actions: name: deleteBackup args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 command: - bash - -o diff --git a/examples/csi-snapshot/README.md b/examples/csi-snapshot/README.md index ff198ee664..cdca847aa2 100644 --- a/examples/csi-snapshot/README.md +++ b/examples/csi-snapshot/README.md @@ -8,7 +8,7 @@ This example demonstrates Kanister's ability to protect an application called Ti - Helm 3 installed - Kubernetes 1.16+ with Beta APIs enabled -- Kanister controller version 0.96.0 installed in the cluster, let's assume in namespace `kanister` +- Kanister controller version 0.97.0 installed in the cluster, let's assume in namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) - VolumeSnapshot CRDs, Snapshot Controller & a CSI Driver diff --git a/examples/elasticsearch/README.md b/examples/elasticsearch/README.md index 059a37bd98..84f3eeb2d2 100644 --- a/examples/elasticsearch/README.md +++ b/examples/elasticsearch/README.md @@ -20,7 +20,7 @@ moving on to Elasticsearch 6.0. * Kubernetes 1.20+ * PV provisioner support in the underlying infrastructure -* Kanister controller version 0.96.0 installed in your cluster +* Kanister controller version 0.97.0 installed in your cluster * Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) ## StatefulSets Details @@ -74,7 +74,7 @@ Add Kanister Helm repository and install Kanister operator ```bash $ helm repo add kanister https://charts.kanister.io $ helm install kanister --namespace kanister --create-namespace \ - kanister/kanister-operator --set image.tag=0.96.0 + kanister/kanister-operator --set image.tag=0.97.0 ``` ### Create Profile diff --git a/examples/elasticsearch/blueprint-v2/elasticsearch-blueprint.yaml b/examples/elasticsearch/blueprint-v2/elasticsearch-blueprint.yaml index dd38b36ff0..b4d29849e9 100644 --- a/examples/elasticsearch/blueprint-v2/elasticsearch-blueprint.yaml +++ b/examples/elasticsearch/blueprint-v2/elasticsearch-blueprint.yaml @@ -20,7 +20,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o @@ -50,7 +50,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o @@ -75,7 +75,7 @@ actions: name: deleteFromStore args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o diff --git a/examples/elasticsearch/elasticsearch-blueprint.yaml b/examples/elasticsearch/elasticsearch-blueprint.yaml index 2f852bc581..ff699c1a30 100644 --- a/examples/elasticsearch/elasticsearch-blueprint.yaml +++ b/examples/elasticsearch/elasticsearch-blueprint.yaml @@ -18,7 +18,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o @@ -48,7 +48,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o @@ -69,7 +69,7 @@ actions: name: deleteFromObjectStore args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/es-sidecar:0.96.0" + image: "ghcr.io/kanisterio/es-sidecar:0.97.0" command: - bash - -o diff --git a/examples/etcd/etcd-in-cluster/k8s/etcd-incluster-blueprint.yaml b/examples/etcd/etcd-in-cluster/k8s/etcd-incluster-blueprint.yaml index 3e2f256fa0..8eb1a9c6c1 100644 --- a/examples/etcd/etcd-in-cluster/k8s/etcd-incluster-blueprint.yaml +++ b/examples/etcd/etcd-in-cluster/k8s/etcd-incluster-blueprint.yaml @@ -12,7 +12,7 @@ actions: - func: KubeTask name: takeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -37,7 +37,7 @@ actions: - func: KubeTask name: uploadSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -55,7 +55,7 @@ actions: - func: KubeTask name: removeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -74,7 +74,7 @@ actions: name: deleteFromObjectStore args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/kanister-tools:0.96.0" + image: "ghcr.io/kanisterio/kanister-tools:0.97.0" command: - bash - -o diff --git a/examples/etcd/etcd-in-cluster/ocp/blueprint-v2/etcd-incluster-ocp-blueprint.yaml b/examples/etcd/etcd-in-cluster/ocp/blueprint-v2/etcd-incluster-ocp-blueprint.yaml index 0cb00449d0..3edb05735d 100644 --- a/examples/etcd/etcd-in-cluster/ocp/blueprint-v2/etcd-incluster-ocp-blueprint.yaml +++ b/examples/etcd/etcd-in-cluster/ocp/blueprint-v2/etcd-incluster-ocp-blueprint.yaml @@ -11,7 +11,7 @@ actions: - func: KubeTask name: takeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -34,7 +34,7 @@ actions: - func: KubeTask name: uploadSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -50,7 +50,7 @@ actions: - func: KubeTask name: removeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -73,7 +73,7 @@ actions: - func: PrepareData name: copyFromObjectStore args: - image: "ghcr.io/kanisterio/kanister-tools:0.96.0" + image: "ghcr.io/kanisterio/kanister-tools:0.97.0" namespace: "{{ .Object.metadata.namespace }}" podOverride: nodeSelector: @@ -108,7 +108,7 @@ actions: name: deleteFromObjectStore args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/kanister-tools:0.96.0" + image: "ghcr.io/kanisterio/kanister-tools:0.97.0" command: - bash - -o diff --git a/examples/etcd/etcd-in-cluster/ocp/etcd-incluster-ocp-blueprint.yaml b/examples/etcd/etcd-in-cluster/ocp/etcd-incluster-ocp-blueprint.yaml index ec0bc519b3..f1113806b2 100644 --- a/examples/etcd/etcd-in-cluster/ocp/etcd-incluster-ocp-blueprint.yaml +++ b/examples/etcd/etcd-in-cluster/ocp/etcd-incluster-ocp-blueprint.yaml @@ -12,7 +12,7 @@ actions: - func: KubeTask name: takeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -35,7 +35,7 @@ actions: - func: KubeTask name: uploadSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -53,7 +53,7 @@ actions: - func: KubeTask name: removeSnapshot args: - image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.96.0 + image: ghcr.io/kanisterio/kanister-kubectl-1.18:0.97.0 command: - sh - -o @@ -72,7 +72,7 @@ actions: name: deleteFromObjectStore args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/kanister-tools:0.96.0" + image: "ghcr.io/kanisterio/kanister-tools:0.97.0" command: - bash - -o diff --git a/examples/foundationdb/README.md b/examples/foundationdb/README.md index 55c74ca817..5bb680bb22 100644 --- a/examples/foundationdb/README.md +++ b/examples/foundationdb/README.md @@ -24,7 +24,7 @@ cluster. on you cluster. * Kubernetes 1.9+ with Beta APIs enabled. * PV support on the underlying infrastructure. -* Kanister version 0.96.0 with `profiles.cr.kanister.io` CRD installed. +* Kanister version 0.97.0 with `profiles.cr.kanister.io` CRD installed. * Docker CLI installed * A docker image containing the required tools to back up FoundationDB. The Dockerfile for the image can be found [here](https://raw.githubusercontent.com/kanisterio/kanister/master/docker/foundationdb/Dockerfile). diff --git a/examples/foundationdb/blueprint-v2/foundationdb-blueprint.yaml b/examples/foundationdb/blueprint-v2/foundationdb-blueprint.yaml index 7845b9e4b9..b45b6b8463 100644 --- a/examples/foundationdb/blueprint-v2/foundationdb-blueprint.yaml +++ b/examples/foundationdb/blueprint-v2/foundationdb-blueprint.yaml @@ -77,7 +77,7 @@ actions: name: deleteBackup args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 command: - bash - -o diff --git a/examples/k8ssandra/README.md b/examples/k8ssandra/README.md index 2e73acd53d..1c93ece33b 100644 --- a/examples/k8ssandra/README.md +++ b/examples/k8ssandra/README.md @@ -8,7 +8,7 @@ K8ssandra operator uses Medusa to backup and restore Cassandra data. Kanister ca * Kubernetes 1.17+ * PV support on the underlying infrastructure -* Kanister controller version 0.96.0 installed in your cluster +* Kanister controller version 0.97.0 installed in your cluster * Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) * K8ssandra needs at least 4 cores and 8GB of RAM available to Docker and appropriate heap sizes for Cassandra and Stargate. If you don’t have those resources available, you can avoid deploying features such as monitoring, Reaper and Medusa, and also reduce the number of Cassandra nodes. diff --git a/examples/kafka/adobe-s3-connector/README.md b/examples/kafka/adobe-s3-connector/README.md index 721efb15d8..b2b2feae19 100644 --- a/examples/kafka/adobe-s3-connector/README.md +++ b/examples/kafka/adobe-s3-connector/README.md @@ -6,7 +6,7 @@ During restore, topic messages are purged before the restore operation is perfor ## Prerequisites * Kubernetes 1.9+ -* Kanister controller version 0.96.0 installed in the cluster in a namespace . This example uses `kanister` namespace +* Kanister controller version 0.97.0 installed in the cluster in a namespace . This example uses `kanister` namespace * Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) ## Assumption diff --git a/examples/maria/blueprint-v2/maria-blueprint.yaml b/examples/maria/blueprint-v2/maria-blueprint.yaml index 5c25aa85bf..ab0a17f772 100644 --- a/examples/maria/blueprint-v2/maria-blueprint.yaml +++ b/examples/maria/blueprint-v2/maria-blueprint.yaml @@ -19,7 +19,7 @@ actions: name: '{{ .StatefulSet.Name }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -53,7 +53,7 @@ actions: name: '{{ .StatefulSet.Name }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -76,7 +76,7 @@ actions: - func: KubeTask name: deleteFromStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/maria/maria-blueprint.yaml b/examples/maria/maria-blueprint.yaml index bd23aadbed..3f5d2f30ab 100644 --- a/examples/maria/maria-blueprint.yaml +++ b/examples/maria/maria-blueprint.yaml @@ -17,7 +17,7 @@ actions: name: '{{ .StatefulSet.Name }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -49,7 +49,7 @@ actions: name: '{{ .StatefulSet.Name }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -69,7 +69,7 @@ actions: - func: KubeTask name: deleteFromBlobStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/mongo-sidecar/README.md b/examples/mongo-sidecar/README.md index 791005888a..e75cf64515 100644 --- a/examples/mongo-sidecar/README.md +++ b/examples/mongo-sidecar/README.md @@ -7,7 +7,7 @@ This is an example of using Kanister to backup and restore MongoDB. In this exam - Kubernetes 1.20+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster, let's assume in Namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster, let's assume in Namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) diff --git a/examples/mongodb-atlas/README.md b/examples/mongodb-atlas/README.md index 3d426e9d24..be8a795a88 100644 --- a/examples/mongodb-atlas/README.md +++ b/examples/mongodb-atlas/README.md @@ -7,7 +7,7 @@ It deploys and scales a MongoDB cluster in the cloud. ## Prerequisites * Kubernetes 1.20+ -* Kanister controller version 0.96.0 installed in your cluster +* Kanister controller version 0.97.0 installed in your cluster * Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) * Already provisioned MongoDB Atlas cluster (https://www.mongodb.com/docs/atlas/getting-started) @@ -19,7 +19,7 @@ to install. ```bash $ helm repo add kanister https://charts.kanister.io $ helm install kanister --namespace kanister --create-namespace \ - kanister/kanister-operator --set image.tag=0.96.0 + kanister/kanister-operator --set image.tag=0.97.0 ``` ### Create Blueprint diff --git a/examples/mongodb-deploymentconfig/README.md b/examples/mongodb-deploymentconfig/README.md index 83fd30d3f5..745e62fc6d 100644 --- a/examples/mongodb-deploymentconfig/README.md +++ b/examples/mongodb-deploymentconfig/README.md @@ -14,7 +14,7 @@ cluster's DeploymentConfig resources. - Setup OpenShift, you can follow steps mentioned below - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster in namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster in namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) **Note** diff --git a/examples/mongodb-deploymentconfig/blueprint-v2/mongo-dep-config-blueprint.yaml b/examples/mongodb-deploymentconfig/blueprint-v2/mongo-dep-config-blueprint.yaml index bbe13eca0d..3d5c5756f6 100644 --- a/examples/mongodb-deploymentconfig/blueprint-v2/mongo-dep-config-blueprint.yaml +++ b/examples/mongodb-deploymentconfig/blueprint-v2/mongo-dep-config-blueprint.yaml @@ -20,7 +20,7 @@ actions: namespace: "{{ .DeploymentConfig.Namespace }}" args: namespace: "{{ .DeploymentConfig.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -50,7 +50,7 @@ actions: namespace: "{{ .DeploymentConfig.Namespace }}" args: namespace: "{{ .DeploymentConfig.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -75,7 +75,7 @@ actions: name: deleteFromStore args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o diff --git a/examples/mongodb-deploymentconfig/mongo-dep-config-blueprint.yaml b/examples/mongodb-deploymentconfig/mongo-dep-config-blueprint.yaml index fb4681f556..db4ae813d4 100644 --- a/examples/mongodb-deploymentconfig/mongo-dep-config-blueprint.yaml +++ b/examples/mongodb-deploymentconfig/mongo-dep-config-blueprint.yaml @@ -18,7 +18,7 @@ actions: namespace: "{{ .DeploymentConfig.Namespace }}" args: namespace: "{{ .DeploymentConfig.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -45,7 +45,7 @@ actions: namespace: "{{ .DeploymentConfig.Namespace }}" args: namespace: "{{ .DeploymentConfig.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -66,7 +66,7 @@ actions: name: deleteFromBlobStore args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o diff --git a/examples/mongodb-restic/README.md b/examples/mongodb-restic/README.md index 067738ba2a..61337d518b 100644 --- a/examples/mongodb-restic/README.md +++ b/examples/mongodb-restic/README.md @@ -7,7 +7,7 @@ * Kubernetes 1.9+ * Kubernetes beta APIs enabled only if `podDisruptionBudget` is enabled * PV support on the underlying infrastructure -* Kanister controller version 0.96.0 installed in your cluster +* Kanister controller version 0.97.0 installed in your cluster * Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) ## Chart Details @@ -28,7 +28,7 @@ $ kubectl create namespace mongo-test $ helm install my-release bitnami/mongodb --namespace mongo-test \ --set architecture="replicaset" \ --set image.repository=ghcr.io/kanisterio/mongodb \ - --set image.tag=0.96.0 + --set image.tag=0.97.0 ``` The command deploys MongoDB on the Kubernetes cluster in the mongo-test namespace diff --git a/examples/mongodb-restic/mongodb-blueprint.yaml b/examples/mongodb-restic/mongodb-blueprint.yaml index ff0aa53780..838fc5dec6 100644 --- a/examples/mongodb-restic/mongodb-blueprint.yaml +++ b/examples/mongodb-restic/mongodb-blueprint.yaml @@ -39,7 +39,7 @@ actions: name: restorePrimary args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 backupArtifactPrefix: "{{ .Profile.Location.Bucket }}/mongodb-backups/{{ .StatefulSet.Name }}/rs_backup" backupInfo: "{{ .ArtifactsIn.backupInfo.KeyValue.backupIdentifier }}" diff --git a/examples/mongodb/README.md b/examples/mongodb/README.md index dd4c03b075..0c0e41a016 100644 --- a/examples/mongodb/README.md +++ b/examples/mongodb/README.md @@ -7,7 +7,7 @@ * Kubernetes 1.20+ * Kubernetes beta APIs enabled only if `podDisruptionBudget` is enabled * PV support on the underlying infrastructure -* Kanister controller version 0.96.0 installed in your cluster +* Kanister controller version 0.97.0 installed in your cluster * Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) ## Chart Details diff --git a/examples/mongodb/blueprint-v2/mongo-blueprint.yaml b/examples/mongodb/blueprint-v2/mongo-blueprint.yaml index 878302a909..a8b5c71865 100644 --- a/examples/mongodb/blueprint-v2/mongo-blueprint.yaml +++ b/examples/mongodb/blueprint-v2/mongo-blueprint.yaml @@ -20,7 +20,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -49,7 +49,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -74,7 +74,7 @@ actions: name: deleteFromStore args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o diff --git a/examples/mongodb/mongo-blueprint.yaml b/examples/mongodb/mongo-blueprint.yaml index 803ed79b43..3d7abb51c5 100644 --- a/examples/mongodb/mongo-blueprint.yaml +++ b/examples/mongodb/mongo-blueprint.yaml @@ -18,7 +18,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -44,7 +44,7 @@ actions: namespace: "{{ .StatefulSet.Namespace }}" args: namespace: "{{ .StatefulSet.Namespace }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o @@ -65,7 +65,7 @@ actions: name: deleteFromBlobStore args: namespace: "{{ .Namespace.Name }}" - image: ghcr.io/kanisterio/mongodb:0.96.0 + image: ghcr.io/kanisterio/mongodb:0.97.0 command: - bash - -o diff --git a/examples/mssql/README.md b/examples/mssql/README.md index baa1722b5e..44b8e20cc9 100644 --- a/examples/mssql/README.md +++ b/examples/mssql/README.md @@ -9,7 +9,7 @@ This document will cover how to install SQL Server and how to run backup/restore - Kubernetes 1.16+ with Beta APIs enabled - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster, let's assume in Namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster, let's assume in Namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) ## Installing Microsoft SQL Server diff --git a/examples/mssql/blueprint-v2/mssql-blueprint.yaml b/examples/mssql/blueprint-v2/mssql-blueprint.yaml index 01763803be..f627b306f6 100644 --- a/examples/mssql/blueprint-v2/mssql-blueprint.yaml +++ b/examples/mssql/blueprint-v2/mssql-blueprint.yaml @@ -16,7 +16,7 @@ actions: name: '{{ index .Object.metadata.labels "app" }}' namespace: '{{ .Deployment.Namespace }}' args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o @@ -47,7 +47,7 @@ actions: name: '{{ index .Object.metadata.labels "app" }}' namespace: '{{ .Deployment.Namespace }}' args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o @@ -74,7 +74,7 @@ actions: - func: KubeTask name: deleteFromBlobStore args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o diff --git a/examples/mssql/mssql-blueprint.yaml b/examples/mssql/mssql-blueprint.yaml index 24902eba11..cda69104a9 100644 --- a/examples/mssql/mssql-blueprint.yaml +++ b/examples/mssql/mssql-blueprint.yaml @@ -14,7 +14,7 @@ actions: - func: KubeTask name: dumpToObjectStore args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o @@ -45,7 +45,7 @@ actions: - func: KubeTask name: restoreFromObjectStore args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o @@ -71,7 +71,7 @@ actions: - func: KubeTask name: deleteFromBlobStore args: - image: ghcr.io/kanisterio/mssql-tools:0.96.0 + image: ghcr.io/kanisterio/mssql-tools:0.97.0 command: - bash - -o diff --git a/examples/mysql-deploymentconfig/README.md b/examples/mysql-deploymentconfig/README.md index f666b5f227..1f6dd01f5d 100644 --- a/examples/mysql-deploymentconfig/README.md +++ b/examples/mysql-deploymentconfig/README.md @@ -14,7 +14,7 @@ cluster's DeploymentConfig resources. - Setup OpenShift, you can follow steps mentioned below - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster in namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster in namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) **Note** diff --git a/examples/mysql-deploymentconfig/blueprint-v2/mysql-dep-config-blueprint.yaml b/examples/mysql-deploymentconfig/blueprint-v2/mysql-dep-config-blueprint.yaml index 1c55edc987..0f9e854993 100644 --- a/examples/mysql-deploymentconfig/blueprint-v2/mysql-dep-config-blueprint.yaml +++ b/examples/mysql-deploymentconfig/blueprint-v2/mysql-dep-config-blueprint.yaml @@ -19,7 +19,7 @@ actions: name: "{{ .DeploymentConfig.Name }}" namespace: "{{ .DeploymentConfig.Namespace }}" args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .DeploymentConfig.Namespace }}" command: - bash @@ -47,7 +47,7 @@ actions: name: "{{ .DeploymentConfig.Name }}" namespace: "{{ .DeploymentConfig.Namespace }}" args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .DeploymentConfig.Namespace }}" command: - bash @@ -71,7 +71,7 @@ actions: - func: KubeTask name: deleteFromStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/mysql-deploymentconfig/mysql-dep-config-blueprint.yaml b/examples/mysql-deploymentconfig/mysql-dep-config-blueprint.yaml index 1cefeb5e84..402a545956 100644 --- a/examples/mysql-deploymentconfig/mysql-dep-config-blueprint.yaml +++ b/examples/mysql-deploymentconfig/mysql-dep-config-blueprint.yaml @@ -17,7 +17,7 @@ actions: name: "{{ .DeploymentConfig.Name }}" namespace: "{{ .DeploymentConfig.Namespace }}" args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .DeploymentConfig.Namespace }}" command: - bash @@ -43,7 +43,7 @@ actions: name: "{{ .DeploymentConfig.Name }}" namespace: "{{ .DeploymentConfig.Namespace }}" args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .DeploymentConfig.Namespace }}" command: - bash @@ -63,7 +63,7 @@ actions: - func: KubeTask name: deleteFromBlobStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/mysql/README.md b/examples/mysql/README.md index fce14d5b5e..cc1fcb88ce 100755 --- a/examples/mysql/README.md +++ b/examples/mysql/README.md @@ -10,7 +10,7 @@ This chart bootstraps a single node MySQL deployment on a [Kubernetes](http://ku - Kubernetes 1.20+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster, let's assume in Namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster, let's assume in Namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) ## Installing the Chart diff --git a/examples/mysql/blueprint-v2/mysql-blueprint.yaml b/examples/mysql/blueprint-v2/mysql-blueprint.yaml index 823f85682d..7d607d2e7f 100644 --- a/examples/mysql/blueprint-v2/mysql-blueprint.yaml +++ b/examples/mysql/blueprint-v2/mysql-blueprint.yaml @@ -19,7 +19,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -47,7 +47,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -71,7 +71,7 @@ actions: - func: KubeTask name: deleteFromStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/mysql/mysql-blueprint.yaml b/examples/mysql/mysql-blueprint.yaml index eb69983bc0..4e82362da1 100644 --- a/examples/mysql/mysql-blueprint.yaml +++ b/examples/mysql/mysql-blueprint.yaml @@ -17,7 +17,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -43,7 +43,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .StatefulSet.Namespace }}" command: - bash @@ -63,7 +63,7 @@ actions: - func: KubeTask name: deleteFromBlobStore args: - image: ghcr.io/kanisterio/mysql-sidecar:0.96.0 + image: ghcr.io/kanisterio/mysql-sidecar:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/postgresql-deploymentconfig/README.md b/examples/postgresql-deploymentconfig/README.md index 1976c84c71..bc9bd11c97 100644 --- a/examples/postgresql-deploymentconfig/README.md +++ b/examples/postgresql-deploymentconfig/README.md @@ -14,7 +14,7 @@ cluster's DeploymentConfig resources. - Setup OpenShift, you can follow steps mentioned below - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster in namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster in namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) diff --git a/examples/postgresql-deploymentconfig/blueprint-v2/postgres-dep-config-blueprint.yaml b/examples/postgresql-deploymentconfig/blueprint-v2/postgres-dep-config-blueprint.yaml index 5c9ed8e778..7effaa8ea8 100644 --- a/examples/postgresql-deploymentconfig/blueprint-v2/postgres-dep-config-blueprint.yaml +++ b/examples/postgresql-deploymentconfig/blueprint-v2/postgres-dep-config-blueprint.yaml @@ -20,7 +20,7 @@ actions: name: '{{ .DeploymentConfig.Name }}-{{ .DeploymentConfig.Namespace }}' namespace: '{{ .DeploymentConfig.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .DeploymentConfig.Namespace }}' command: - bash @@ -50,7 +50,7 @@ actions: name: '{{ .DeploymentConfig.Name }}-{{ .DeploymentConfig.Namespace }}' namespace: '{{ .DeploymentConfig.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .DeploymentConfig.Namespace }}' command: - bash @@ -75,7 +75,7 @@ actions: - func: KubeTask name: deleteDump args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/postgresql-deploymentconfig/postgres-dep-config-blueprint.yaml b/examples/postgresql-deploymentconfig/postgres-dep-config-blueprint.yaml index 0dee93399c..50688d04b4 100644 --- a/examples/postgresql-deploymentconfig/postgres-dep-config-blueprint.yaml +++ b/examples/postgresql-deploymentconfig/postgres-dep-config-blueprint.yaml @@ -18,7 +18,7 @@ actions: name: '{{ .DeploymentConfig.Name }}-{{ .DeploymentConfig.Namespace }}' namespace: '{{ .DeploymentConfig.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .DeploymentConfig.Namespace }}' command: - bash @@ -47,7 +47,7 @@ actions: name: '{{ .DeploymentConfig.Name }}-{{ .DeploymentConfig.Namespace }}' namespace: '{{ .DeploymentConfig.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .DeploymentConfig.Namespace }}' command: - bash @@ -69,7 +69,7 @@ actions: - func: KubeTask name: deleteDump args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/postgresql-ha/hook-blueprint/README.md b/examples/postgresql-ha/hook-blueprint/README.md index 105e611df9..45a2aa811c 100644 --- a/examples/postgresql-ha/hook-blueprint/README.md +++ b/examples/postgresql-ha/hook-blueprint/README.md @@ -20,7 +20,7 @@ This blueprint is only required when you face above mentioned issue, else you wi - Kubernetes 1.10+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster +- Kanister controller version 0.97.0 installed in your cluster - Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) ## Installing the Chart diff --git a/examples/postgresql-ha/hook-blueprint/postgres-ha-hook.yaml b/examples/postgresql-ha/hook-blueprint/postgres-ha-hook.yaml index ec9487a869..594a45e4ea 100644 --- a/examples/postgresql-ha/hook-blueprint/postgres-ha-hook.yaml +++ b/examples/postgresql-ha/hook-blueprint/postgres-ha-hook.yaml @@ -26,7 +26,7 @@ actions: namespace: '{{ .StatefulSet.Namespace }}' args: namespace: '{{ .StatefulSet.Namespace }}' - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 command: - bash - -o diff --git a/examples/postgresql-wale/README.md b/examples/postgresql-wale/README.md index a3b75ff233..489715200c 100755 --- a/examples/postgresql-wale/README.md +++ b/examples/postgresql-wale/README.md @@ -12,7 +12,7 @@ Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment - Kubernetes 1.10+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster +- Kanister controller version 0.97.0 installed in your cluster - Kanctl CLI installed (https://docs.kanister.io/tooling.html#kanctl) ## Installing the Chart @@ -25,7 +25,7 @@ $ helm repo update $ helm install my-release bitnami/postgresql \ --namespace postgres-test --create-namespace \ --set image.repository=ghcr.io/kanisterio/postgresql \ - --set image.tag=0.96.0 \ + --set image.tag=0.97.0 \ --set postgresqlPassword=postgres-12345 \ --set postgresqlExtendedConf.archiveCommand="'envdir /bitnami/postgresql/data/env wal-e wal-push %p'" \ --set postgresqlExtendedConf.archiveMode=true \ @@ -41,7 +41,7 @@ In case, if you don't have `Kanister` installed already, you can use following c Add Kanister Helm repository and install Kanister operator ```bash $ helm repo add kanister https://charts.kanister.io -$ helm install kanister --namespace kanister --create-namespace kanister/kanister-operator --set image.tag=0.96.0 +$ helm install kanister --namespace kanister --create-namespace kanister/kanister-operator --set image.tag=0.97.0 ``` ## Integrating with Kanister diff --git a/examples/postgresql-wale/postgresql-blueprint.yaml b/examples/postgresql-wale/postgresql-blueprint.yaml index d5f63f1a6b..ec5fd40882 100644 --- a/examples/postgresql-wale/postgresql-blueprint.yaml +++ b/examples/postgresql-wale/postgresql-blueprint.yaml @@ -132,7 +132,7 @@ actions: - func: PrepareData name: performRestore args: - image: "ghcr.io/kanisterio/postgresql:0.96.0" + image: "ghcr.io/kanisterio/postgresql:0.97.0" namespace: "{{ .StatefulSet.Namespace }}" volumes: "data-{{ .StatefulSet.Name }}-0": "/bitnami/postgresql" @@ -282,7 +282,7 @@ actions: name: deleteArtifact args: namespace: "{{ .Namespace.Name }}" - image: "ghcr.io/kanisterio/postgresql:0.96.0" + image: "ghcr.io/kanisterio/postgresql:0.97.0" command: - bash - -o diff --git a/examples/postgresql/README.md b/examples/postgresql/README.md index f38423a524..e3db65a503 100755 --- a/examples/postgresql/README.md +++ b/examples/postgresql/README.md @@ -12,7 +12,7 @@ Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment - Kubernetes 1.20+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster +- Kanister controller version 0.97.0 installed in your cluster - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) ## Installing the Chart @@ -34,7 +34,7 @@ In case, if you don't have `Kanister` installed already, you can use following c Add Kanister Helm repository and install Kanister operator ```bash $ helm repo add kanister https://charts.kanister.io -$ helm install kanister --namespace kanister --create-namespace kanister/kanister-operator --set image.tag=0.96.0 +$ helm install kanister --namespace kanister --create-namespace kanister/kanister-operator --set image.tag=0.97.0 ``` ## Integrating with Kanister diff --git a/examples/postgresql/blueprint-v2/postgres-blueprint.yaml b/examples/postgresql/blueprint-v2/postgres-blueprint.yaml index 8c2121b397..2e160e138e 100644 --- a/examples/postgresql/blueprint-v2/postgres-blueprint.yaml +++ b/examples/postgresql/blueprint-v2/postgres-blueprint.yaml @@ -20,7 +20,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -50,7 +50,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -75,7 +75,7 @@ actions: - func: KubeTask name: deleteDump args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/postgresql/postgres-blueprint.yaml b/examples/postgresql/postgres-blueprint.yaml index 9c1d8ec3b8..f32c765ead 100644 --- a/examples/postgresql/postgres-blueprint.yaml +++ b/examples/postgresql/postgres-blueprint.yaml @@ -18,7 +18,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -47,7 +47,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -69,7 +69,7 @@ actions: - func: KubeTask name: deleteDump args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/postgresql/v10.16.2/postgres-blueprint.yaml b/examples/postgresql/v10.16.2/postgres-blueprint.yaml index b9b66deed1..710be2cb76 100644 --- a/examples/postgresql/v10.16.2/postgres-blueprint.yaml +++ b/examples/postgresql/v10.16.2/postgres-blueprint.yaml @@ -18,7 +18,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -47,7 +47,7 @@ actions: name: '{{ index .Object.metadata.labels "app.kubernetes.io/instance" }}-postgresql' namespace: '{{ .StatefulSet.Namespace }}' args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: '{{ .StatefulSet.Namespace }}' command: - bash @@ -69,7 +69,7 @@ actions: - func: KubeTask name: deleteDump args: - image: ghcr.io/kanisterio/postgres-kanister-tools:0.96.0 + image: ghcr.io/kanisterio/postgres-kanister-tools:0.97.0 namespace: "{{ .Namespace.Name }}" command: - bash diff --git a/examples/redis/README.md b/examples/redis/README.md index 5b3e6e94ec..d1a5328304 100644 --- a/examples/redis/README.md +++ b/examples/redis/README.md @@ -11,7 +11,7 @@ We will be using [Redis](https://github.com/bitnami/charts/tree/main/bitnami/red - Kubernetes 1.20+ - PV provisioner support in the underlying infrastructure -- Kanister controller version 0.96.0 installed in your cluster, let's assume in Namespace `kanister` +- Kanister controller version 0.97.0 installed in your cluster, let's assume in Namespace `kanister` - Kanctl CLI installed (https://docs.kanister.io/tooling.html#install-the-tools) - Docker CLI installed - A docker image containing the required tools to back up Redis. The Dockerfile for the image can be found [here](https://raw.githubusercontent.com/kanisterio/kanister/master/docker/redis-tools/Dockerfile). To build and push the docker image to your docker registry, execute [these](#build-docker-image) steps. diff --git a/examples/time-log/blueprint.yaml b/examples/time-log/blueprint.yaml index a42a1f0a7a..a4a8ca977b 100644 --- a/examples/time-log/blueprint.yaml +++ b/examples/time-log/blueprint.yaml @@ -38,7 +38,7 @@ actions: args: namespace: "{{ .Deployment.Namespace }}" pod: "{{ index .Deployment.Pods 0 }}" - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 backupArtifactPrefix: "{{ .ArtifactsIn.timeLog.KeyValue.path }}" backupIdentifier: "{{ .ArtifactsIn.backupIdentifier.KeyValue.id }}" - func: ScaleWorkload diff --git a/examples/time-log/time-logger-deployment.yaml b/examples/time-log/time-logger-deployment.yaml index bcbce207ad..8a6bee181c 100644 --- a/examples/time-log/time-logger-deployment.yaml +++ b/examples/time-log/time-logger-deployment.yaml @@ -27,7 +27,7 @@ spec: spec: containers: - name: test-container - image: ghcr.io/kanisterio/kanister-tools:0.96.0 + image: ghcr.io/kanisterio/kanister-tools:0.97.0 command: ["sh", "-c"] args: ["while true; do for x in $(seq 1200); do date >> /var/log/time.log; sleep 1; done; truncate /var/log/time.log --size 0; done"] volumeMounts: diff --git a/go.mod b/go.mod index 11af4eca40..08a205a65c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/kanisterio/kanister -go 1.19 +go 1.21.3 replace ( github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.4.1 @@ -18,7 +18,7 @@ require ( github.com/Azure/go-autorest/autorest/to v0.4.0 github.com/Masterminds/semver v1.5.0 github.com/Masterminds/sprig v2.22.0+incompatible - github.com/aws/aws-sdk-go v1.45.13 + github.com/aws/aws-sdk-go v1.45.25 github.com/dustin/go-humanize v1.0.1 github.com/go-logr/logr v1.2.4 github.com/go-openapi/strfmt v0.21.7 @@ -42,21 +42,21 @@ require ( github.com/prometheus/client_model v0.4.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 - github.com/vmware/govmomi v0.30.7 + github.com/vmware/govmomi v0.31.0 go.uber.org/zap v1.26.0 - golang.org/x/oauth2 v0.12.0 + golang.org/x/oauth2 v0.13.0 gonum.org/v1/gonum v0.14.0 - google.golang.org/api v0.142.0 + google.golang.org/api v0.147.0 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 //pinned k8s.io to v0.26.x tag - k8s.io/api v0.26.3 + k8s.io/api v0.26.9 k8s.io/apiextensions-apiserver v0.26.3 - k8s.io/apimachinery v0.26.3 + k8s.io/apimachinery v0.26.9 k8s.io/cli-runtime v0.26.3 - k8s.io/client-go v0.26.3 - k8s.io/code-generator v0.26.3 + k8s.io/client-go v0.26.9 + k8s.io/code-generator v0.26.9 k8s.io/kubectl v0.26.3 k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 sigs.k8s.io/controller-runtime v0.14.6 @@ -65,10 +65,10 @@ require ( ) require ( - cloud.google.com/go v0.110.6 // indirect + cloud.google.com/go v0.110.8 // indirect cloud.google.com/go/compute v1.23.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.1 // indirect + cloud.google.com/go/iam v1.1.2 // indirect cloud.google.com/go/storage v1.30.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 // indirect @@ -113,7 +113,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/huandu/xstrings v1.2.0 // indirect @@ -151,7 +151,7 @@ require ( github.com/rs/xid v1.4.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/xlab/treeprint v1.1.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect go.opencensus.io v0.24.0 // indirect @@ -159,23 +159,23 @@ require ( go.opentelemetry.io/otel/trace v1.15.1 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.13.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb // indirect - google.golang.org/grpc v1.57.0 // indirect + google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.2 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 6076abb3aa..0e272ea106 100644 --- a/go.sum +++ b/go.sum @@ -6,32 +6,35 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= -cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= +cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= +cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= +github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0 h1:VuHAcMq8pU1IWNT/m5yRaGqbK0BiQKHT8X4DTp9CHdI= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.3.0/go.mod h1:tZoQYdDZNOiIjdSn0dVWVfl0NEPGOJqVLzSrcFk4Is0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1 h1:Oj853U9kG+RLTCQXpjvOnrv0WaZHxgmZz1TlLywgOPY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.1/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk= +github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -72,9 +75,11 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 h1:KeNholpO2xKjgaaSyd+DyQRrsQjhbSeS7qe4nEw8aQw= +github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962/go.mod h1:kC29dT1vFpj7py2OvG1khBdQpo3kInWP+6QipLbdngo= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -89,11 +94,13 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= +github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.45.13 h1:LwD/G+PX7FQnbU8wXekx12e90i1GuKJQC2+pl4IlPAs= -github.com/aws/aws-sdk-go v1.45.13/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= +github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -103,6 +110,7 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= +github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chmduquesne/rollinghash v4.0.0+incompatible h1:hnREQO+DXjqIw3rUTzWN7/+Dpw+N5Um8zpKV0JOEgbo= github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dge82bi3RU0OQUmXT9iweIcPqvr8A0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -115,6 +123,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -122,9 +131,11 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02 h1:tR3jsKPiO/mb6ntzk/dJlHZtm37CPfVp1C9KIo534+4= +github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02/go.mod h1:7NQ3kWOx2cZOSjtcveTa5nqupVr2s6/83sG+rTlI7uA= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= @@ -150,6 +161,7 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/frankban/quicktest v1.13.1 h1:xVm/f9seEhZFL9+n5kv5XLrGwy6elc4V9v/XFY2vmd8= +github.com/frankban/quicktest v1.13.1/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -190,13 +202,16 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= @@ -252,6 +267,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -264,18 +280,20 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/hanwen/go-fuse/v2 v2.3.0 h1:t5ivNIH2PK+zw4OBul/iJjsoG9K6kXo4nMDoBpciC8A= +github.com/hanwen/go-fuse/v2 v2.3.0/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -324,11 +342,13 @@ github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/klauspost/reedsolomon v1.11.7 h1:9uaHU0slncktTEEg4+7Vl7q7XUNMBUOK4R9gnKhMjAU= github.com/klauspost/reedsolomon v1.11.7/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A= github.com/kopia/htmluibuild v0.0.0-20230326183719-f482ef17e2c9 h1:s5Wa89s8RlPjuwqd8K8kuf+T9Kz4+NsbKwR/pJ3PAT0= +github.com/kopia/htmluibuild v0.0.0-20230326183719-f482ef17e2c9/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw= github.com/kopia/kopia v0.13.1-0.20230605143225-3551f743d762 h1:DPWqxB77wWG8ZuoMLXSq6DxrVNqQqbvNu0YRohN9sNk= github.com/kopia/kopia v0.13.1-0.20230605143225-3551f743d762/go.mod h1:gOXUOqfha+vBhx755GPEy/Ypk5m/6wzHTx/XP8VLmFk= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -337,6 +357,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA= github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -348,6 +369,7 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI= +github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= @@ -394,9 +416,11 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= +github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= github.com/openshift/api v0.0.0-20230406152840-ce21e3fe5da2 h1:lpKBKpI8or60mSEEKrpS67cevp8XaW8vfmXSwCZXKd0= github.com/openshift/api v0.0.0-20230406152840-ce21e3fe5da2/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= github.com/openshift/client-go v0.0.0-20230324103026-3f1513df25e0 h1:ftAVjdiw4/Bnav0Fvw9mxoa0kU1lGK8GKRn28eja8Ik= @@ -406,6 +430,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -429,6 +454,7 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -452,24 +478,27 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tg123/go-htpasswd v1.2.1 h1:i4wfsX1KvvkyoMiHZzjS0VzbAPWfxzI8INcZAKtutoU= +github.com/tg123/go-htpasswd v1.2.1/go.mod h1:erHp1B86KXdwQf1X5ZrLb7erXZnWueEQezb2dql4q58= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/vmware/govmomi v0.30.7 h1:YO8CcDpLJzmq6PK5/CBQbXyV21iCMh8SbdXt+xNkXp8= -github.com/vmware/govmomi v0.30.7/go.mod h1:epgoslm97rLECMV4D+08ORzUBEU7boFSepKjt7AYVGg= +github.com/vmware/govmomi v0.31.0 h1:+NC7le8yeXj7f4YUC841jgdWsehN7A3ivqLxm79eKyo= +github.com/vmware/govmomi v0.31.0/go.mod h1:JA63Pg0SgQcSjk+LuPzjh3rJdcWBo/ZNCIwbb1qf2/0= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zalando/go-keyring v0.2.2 h1:f0xmpYiSrHtSNAVgwip93Cg8tuF45HJM6rHq/A5RI/4= +github.com/zalando/go-keyring v0.2.2/go.mod h1:sI3evg9Wvpw3+n4SqplGSJUMwtDeROfD4nsFz4z9PG0= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= @@ -492,6 +521,7 @@ go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0H go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -510,8 +540,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -565,15 +595,15 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -583,8 +613,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -615,14 +645,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -685,8 +715,8 @@ google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.142.0 h1:mf+7EJ94fi5ZcnpPy+m0Yv2dkz8bKm+UL0snTCuwXlY= -google.golang.org/api v0.142.0/go.mod h1:zJAN5o6HRqR7O+9qJUFOWrZkYE66RH+efPBdTLA4xBA= +google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= +google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -705,12 +735,12 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb h1:Isk1sSH7bovx8Rti2wZK0UZF6oraBDK74uoyLEEVFN0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -719,8 +749,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -757,27 +787,28 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= -k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= -k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +k8s.io/api v0.26.9 h1:s8Y+G1u2JM55b90+Yo2RVb3PGT/hkWNVPN4idPERxJg= +k8s.io/api v0.26.9/go.mod h1:W/W4fEWRVzPD36820LlVUQfNBiSbiq0VPWRFJKwzmUg= k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE= k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ= k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= -k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/apimachinery v0.26.9 h1:5yAV9cFR7Z4gIorKcAjWnx4uxtxiFsERwq4Pvmx0CCg= +k8s.io/apimachinery v0.26.9/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0= k8s.io/cli-runtime v0.26.3 h1:3ULe0oI28xmgeLMVXIstB+ZL5CTGvWSMVMLeHxitIuc= k8s.io/cli-runtime v0.26.3/go.mod h1:5YEhXLV4kLt/OSy9yQwtSSNZU2Z7aTEYta1A+Jg4VC4= k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU= -k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= -k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= +k8s.io/client-go v0.26.9 h1:TGWi/6guEjIgT0Hg871Gsmx0qFuoGyGFjlFedrk7It0= +k8s.io/client-go v0.26.9/go.mod h1:tU1FZS0bwAmAFyPYpZycUQrQnUMzQ5MHloop7EbX6ow= k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= -k8s.io/code-generator v0.26.3 h1:DNYPsWoeFwmg4qFg97Z1cHSSv7KSG10mAEIFoZGTQM8= -k8s.io/code-generator v0.26.3/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= +k8s.io/code-generator v0.26.9 h1:GiS9v3UE3bpE6Zp3sr9ooNJpZXwscjdyzMMVYWk6UmI= +k8s.io/code-generator v0.26.9/go.mod h1:seNkA/wYpeG1GT1REW1xHk4MCjQcVbx6FFAXKwCgdlE= k8s.io/component-base v0.26.3 h1:oC0WMK/ggcbGDTkdcqefI4wIZRYdK3JySx9/HADpV0g= k8s.io/component-base v0.26.3/go.mod h1:5kj1kZYwSC6ZstHJN7oHBqcJC6yyn41eR+Sqa/mQc8E= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= diff --git a/helm/kanister-operator/Chart.yaml b/helm/kanister-operator/Chart.yaml index 5b7476bdcc..fc4fd37b1c 100644 --- a/helm/kanister-operator/Chart.yaml +++ b/helm/kanister-operator/Chart.yaml @@ -9,5 +9,5 @@ maintainers: - email: tom@kasten.io name: tdmanv icon: https://kasten.io/assets/img/kanister-logo.png -appVersion: 0.96.0 +appVersion: 0.97.0 source: https://github.com/kanisterio/kanister diff --git a/helm/kanister-operator/values.yaml b/helm/kanister-operator/values.yaml index 5ce8c010e2..0f104c521a 100644 --- a/helm/kanister-operator/values.yaml +++ b/helm/kanister-operator/values.yaml @@ -3,17 +3,17 @@ # Declare variables to be passed into your templates. image: repository: ghcr.io/kanisterio/controller - tag: 0.96.0 + tag: 0.97.0 pullPolicy: IfNotPresent repositoryServerControllerImage: registry: ghcr.io/kanisterio name: repo-server-controller - tag: 0.96.0 + tag: 0.97.0 pullPolicy: IfNotPresent kanisterToolsImage: override: false image: ghcr.io/kanisterio/kanister-tools - tag: 0.96.0 + tag: 0.97.0 rbac: create: true serviceAccount: diff --git a/helm/profile/Chart.yaml b/helm/profile/Chart.yaml index dea682a323..4759106508 100644 --- a/helm/profile/Chart.yaml +++ b/helm/profile/Chart.yaml @@ -3,7 +3,7 @@ description: A helm chart to create profile custom resource for kanister engine: gotpl name: profile home: https://kanister.io/ -version: 0.96.0 +version: 0.97.0 maintainers: - email: tom@kasten.io name: tdmanv diff --git a/pkg/apis/cr/v1alpha1/types.go b/pkg/apis/cr/v1alpha1/types.go index eec65c73ce..1aa90de0fd 100644 --- a/pkg/apis/cr/v1alpha1/types.go +++ b/pkg/apis/cr/v1alpha1/types.go @@ -147,7 +147,8 @@ type ActionStatus struct { DeferPhase Phase `json:"deferPhase,omitempty"` } -// ActionProgress provides information on the progress of an action. +// ActionProgress provides information on the combined progress +// of all the phases in the action. type ActionProgress struct { // RunningPhase represents which phase of the action is being run RunningPhase string `json:"runningPhase,omitempty"` @@ -187,6 +188,28 @@ type Phase struct { State State `json:"state"` // Output is the map of output artifacts produced by the Blueprint phase. Output map[string]interface{} `json:"output,omitempty"` + // Progress represents the phase execution progress. + Progress PhaseProgress `json:"progress,omitempty"` +} + +// PhaseProgress represents the execution state of the phase. +type PhaseProgress struct { + // ProgressPercent represents the execution progress in percentage. + ProgressPercent string `json:"progressPercent,omitempty"` + // SizeUploadedB represents the size of data uploaded in Bytes at a given time during phase execution. + // This field will be empty for phases which do not involve data movement. + SizeUploadedB int64 `json:"sizeUploadedB,omitempty"` + // EstimatedUploadSizeB represents the total estimated size of data in Bytes + // that will be uploaded during the phase execution. + // This field will be empty for phases which do not involve data movement. + EstimatedUploadSizeB int64 `json:"estinatedUploadSizeB,omitempty"` + // EstimatedTimeSeconds is the estimated time required in seconds to upload the + // remaining data estimated with EstimatedUploadSizeB. + // This field will be empty for phases which do not involve data movement. + EstimatedTimeSeconds int64 `json:"estinatedTimeSeconds,omitempty"` + // LastTransitionTime represents the last date time when the progress status + // was received. + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` } // k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go index 691ce62c11..406efd37d8 100644 --- a/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/cr/v1alpha1/zz_generated.deepcopy.go @@ -627,6 +627,26 @@ func (in *Phase) DeepCopy() *Phase { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PhaseProgress) DeepCopyInto(out *PhaseProgress) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PhaseProgress. +func (in *PhaseProgress) DeepCopy() *PhaseProgress { + if in == nil { + return nil + } + out := new(PhaseProgress) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile) DeepCopyInto(out *Profile) { *out = *in diff --git a/pkg/app/csi-snapshot.go b/pkg/app/csi-snapshot.go index 849c52ef79..db891f7193 100644 --- a/pkg/app/csi-snapshot.go +++ b/pkg/app/csi-snapshot.go @@ -192,7 +192,7 @@ func (tlc TimeLogCSI) getAppDeploymentObj() *appsv1.Deployment { Containers: []v1.Container{ { Name: "test-container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c"}, Args: []string{"while true; do for x in $(seq 1200); do date >> /var/log/time.log; sleep 1; done; truncate /var/log/time.log --size 0; done"}, VolumeMounts: []v1.VolumeMount{ diff --git a/pkg/blueprint/validate/validate_test.go b/pkg/blueprint/validate/validate_test.go index c7382caff2..c22ee38c17 100644 --- a/pkg/blueprint/validate/validate_test.go +++ b/pkg/blueprint/validate/validate_test.go @@ -438,7 +438,9 @@ func blueprint() *crv1alpha1.Blueprint { } } -type nonDefaultVersionFunc struct{} +type nonDefaultVersionFunc struct { + progressPercent string +} func (nd *nonDefaultVersionFunc) Name() string { return "NonDefaultVersionFunc" @@ -453,9 +455,15 @@ func (nd *nonDefaultVersionFunc) Arguments() []string { } func (nd *nonDefaultVersionFunc) Exec(context.Context, param.TemplateParams, map[string]interface{}) (map[string]interface{}, error) { + nd.progressPercent = "0" + defer func() { nd.progressPercent = "100" }() return nil, nil } +func (nd *nonDefaultVersionFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + return crv1alpha1.PhaseProgress{ProgressPercent: nd.progressPercent}, nil +} + var _ kanister.Func = (*nonDefaultVersionFunc)(nil) func init() { diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 5d36db7095..79c0c1e3b3 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -43,7 +43,7 @@ const RepositoryServerResourceName = "repositoryserver" const RepositoryServerResourceNamePlural = "repositoryservers" const LatestKanisterToolsImage = "ghcr.io/kanisterio/kanister-tools:v9.99.9-dev" -const KanisterToolsImage = "ghcr.io/kanisterio/kanister-tools:0.96.0" +const KanisterToolsImage = "ghcr.io/kanisterio/kanister-tools:0.97.0" // KanisterToolsImageEnvName is used to set up a custom kanister-tools image const KanisterToolsImageEnvName = "KANISTER_TOOLS" diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 46fde9b65e..e06dc34c7f 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -394,14 +394,6 @@ func (c *Controller) handleActionSet(ctx context.Context, t *tomb.Tomb, as *crv1 } } - go func() { - // progress update is computed on a best-effort basis. - // if it exits with error, we will just log it. - if err := progress.TrackActionsProgress(ctx, c.crClient, as.GetName(), as.GetNamespace()); err != nil { - log.Error().WithError(err) - } - }() - for i, a := range as.Status.Actions { var bp *crv1alpha1.Blueprint if bp, err = c.crClient.CrV1alpha1().Blueprints(as.GetNamespace()).Get(ctx, a.Blueprint, v1.GetOptions{}); err != nil { @@ -471,7 +463,7 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 defer func() { var deferErr error if deferPhase != nil { - c.updateActionSetRunningPhase(ctx, as, deferPhase.Name()) + c.updateActionSetRunningPhase(ctx, aIDX, as, deferPhase.Name()) deferErr = c.executeDeferPhase(ctx, deferPhase, tp, bp, action.Name, aIDX, as) } // render artifacts only if all the phases are run successfully @@ -490,11 +482,22 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 var output map[string]interface{} var msg string if err == nil { - c.updateActionSetRunningPhase(ctx, as, p.Name()) + c.updateActionSetRunningPhase(ctx, aIDX, as, p.Name()) + progressTrackCtx, doneProgressTrack := context.WithCancel(ctx) + defer doneProgressTrack() + go func() { + // progress update is computed on a best-effort basis. + // if it exits with error, we will just log it. + if err := progress.UpdateActionSetsProgress(progressTrackCtx, aIDX, c.crClient, as.GetName(), as.GetNamespace(), p); err != nil { + log.Error().WithError(err) + } + }() output, err = p.Exec(ctx, *bp, action.Name, *tp) + doneProgressTrack() } else { msg = fmt.Sprintf("Failed to init phase params: %#v:", as.Status.Actions[aIDX].Phases[i]) } + var rf func(*crv1alpha1.ActionSet) error if err != nil { coreErr = err @@ -511,8 +514,17 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 coreErr = nil rf = func(ras *crv1alpha1.ActionSet) error { ras.Status.Actions[aIDX].Phases[i].State = crv1alpha1.StateComplete + pp, err := p.Progress() + if err != nil { + log.Error().WithError(err) + return nil + } + ras.Status.Actions[aIDX].Phases[i].Progress = pp // this updates the phase output in the actionset status ras.Status.Actions[aIDX].Phases[i].Output = output + if err := progress.SetActionSetPercentCompleted(ras); err != nil { + log.Error().WithError(err) + } return nil } } @@ -545,9 +557,15 @@ func (c *Controller) runAction(ctx context.Context, t *tomb.Tomb, as *crv1alpha1 // updateActionSetRunningPhase updates the actionset's `status.Progress.RunningPhase` with the phase name // that is being run currently. It doesn't fail if there was a problem updating the actionset. It just logs // the failure. -func (c *Controller) updateActionSetRunningPhase(ctx context.Context, as *crv1alpha1.ActionSet, phase string) { +func (c *Controller) updateActionSetRunningPhase(ctx context.Context, aIDX int, as *crv1alpha1.ActionSet, phase string) { err := reconcile.ActionSet(ctx, c.crClient.CrV1alpha1(), as.Namespace, as.Name, func(as *crv1alpha1.ActionSet) error { as.Status.Progress.RunningPhase = phase + // Iterate through all the phases and set current phase state to running + for i := 0; i < len(as.Status.Actions[aIDX].Phases); i++ { + if as.Status.Actions[aIDX].Phases[i].Name == phase { + as.Status.Actions[aIDX].Phases[i].State = crv1alpha1.StateRunning + } + } return nil }) if err != nil { diff --git a/pkg/controllers/repositoryserver/handler.go b/pkg/controllers/repositoryserver/handler.go index 347831dc44..e9dc857692 100644 --- a/pkg/controllers/repositoryserver/handler.go +++ b/pkg/controllers/repositoryserver/handler.go @@ -267,7 +267,7 @@ func (h *RepoServerHandler) setCredDataFromSecretInPod(ctx context.Context, podO h.Logger.Info("Setting credentials data from secret as env variables") podOptions.EnvironmentVariables = envVars } - pod, err = kube.GetPodObjectFromPodOptions(h.KubeCli, podOptions) + pod, err = kube.GetPodObjectFromPodOptions(ctx, h.KubeCli, podOptions) if err != nil { return nil, nil, err } diff --git a/pkg/controllers/repositoryserver/utils.go b/pkg/controllers/repositoryserver/utils.go index 513142d11f..0c2980f419 100644 --- a/pkg/controllers/repositoryserver/utils.go +++ b/pkg/controllers/repositoryserver/utils.go @@ -199,7 +199,7 @@ func addTLSCertConfigurationInPodOverride(podOverride *map[string]interface{}, t return nil } -func getPodOptions(namespace string, svc *corev1.Service, vols map[string]string) *kube.PodOptions { +func getPodOptions(namespace string, svc *corev1.Service, vols map[string]kube.VolumeMountOptions) *kube.PodOptions { uidguid := int64(0) nonRootBool := false return &kube.PodOptions{ @@ -253,8 +253,13 @@ func getCondition(status metav1.ConditionStatus, reason string, message string, } } -func getVolumes(ctx context.Context, cli kubernetes.Interface, secret *corev1.Secret, namespace string) (map[string]string, error) { - vols := make(map[string]string, 0) +func getVolumes( + ctx context.Context, + cli kubernetes.Interface, + secret *corev1.Secret, + namespace string, +) (map[string]kube.VolumeMountOptions, error) { + vols := make(map[string]kube.VolumeMountOptions, 0) var claimName []byte if len(secret.Data) == 0 { return nil, errors.Errorf(secerrors.EmptySecretErrorMessage, secret.Namespace, secret.Name) @@ -263,11 +268,17 @@ func getVolumes(ctx context.Context, cli kubernetes.Interface, secret *corev1.Se if claimName, ok = secret.Data[reposerver.ClaimNameKey]; !ok { return nil, errors.New("Claim name not set for file store location secret, failed to retrieve PVC") } + claimNameString := string(claimName) - if _, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, claimNameString, metav1.GetOptions{}); err != nil { + pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, claimNameString, metav1.GetOptions{}) + if err != nil { return nil, errors.Wrapf(err, "Failed to validate if PVC %s:%s exists", namespace, claimName) } - vols[claimNameString] = storage.DefaultFSMountPath + + vols[claimNameString] = kube.VolumeMountOptions{ + MountPath: storage.DefaultFSMountPath, + ReadOnly: kube.PVCContainsReadOnlyAccessMode(pvc), + } } return vols, nil } diff --git a/pkg/customresource/actionset.yaml b/pkg/customresource/actionset.yaml index db0ee28548..ca00e29bd3 100644 --- a/pkg/customresource/actionset.yaml +++ b/pkg/customresource/actionset.yaml @@ -267,6 +267,20 @@ spec: type: object state: type: string + progress: + properties: + progressPercent: + type: string + sizeUploadedB: + type: integer + estimatedTimeSeconds: + type: integer + estimatedUploadSizeB: + type: integer + lastTransitionTime: + type: string + format: date-time + type: object type: object phases: description: Phases are sub-actions an are executed sequentially. @@ -279,6 +293,20 @@ spec: type: object state: type: string + progress: + properties: + progressPercent: + type: string + sizeUploadedB: + type: integer + estimatedTimeSeconds: + type: integer + estimatedUploadSizeB: + type: integer + lastTransitionTime: + type: string + format: date-time + type: object type: object type: array type: object diff --git a/pkg/function/backup_data.go b/pkg/function/backup_data.go index f8210eda28..8dc2396cd4 100644 --- a/pkg/function/backup_data.go +++ b/pkg/function/backup_data.go @@ -16,18 +16,22 @@ package function import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -64,13 +68,19 @@ func init() { var _ kanister.Func = (*backupDataFunc)(nil) -type backupDataFunc struct{} +type backupDataFunc struct { + progressPercent string +} func (*backupDataFunc) Name() string { return BackupDataFuncName } -func (*backupDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *backupDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, pod, container, includePath, backupArtifactPrefix, encryptionKey string var err error if err = Arg(args, BackupDataNamespaceArg, &namespace); err != nil { @@ -188,3 +198,11 @@ func backupData(ctx context.Context, cli kubernetes.Interface, namespace, pod, c phySize: phySize, }, nil } + +func (b *backupDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_all.go b/pkg/function/backup_data_all.go index 66cece7ded..00b56c91dd 100644 --- a/pkg/function/backup_data_all.go +++ b/pkg/function/backup_data_all.go @@ -19,15 +19,19 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -62,13 +66,19 @@ func init() { var _ kanister.Func = (*backupDataAllFunc)(nil) -type backupDataAllFunc struct{} +type backupDataAllFunc struct { + progressPercent string +} func (*backupDataAllFunc) Name() string { return BackupDataAllFuncName } -func (*backupDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *backupDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, pods, container, includePath, backupArtifactPrefix, encryptionKey string var err error if err = Arg(args, BackupDataAllNamespaceArg, &namespace); err != nil { @@ -172,3 +182,11 @@ func backupDataAll(ctx context.Context, cli kubernetes.Interface, namespace stri FunctionOutputVersion: kanister.DefaultVersion, }, nil } + +func (b *backupDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_stats.go b/pkg/function/backup_data_stats.go index 3f23fe4f84..60e5a2a14c 100644 --- a/pkg/function/backup_data_stats.go +++ b/pkg/function/backup_data_stats.go @@ -17,8 +17,10 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -27,6 +29,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -56,7 +59,9 @@ func init() { var _ kanister.Func = (*BackupDataStatsFunc)(nil) -type BackupDataStatsFunc struct{} +type BackupDataStatsFunc struct { + progressPercent string +} func (*BackupDataStatsFunc) Name() string { return BackupDataStatsFuncName @@ -72,7 +77,7 @@ func backupDataStats(ctx context.Context, cli kubernetes.Interface, tp param.Tem } pr := kube.NewPodRunner(cli, options) podFunc := backupDataStatsPodFunc(tp, encryptionKey, backupArtifactPrefix, backupID, mode) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func backupDataStatsPodFunc( @@ -130,7 +135,11 @@ func backupDataStatsPodFunc( } } -func (*BackupDataStatsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (b *BackupDataStatsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var namespace, backupArtifactPrefix, backupID, mode, encryptionKey string var err error if err = Arg(args, BackupDataStatsNamespaceArg, &namespace); err != nil { @@ -148,7 +157,7 @@ func (*BackupDataStatsFunc) Exec(ctx context.Context, tp param.TemplateParams, a if err = OptArg(args, BackupDataStatsEncryptionKeyArg, &encryptionKey, restic.GeneratePassword()); err != nil { return nil, err } - podOverride, err := GetPodSpecOverride(tp, args, DescribeBackupsPodOverrideArg) + podOverride, err := GetPodSpecOverride(tp, args, CheckRepositoryPodOverrideArg) if err != nil { return nil, err } @@ -183,3 +192,11 @@ func (*BackupDataStatsFunc) Arguments() []string { BackupDataStatsEncryptionKeyArg, } } + +func (b *BackupDataStatsFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/backup_data_using_kopia_server.go b/pkg/function/backup_data_using_kopia_server.go index 19e542dc7e..cab01e988a 100644 --- a/pkg/function/backup_data_using_kopia_server.go +++ b/pkg/function/backup_data_using_kopia_server.go @@ -19,18 +19,22 @@ import ( "encoding/base64" "encoding/json" "strings" + "time" "github.com/dustin/go-humanize" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" kankopia "github.com/kanisterio/kanister/pkg/kopia" kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" kerrors "github.com/kanisterio/kanister/pkg/kopia/errors" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/utils" ) @@ -42,7 +46,9 @@ const ( KopiaRepositoryServerUserHostname = "repositoryServerUserHostname" ) -type backupDataUsingKopiaServerFunc struct{} +type backupDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { err := kanister.Register(&backupDataUsingKopiaServerFunc{}) @@ -77,7 +83,11 @@ func (*backupDataUsingKopiaServerFunc) Arguments() []string { } } -func (*backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (b *backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + b.progressPercent = progress.StartedPercent + defer func() { b.progressPercent = progress.CompletedPercent }() + var ( container string err error @@ -163,6 +173,14 @@ func (*backupDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templa return output, nil } +func (b *backupDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: b.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func backupDataUsingKopiaServer( cli kubernetes.Interface, container, diff --git a/pkg/function/checkRepository.go b/pkg/function/checkRepository.go index 88056b56e4..a240f20e15 100644 --- a/pkg/function/checkRepository.go +++ b/pkg/function/checkRepository.go @@ -3,8 +3,10 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -12,6 +14,7 @@ import ( "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -35,7 +38,9 @@ func init() { var _ kanister.Func = (*CheckRepositoryFunc)(nil) -type CheckRepositoryFunc struct{} +type CheckRepositoryFunc struct { + progressPercent string +} func (*CheckRepositoryFunc) Name() string { return CheckRepositoryFuncName @@ -55,7 +60,7 @@ func CheckRepository(ctx context.Context, cli kubernetes.Interface, tp param.Tem } pr := kube.NewPodRunner(cli, options) podFunc := CheckRepositoryPodFunc(cli, tp, encryptionKey, targetPaths) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func CheckRepositoryPodFunc( @@ -115,7 +120,11 @@ func CheckRepositoryPodFunc( } } -func (*CheckRepositoryFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *CheckRepositoryFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var checkRepositoryArtifactPrefix, encryptionKey string if err := Arg(args, CheckRepositoryArtifactPrefixArg, &checkRepositoryArtifactPrefix); err != nil { return nil, err @@ -151,3 +160,10 @@ func (*CheckRepositoryFunc) Arguments() []string { CheckRepositoryEncryptionKeyArg, } } +func (c *CheckRepositoryFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/copy_volume_data.go b/pkg/function/copy_volume_data.go index f96ebd2913..ee263a451c 100644 --- a/pkg/function/copy_volume_data.go +++ b/pkg/function/copy_volume_data.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,11 +26,13 @@ import ( "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -58,30 +61,46 @@ func init() { var _ kanister.Func = (*copyVolumeDataFunc)(nil) -type copyVolumeDataFunc struct{} +type copyVolumeDataFunc struct { + progressPercent string +} func (*copyVolumeDataFunc) Name() string { return CopyVolumeDataFuncName } -func copyVolumeData(ctx context.Context, cli kubernetes.Interface, tp param.TemplateParams, namespace, pvc, targetPath, encryptionKey string, podOverride map[string]interface{}) (map[string]interface{}, error) { +func copyVolumeData( + ctx context.Context, + cli kubernetes.Interface, + tp param.TemplateParams, + namespace, + pvcName, + targetPath, + encryptionKey string, + podOverride map[string]interface{}, +) (map[string]interface{}, error) { // Validate PVC exists - if _, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvc, metav1.GetOptions{}); err != nil { - return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvc) + pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvcName) } + // Create a pod with PVCs attached - mountPoint := fmt.Sprintf(CopyVolumeDataMountPoint, pvc) + mountPoint := fmt.Sprintf(CopyVolumeDataMountPoint, pvcName) options := &kube.PodOptions{ Namespace: namespace, GenerateName: CopyVolumeDataJobPrefix, Image: consts.GetKanisterToolsImage(), Command: []string{"sh", "-c", "tail -f /dev/null"}, - Volumes: map[string]string{pvc: mountPoint}, - PodOverride: podOverride, + Volumes: map[string]kube.VolumeMountOptions{pvcName: { + MountPath: mountPoint, + ReadOnly: kube.PVCContainsReadOnlyAccessMode(pvc), + }}, + PodOverride: podOverride, } pr := kube.NewPodRunner(cli, options) podFunc := copyVolumeDataPodFunc(cli, tp, mountPoint, targetPath, encryptionKey) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func copyVolumeDataPodFunc( @@ -158,7 +177,11 @@ func copyVolumeDataPodFunc( } } -func (*copyVolumeDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *copyVolumeDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var namespace, vol, targetPath, encryptionKey string var err error if err = Arg(args, CopyVolumeDataNamespaceArg, &namespace); err != nil { @@ -207,3 +230,11 @@ func (*copyVolumeDataFunc) Arguments() []string { CopyVolumeDataEncryptionKeyArg, } } + +func (c *copyVolumeDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_csi_snapshot.go b/pkg/function/create_csi_snapshot.go index abcf9bb58d..fde31a2c72 100644 --- a/pkg/function/create_csi_snapshot.go +++ b/pkg/function/create_csi_snapshot.go @@ -17,15 +17,19 @@ package function import ( "context" "fmt" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -55,13 +59,19 @@ const ( CreateCSISnapshotSnapshotContentNameArg = "snapshotContent" ) -type createCSISnapshotFunc struct{} +type createCSISnapshotFunc struct { + progressPercent string +} func (*createCSISnapshotFunc) Name() string { return CreateCSISnapshotFuncName } -func (*createCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var snapshotClass string var labels map[string]string var name, pvc, namespace string @@ -147,3 +157,11 @@ func createCSISnapshot(ctx context.Context, snapshotter snapshot.Snapshotter, na func defaultSnapshotName(pvcName string, len int) string { return fmt.Sprintf("%s-snapshot-%s", pvcName, rand.String(len)) } + +func (c *createCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_csi_snapshot_static.go b/pkg/function/create_csi_snapshot_static.go index 3ffc7401b1..d82c96142f 100644 --- a/pkg/function/create_csi_snapshot_static.go +++ b/pkg/function/create_csi_snapshot_static.go @@ -16,13 +16,17 @@ package function import ( "context" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -59,13 +63,19 @@ const ( CreateCSISnapshotStaticOutputSnapshotContentName = "snapshotContent" ) -type createCSISnapshotStaticFunc struct{} +type createCSISnapshotStaticFunc struct { + progressPercent string +} func (*createCSISnapshotStaticFunc) Name() string { return CreateCSISnapshotStaticFuncName } -func (*createCSISnapshotStaticFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createCSISnapshotStaticFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + var ( name, namespace string driver, snapshotHandle, snapshotClass string @@ -158,3 +168,11 @@ func createCSISnapshotStatic( return snapshotter.Get(ctx, name, namespace) } + +func (c *createCSISnapshotStaticFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_rds_snapshot.go b/pkg/function/create_rds_snapshot.go index e64e9e813f..5cf40964fd 100644 --- a/pkg/function/create_rds_snapshot.go +++ b/pkg/function/create_rds_snapshot.go @@ -18,16 +18,20 @@ import ( "context" "fmt" "strconv" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/yaml" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -61,7 +65,9 @@ const ( DBEngineAuroraPostgreSQL RDSDBEngine = "aurora-postgresql" ) -type createRDSSnapshotFunc struct{} +type createRDSSnapshotFunc struct { + progressPercent string +} func (*createRDSSnapshotFunc) Name() string { return CreateRDSSnapshotFuncName @@ -155,6 +161,10 @@ func createRDSSnapshot(ctx context.Context, instanceID string, dbEngine RDSDBEng } func (crs *createRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var instanceID string var dbEngine RDSDBEngine if err := Arg(args, CreateRDSSnapshotInstanceIDArg, &instanceID); err != nil { @@ -180,3 +190,11 @@ func (crs *createRDSSnapshotFunc) Arguments() []string { CreateRDSSnapshotDBEngine, } } + +func (crs *createRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: crs.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_volume_from_snapshot.go b/pkg/function/create_volume_from_snapshot.go index d4313f3838..17c54ff3b9 100644 --- a/pkg/function/create_volume_from_snapshot.go +++ b/pkg/function/create_volume_from_snapshot.go @@ -17,12 +17,14 @@ package function import ( "context" "encoding/json" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" @@ -31,6 +33,7 @@ import ( kubevolume "github.com/kanisterio/kanister/pkg/kube/volume" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -49,7 +52,9 @@ const ( CreateVolumeFromSnapshotPVCNamesArg = "pvcNames" ) -type createVolumeFromSnapshotFunc struct{} +type createVolumeFromSnapshotFunc struct { + progressPercent string +} func (*createVolumeFromSnapshotFunc) Name() string { return CreateVolumeFromSnapshotFuncName @@ -120,7 +125,11 @@ func createVolumeFromSnapshot(ctx context.Context, cli kubernetes.Interface, nam return providerList, nil } -func (kef *createVolumeFromSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createVolumeFromSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -154,3 +163,11 @@ func (*createVolumeFromSnapshotFunc) Arguments() []string { CreateVolumeFromSnapshotPVCNamesArg, } } + +func (crs *createVolumeFromSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: crs.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/create_volume_snapshot.go b/pkg/function/create_volume_snapshot.go index 87f28684e7..a4395a6189 100644 --- a/pkg/function/create_volume_snapshot.go +++ b/pkg/function/create_volume_snapshot.go @@ -21,6 +21,7 @@ import ( "path/filepath" "strings" "sync" + "time" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" @@ -35,6 +36,7 @@ import ( "github.com/kanisterio/kanister/pkg/blockstorage/getter" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/secrets" ) @@ -54,7 +56,9 @@ const ( CreateVolumeSnapshotSkipWaitArg = "skipWait" ) -type createVolumeSnapshotFunc struct{} +type createVolumeSnapshotFunc struct { + progressPercent string +} func (*createVolumeSnapshotFunc) Name() string { return CreateVolumeSnapshotFuncName @@ -261,7 +265,11 @@ func getPVCList(tp param.TemplateParams) ([]string, error) { return pvcList, nil } -func (kef *createVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (c *createVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + c.progressPercent = progress.StartedPercent + defer func() { c.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -317,3 +325,11 @@ func (*createVolumeSnapshotFunc) Arguments() []string { CreateVolumeSnapshotSkipWaitArg, } } + +func (c *createVolumeSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/data_test.go b/pkg/function/data_test.go index a6ad4cc8bf..63ca6f077e 100644 --- a/pkg/function/data_test.go +++ b/pkg/function/data_test.go @@ -135,7 +135,7 @@ func newRestoreDataBlueprint(pvc, identifierArg, identifierVal string) *crv1alph Func: RestoreDataFuncName, Args: map[string]interface{}{ RestoreDataNamespaceArg: "{{ .StatefulSet.Namespace }}", - RestoreDataImageArg: "ghcr.io/kanisterio/kanister-tools:0.96.0", + RestoreDataImageArg: "ghcr.io/kanisterio/kanister-tools:0.97.0", RestoreDataBackupArtifactPrefixArg: "{{ .Profile.Location.Bucket }}/{{ .Profile.Location.Prefix }}", RestoreDataRestorePathArg: "/mnt/data", RestoreDataEncryptionKeyArg: "{{ .Secrets.backupKey.Data.password | toString }}", @@ -175,26 +175,6 @@ func newBackupDataBlueprint() *crv1alpha1.Blueprint { } } -func newDescribeBackupsBlueprint() *crv1alpha1.Blueprint { - return &crv1alpha1.Blueprint{ - Actions: map[string]*crv1alpha1.BlueprintAction{ - "describeBackups": { - Kind: param.StatefulSetKind, - Phases: []crv1alpha1.BlueprintPhase{ - { - Name: "testDescribeBackups", - Func: DescribeBackupsFuncName, - Args: map[string]interface{}{ - DescribeBackupsArtifactPrefixArg: "{{ .Profile.Location.Prefix }}", - DescribeBackupsEncryptionKeyArg: "{{ .Secrets.backupKey.Data.password | toString }}", - }, - }, - }, - }, - }, - } -} - func newCheckRepositoryBlueprint() *crv1alpha1.Blueprint { return &crv1alpha1.Blueprint{ Actions: map[string]*crv1alpha1.BlueprintAction{ @@ -267,7 +247,7 @@ func newRestoreDataAllBlueprint() *crv1alpha1.Blueprint { Func: RestoreDataAllFuncName, Args: map[string]interface{}{ RestoreDataAllNamespaceArg: "{{ .StatefulSet.Namespace }}", - RestoreDataAllImageArg: "ghcr.io/kanisterio/kanister-tools:0.96.0", + RestoreDataAllImageArg: "ghcr.io/kanisterio/kanister-tools:0.97.0", RestoreDataAllBackupArtifactPrefixArg: "{{ .Profile.Location.Bucket }}/{{ .Profile.Location.Prefix }}", RestoreDataAllBackupInfo: fmt.Sprintf("{{ .Options.%s }}", BackupDataAllOutput), RestoreDataAllRestorePathArg: "/mnt/data", @@ -478,7 +458,7 @@ func newCopyDataTestBlueprint() crv1alpha1.Blueprint { Func: RestoreDataFuncName, Args: map[string]interface{}{ RestoreDataNamespaceArg: "{{ .PVC.Namespace }}", - RestoreDataImageArg: "ghcr.io/kanisterio/kanister-tools:0.96.0", + RestoreDataImageArg: "ghcr.io/kanisterio/kanister-tools:0.97.0", RestoreDataBackupArtifactPrefixArg: fmt.Sprintf("{{ .Options.%s }}", CopyVolumeDataOutputBackupArtifactLocation), RestoreDataBackupTagArg: fmt.Sprintf("{{ .Options.%s }}", CopyVolumeDataOutputBackupTag), RestoreDataVolsArg: map[string]string{ @@ -590,63 +570,6 @@ func (s *DataSuite) initPVCTemplateParams(c *C, pvc *v1.PersistentVolumeClaim, o tp.Profile = s.profile return tp } -func (s *DataSuite) TestDescribeBackups(c *C) { - tp, _ := s.getTemplateParamsAndPVCName(c, 1) - - // Test backup - bp := *newBackupDataBlueprint() - out := runAction(c, bp, "backup", tp) - c.Assert(out[BackupDataOutputBackupID].(string), Not(Equals), "") - c.Assert(out[BackupDataOutputBackupTag].(string), Not(Equals), "") - c.Assert(out[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) - - // Test DescribeBackups - bp2 := *newDescribeBackupsBlueprint() - out2 := runAction(c, bp2, "describeBackups", tp) - c.Assert(out2[DescribeBackupsFileCount].(string), Not(Equals), "") - c.Assert(out2[DescribeBackupsSize].(string), Not(Equals), "") - c.Assert(out2[DescribeBackupsPasswordIncorrect].(string), Not(Equals), "") - c.Assert(out2[DescribeBackupsRepoDoesNotExist].(string), Not(Equals), "") - c.Assert(out2[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) -} - -func (s *DataSuite) TestDescribeBackupsWrongPassword(c *C) { - tp, _ := s.getTemplateParamsAndPVCName(c, 1) - - // Test backup - bp := *newBackupDataBlueprint() - bp.Actions["backup"].Phases[0].Args[BackupDataBackupArtifactPrefixArg] = fmt.Sprintf("%s/%s", bp.Actions["backup"].Phases[0].Args[BackupDataBackupArtifactPrefixArg], "abcde") - bp.Actions["backup"].Phases[0].Args[BackupDataEncryptionKeyArg] = "foobar" - out := runAction(c, bp, "backup", tp) - c.Assert(out[BackupDataOutputBackupID].(string), Not(Equals), "") - c.Assert(out[BackupDataOutputBackupTag].(string), Not(Equals), "") - c.Assert(out[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) - - // Test DescribeBackups - bp2 := *newDescribeBackupsBlueprint() - bp2.Actions["describeBackups"].Phases[0].Args[DescribeBackupsArtifactPrefixArg] = fmt.Sprintf("%s/%s", bp2.Actions["describeBackups"].Phases[0].Args[DescribeBackupsArtifactPrefixArg], "abcde") - out2 := runAction(c, bp2, "describeBackups", tp) - c.Assert(out2[DescribeBackupsPasswordIncorrect].(string), Equals, "true") - c.Assert(out2[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) -} - -func (s *DataSuite) TestDescribeBackupsRepoNotAvailable(c *C) { - tp, _ := s.getTemplateParamsAndPVCName(c, 1) - - // Test backup - bp := *newBackupDataBlueprint() - out := runAction(c, bp, "backup", tp) - c.Assert(out[BackupDataOutputBackupID].(string), Not(Equals), "") - c.Assert(out[BackupDataOutputBackupTag].(string), Not(Equals), "") - c.Assert(out[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) - - // Test DescribeBackups - bp2 := *newDescribeBackupsBlueprint() - bp2.Actions["describeBackups"].Phases[0].Args[DescribeBackupsArtifactPrefixArg] = fmt.Sprintf("%s/%s", bp2.Actions["describeBackups"].Phases[0].Args[DescribeBackupsArtifactPrefixArg], c.TestName()) - out2 := runAction(c, bp2, "describeBackups", tp) - c.Assert(out2[DescribeBackupsRepoDoesNotExist].(string), Equals, "true") - c.Assert(out2[FunctionOutputVersion].(string), Equals, kanister.DefaultVersion) -} func (s *DataSuite) TestCheckRepository(c *C) { tp, _ := s.getTemplateParamsAndPVCName(c, 1) diff --git a/pkg/function/delete_csi_snapshot.go b/pkg/function/delete_csi_snapshot.go index cbdfb3de56..4fc3e7a141 100644 --- a/pkg/function/delete_csi_snapshot.go +++ b/pkg/function/delete_csi_snapshot.go @@ -16,15 +16,19 @@ package function import ( "context" + "time" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/poll" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -44,13 +48,19 @@ const ( DeleteCSISnapshotNamespaceArg = "namespace" ) -type deleteCSISnapshotFunc struct{} +type deleteCSISnapshotFunc struct { + progressPercent string +} func (*deleteCSISnapshotFunc) Name() string { return DeleteCSISnapshotFuncName } -func (*deleteCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var name, namespace string if err := Arg(args, DeleteCSISnapshotNameArg, &name); err != nil { return nil, err @@ -93,6 +103,14 @@ func (*deleteCSISnapshotFunc) Arguments() []string { } } +func (c *deleteCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteCSISnapshot(ctx context.Context, snapshotter snapshot.Snapshotter, name, namespace string) (*v1.VolumeSnapshot, error) { return snapshotter.Delete(ctx, name, namespace) } diff --git a/pkg/function/delete_csi_snapshot_content.go b/pkg/function/delete_csi_snapshot_content.go index a77a466e50..f28678a7e5 100644 --- a/pkg/function/delete_csi_snapshot_content.go +++ b/pkg/function/delete_csi_snapshot_content.go @@ -16,11 +16,15 @@ package function import ( "context" + "time" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/kube/snapshot" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { @@ -39,13 +43,19 @@ const ( DeleteCSISnapshotContentNameArg = "name" ) -type deleteCSISnapshotContentFunc struct{} +type deleteCSISnapshotContentFunc struct { + progressPercent string +} func (*deleteCSISnapshotContentFunc) Name() string { return DeleteCSISnapshotContentFuncName } -func (*deleteCSISnapshotContentFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteCSISnapshotContentFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var name string if err := Arg(args, DeleteCSISnapshotContentNameArg, &name); err != nil { return nil, err @@ -81,6 +91,14 @@ func (*deleteCSISnapshotContentFunc) Arguments() []string { } } +func (c *deleteCSISnapshotContentFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: c.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteCSISnapshotContent(ctx context.Context, snapshotter snapshot.Snapshotter, name string) error { return snapshotter.DeleteContent(ctx, name) } diff --git a/pkg/function/delete_data.go b/pkg/function/delete_data.go index 4de0951e87..2eb0dded65 100644 --- a/pkg/function/delete_data.go +++ b/pkg/function/delete_data.go @@ -19,9 +19,11 @@ import ( "context" "fmt" "strings" + "time" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -30,6 +32,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -61,7 +64,9 @@ func init() { var _ kanister.Func = (*deleteDataFunc)(nil) -type deleteDataFunc struct{} +type deleteDataFunc struct { + progressPercent string +} func (*deleteDataFunc) Name() string { return DeleteDataFuncName @@ -93,7 +98,7 @@ func deleteData( } pr := kube.NewPodRunner(cli, options) podFunc := deleteDataPodFunc(tp, reclaimSpace, encryptionKey, targetPaths, deleteTags, deleteIdentifiers) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } //nolint:gocognit @@ -196,7 +201,11 @@ func pruneData( return spaceFreed, errors.Wrapf(err, "Failed to prune data after forget") } -func (*deleteDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var namespace, deleteArtifactPrefix, deleteIdentifier, deleteTag, encryptionKey string var reclaimSpace bool var err error @@ -253,3 +262,11 @@ func (*deleteDataFunc) Arguments() []string { DeleteDataReclaimSpace, } } + +func (d *deleteDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_data_all.go b/pkg/function/delete_data_all.go index 2b6fd8e054..1e631e5bd1 100644 --- a/pkg/function/delete_data_all.go +++ b/pkg/function/delete_data_all.go @@ -18,12 +18,16 @@ import ( "context" "encoding/json" "fmt" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -51,13 +55,19 @@ func init() { var _ kanister.Func = (*deleteDataAllFunc)(nil) -type deleteDataAllFunc struct{} +type deleteDataAllFunc struct { + progressPercent string +} func (*deleteDataAllFunc) Name() string { return DeleteDataAllFuncName } -func (*deleteDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var namespace, deleteArtifactPrefix, backupInfo, encryptionKey string var reclaimSpace bool var err error @@ -120,3 +130,11 @@ func (*deleteDataAllFunc) Arguments() []string { DeleteDataAllReclaimSpace, } } + +func (d *deleteDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_data_using_kopia_server.go b/pkg/function/delete_data_using_kopia_server.go index f23c068815..ac1e04bdea 100644 --- a/pkg/function/delete_data_using_kopia_server.go +++ b/pkg/function/delete_data_using_kopia_server.go @@ -17,23 +17,29 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" kankopia "github.com/kanisterio/kanister/pkg/kopia" kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( DeleteDataUsingKopiaServerFuncName = "DeleteDataUsingKopiaServer" ) -type deleteDataUsingKopiaServerFunc struct{} +type deleteDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { err := kanister.Register(&deleteDataUsingKopiaServerFunc{}) @@ -65,7 +71,11 @@ func (*deleteDataUsingKopiaServerFunc) Arguments() []string { } } -func (*deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (d *deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + var ( err error image string @@ -121,6 +131,14 @@ func (*deleteDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templa ) } +func (d *deleteDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func deleteDataFromServer( ctx context.Context, cli kubernetes.Interface, @@ -149,7 +167,7 @@ func deleteDataFromServer( username, userPassphrase, ) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func deleteDataFromServerPodFunc( diff --git a/pkg/function/delete_rds_snapshot.go b/pkg/function/delete_rds_snapshot.go index f1b008337a..2c0f5412d9 100644 --- a/pkg/function/delete_rds_snapshot.go +++ b/pkg/function/delete_rds_snapshot.go @@ -16,16 +16,20 @@ package function import ( "context" + "time" "github.com/aws/aws-sdk-go/aws/awserr" awsrds "github.com/aws/aws-sdk-go/service/rds" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -42,7 +46,9 @@ const ( DeleteRDSSnapshotSnapshotIDArg = "snapshotID" ) -type deleteRDSSnapshotFunc struct{} +type deleteRDSSnapshotFunc struct { + progressPercent string +} func (*deleteRDSSnapshotFunc) Name() string { return DeleteRDSSnapshotFuncName @@ -109,6 +115,10 @@ func deleteRDSSnapshot(ctx context.Context, snapshotID string, profile *param.Pr } func (crs *deleteRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var snapshotID string var dbEngine RDSDBEngine if err := Arg(args, DeleteRDSSnapshotSnapshotIDArg, &snapshotID); err != nil { @@ -132,3 +142,11 @@ func (*deleteRDSSnapshotFunc) Arguments() []string { CreateRDSSnapshotDBEngine, } } + +func (d *deleteRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/delete_volume_snapshot.go b/pkg/function/delete_volume_snapshot.go index 2abc3eecf4..7e1cc4fbc2 100644 --- a/pkg/function/delete_volume_snapshot.go +++ b/pkg/function/delete_volume_snapshot.go @@ -18,11 +18,14 @@ import ( "context" "encoding/json" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" @@ -30,6 +33,7 @@ import ( "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -48,7 +52,9 @@ const ( SnapshotDoesNotExistError = "does not exist" ) -type deleteVolumeSnapshotFunc struct{} +type deleteVolumeSnapshotFunc struct { + progressPercent string +} func (*deleteVolumeSnapshotFunc) Name() string { return DeleteVolumeSnapshotFuncName @@ -93,7 +99,11 @@ func deleteVolumeSnapshot(ctx context.Context, cli kubernetes.Interface, namespa return providerList, nil } -func (kef *deleteVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (d *deleteVolumeSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + d.progressPercent = progress.StartedPercent + defer func() { d.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, errors.Wrapf(err, "Failed to create Kubernetes client") @@ -122,3 +132,11 @@ func (*deleteVolumeSnapshotFunc) Arguments() []string { DeleteVolumeSnapshotManifestArg, } } + +func (d *deleteVolumeSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/describe_backups.go b/pkg/function/describe_backups.go deleted file mode 100644 index fb9f512a13..0000000000 --- a/pkg/function/describe_backups.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2019 The Kanister Authors. -// -// 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. - -package function - -import ( - "bytes" - "context" - "strings" - - "github.com/pkg/errors" - "k8s.io/client-go/kubernetes" - - kanister "github.com/kanisterio/kanister/pkg" - crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" - "github.com/kanisterio/kanister/pkg/consts" - "github.com/kanisterio/kanister/pkg/format" - "github.com/kanisterio/kanister/pkg/kube" - "github.com/kanisterio/kanister/pkg/param" - "github.com/kanisterio/kanister/pkg/restic" -) - -const ( - // DescribeBackupsFuncName gives the function name - DescribeBackupsFuncName = "DescribeBackups" - // DescribeBackupsArtifactPrefixArg provides the path to restore backed up data - DescribeBackupsArtifactPrefixArg = "backupArtifactPrefix" - // DescribeBackupsEncryptionKeyArg provides the encryption key to be used for deletes - DescribeBackupsEncryptionKeyArg = "encryptionKey" - // DescribeBackupsPodOverrideArg contains pod specs to override default pod specs - DescribeBackupsPodOverrideArg = "podOverride" - DescribeBackupsJobPrefix = "describe-backups-" - DescribeBackupsFileCount = "fileCount" - DescribeBackupsSize = "size" - DescribeBackupsPasswordIncorrect = "passwordIncorrect" - DescribeBackupsRepoDoesNotExist = "repoUnavailable" - RawDataStatsMode = "raw-data" -) - -func init() { - _ = kanister.Register(&DescribeBackupsFunc{}) -} - -var _ kanister.Func = (*DescribeBackupsFunc)(nil) - -type DescribeBackupsFunc struct{} - -func (*DescribeBackupsFunc) Name() string { - return DescribeBackupsFuncName -} - -func describeBackups(ctx context.Context, cli kubernetes.Interface, tp param.TemplateParams, encryptionKey, targetPaths, jobPrefix string, podOverride crv1alpha1.JSONMap) (map[string]interface{}, error) { - namespace, err := kube.GetControllerNamespace() - if err != nil { - return nil, errors.Wrapf(err, "Failed to get controller namespace") - } - options := &kube.PodOptions{ - Namespace: namespace, - GenerateName: jobPrefix, - Image: consts.GetKanisterToolsImage(), - Command: []string{"sh", "-c", "tail -f /dev/null"}, - PodOverride: podOverride, - } - pr := kube.NewPodRunner(cli, options) - podFunc := describeBackupsPodFunc(cli, tp, encryptionKey, targetPaths) - return pr.RunEx(ctx, podFunc) -} - -func describeBackupsPodFunc( - cli kubernetes.Interface, - tp param.TemplateParams, - encryptionKey, - targetPath string, -) func(ctx context.Context, pc kube.PodController) (map[string]interface{}, error) { - return func(ctx context.Context, pc kube.PodController) (map[string]interface{}, error) { - pod := pc.Pod() - - // Wait for pod to reach running state - if err := pc.WaitForPodReady(ctx); err != nil { - return nil, errors.Wrapf(err, "Failed while waiting for Pod %s to be ready", pod.Name) - } - - remover, err := MaybeWriteProfileCredentials(ctx, pc, tp.Profile) - if err != nil { - return nil, err - } - - // Parent context could already be dead, so removing file within new context - defer remover.Remove(context.Background()) //nolint:errcheck - - err = restic.CheckIfRepoIsReachable( - tp.Profile, - targetPath, - encryptionKey, - cli, pod.Namespace, - pod.Name, - pod.Spec.Containers[0].Name, - ) - switch { - case err == nil: - break - case strings.Contains(err.Error(), restic.PasswordIncorrect): - return map[string]interface{}{ - DescribeBackupsFileCount: nil, - DescribeBackupsSize: nil, - DescribeBackupsPasswordIncorrect: "true", - DescribeBackupsRepoDoesNotExist: "false", - FunctionOutputVersion: kanister.DefaultVersion, - }, - nil - - case strings.Contains(err.Error(), restic.RepoDoesNotExist): - return map[string]interface{}{ - DescribeBackupsFileCount: nil, - DescribeBackupsSize: nil, - DescribeBackupsPasswordIncorrect: "false", - DescribeBackupsRepoDoesNotExist: "true", - FunctionOutputVersion: kanister.DefaultVersion, - }, - nil - default: - return nil, err - } - - cmd, err := restic.StatsCommandByID(tp.Profile, targetPath, "" /* get all snapshot stats */, RawDataStatsMode, encryptionKey) - if err != nil { - return nil, err - } - - ex, err := pc.GetCommandExecutor() - if err != nil { - return nil, err - } - - var stdout, stderr bytes.Buffer - err = ex.Exec(ctx, cmd, nil, &stdout, &stderr) - format.LogWithCtx(ctx, pod.Name, pod.Spec.Containers[0].Name, stdout.String()) - format.LogWithCtx(ctx, pod.Name, pod.Spec.Containers[0].Name, stderr.String()) - if err != nil { - return nil, errors.Wrapf(err, "Failed to get backup stats") - } - - // Get File Count and Size from Stats - _, fc, size := restic.SnapshotStatsFromStatsLog(stdout.String()) - if fc == "" || size == "" { - return nil, errors.New("Failed to parse snapshot stats from logs") - } - return map[string]interface{}{ - DescribeBackupsFileCount: fc, - DescribeBackupsSize: size, - DescribeBackupsPasswordIncorrect: "false", - DescribeBackupsRepoDoesNotExist: "false", - FunctionOutputVersion: kanister.DefaultVersion, - }, - nil - } -} - -func (*DescribeBackupsFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { - var describeBackupsArtifactPrefix, encryptionKey string - var err error - if err = Arg(args, DescribeBackupsArtifactPrefixArg, &describeBackupsArtifactPrefix); err != nil { - return nil, err - } - if err = OptArg(args, DescribeBackupsEncryptionKeyArg, &encryptionKey, restic.GeneratePassword()); err != nil { - return nil, err - } - podOverride, err := GetPodSpecOverride(tp, args, DescribeBackupsPodOverrideArg) - if err != nil { - return nil, err - } - - if err = ValidateProfile(tp.Profile); err != nil { - return nil, err - } - - describeBackupsArtifactPrefix = ResolveArtifactPrefix(describeBackupsArtifactPrefix, tp.Profile) - - cli, err := kube.NewClient() - if err != nil { - return nil, errors.Wrapf(err, "Failed to create Kubernetes client") - } - return describeBackups(ctx, cli, tp, encryptionKey, describeBackupsArtifactPrefix, DescribeBackupsJobPrefix, podOverride) -} - -func (*DescribeBackupsFunc) RequiredArgs() []string { - return []string{DescribeBackupsArtifactPrefixArg} -} - -func (*DescribeBackupsFunc) Arguments() []string { - return []string{ - DescribeBackupsArtifactPrefixArg, - DescribeBackupsEncryptionKeyArg, - } -} diff --git a/pkg/function/export_rds_snapshot_location.go b/pkg/function/export_rds_snapshot_location.go index fbab481db2..dece0c1ebf 100644 --- a/pkg/function/export_rds_snapshot_location.go +++ b/pkg/function/export_rds_snapshot_location.go @@ -19,8 +19,10 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/yaml" @@ -32,6 +34,7 @@ import ( "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/postgres" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -61,10 +64,12 @@ const ( BackupAction RDSAction = "backup" RestoreAction RDSAction = "restore" - postgresToolsImage = "ghcr.io/kanisterio/postgres-kanister-tools:0.96.0" + postgresToolsImage = "ghcr.io/kanisterio/postgres-kanister-tools:0.97.0" ) -type exportRDSSnapshotToLocationFunc struct{} +type exportRDSSnapshotToLocationFunc struct { + progressPercent string +} // RDSDBEngine for RDS Engine types type RDSDBEngine string @@ -151,6 +156,10 @@ func exportRDSSnapshotToLoc(ctx context.Context, namespace, instanceID, snapshot } func (crs *exportRDSSnapshotToLocationFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + crs.progressPercent = progress.StartedPercent + defer func() { crs.progressPercent = progress.CompletedPercent }() + var namespace, instanceID, snapshotID, username, password, dbSubnetGroup, backupArtifact string var dbEngine RDSDBEngine @@ -217,6 +226,14 @@ func (*exportRDSSnapshotToLocationFunc) Arguments() []string { } } +func (d *exportRDSSnapshotToLocationFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func execDumpCommand(ctx context.Context, dbEngine RDSDBEngine, action RDSAction, namespace, dbEndpoint, username, password string, databases []string, backupPrefix, backupID string, profile *param.Profile, dbEngineVersion string) (map[string]interface{}, error) { // Trim "\n" from creds username = strings.TrimSpace(username) diff --git a/pkg/function/kube_exec.go b/pkg/function/kube_exec.go index 09fd38abc7..ab47058a0b 100644 --- a/pkg/function/kube_exec.go +++ b/pkg/function/kube_exec.go @@ -20,11 +20,15 @@ import ( "io" "os" "regexp" + "time" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/output" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func init() { @@ -44,7 +48,9 @@ const ( KubeExecCommandArg = "command" ) -type kubeExecFunc struct{} +type kubeExecFunc struct { + progressPercent string +} func (*kubeExecFunc) Name() string { return KubeExecFuncName @@ -73,6 +79,10 @@ func parseLogAndCreateOutput(out string) (map[string]interface{}, error) { } func (kef *kubeExecFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + kef.progressPercent = progress.StartedPercent + defer func() { kef.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, err @@ -119,3 +129,11 @@ func (*kubeExecFunc) Arguments() []string { KubeExecContainerNameArg, } } + +func (kef *kubeExecFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: kef.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/kube_exec_all.go b/pkg/function/kube_exec_all.go index 144e2dda79..6e7b52246c 100644 --- a/pkg/function/kube_exec_all.go +++ b/pkg/function/kube_exec_all.go @@ -17,14 +17,18 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -44,13 +48,19 @@ const ( KubeExecAllCommandArg = "command" ) -type kubeExecAllFunc struct{} +type kubeExecAllFunc struct { + progressPercent string +} func (*kubeExecAllFunc) Name() string { return KubeExecAllFuncName } -func (*kubeExecAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (kef *kubeExecAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + kef.progressPercent = progress.StartedPercent + defer func() { kef.progressPercent = progress.CompletedPercent }() + cli, err := kube.NewClient() if err != nil { return nil, err @@ -92,6 +102,14 @@ func (*kubeExecAllFunc) Arguments() []string { } } +func (k *kubeExecAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func execAll(ctx context.Context, cli kubernetes.Interface, namespace string, ps []string, cs []string, cmd []string) (map[string]interface{}, error) { numContainers := len(ps) * len(cs) errChan := make(chan error, numContainers) diff --git a/pkg/function/kube_exec_test.go b/pkg/function/kube_exec_test.go index 158e55334c..d6e10b9ebb 100644 --- a/pkg/function/kube_exec_test.go +++ b/pkg/function/kube_exec_test.go @@ -179,11 +179,11 @@ func (s *KubeExecTest) TestParseLogAndCreateOutput(c *C) { errChecker Checker outChecker Checker }{ - {"###Phase-output###: {\"key\":\"version\",\"value\":\"0.96.0\"}", map[string]interface{}{"version": "0.96.0"}, IsNil, NotNil}, - {"###Phase-output###: {\"key\":\"version\",\"value\":\"0.96.0\"}\n###Phase-output###: {\"key\":\"path\",\"value\":\"/backup/path\"}", - map[string]interface{}{"version": "0.96.0", "path": "/backup/path"}, IsNil, NotNil}, - {"Random message ###Phase-output###: {\"key\":\"version\",\"value\":\"0.96.0\"}", map[string]interface{}{"version": "0.96.0"}, IsNil, NotNil}, - {"Random message with newline \n###Phase-output###: {\"key\":\"version\",\"value\":\"0.96.0\"}", map[string]interface{}{"version": "0.96.0"}, IsNil, NotNil}, + {"###Phase-output###: {\"key\":\"version\",\"value\":\"0.97.0\"}", map[string]interface{}{"version": "0.97.0"}, IsNil, NotNil}, + {"###Phase-output###: {\"key\":\"version\",\"value\":\"0.97.0\"}\n###Phase-output###: {\"key\":\"path\",\"value\":\"/backup/path\"}", + map[string]interface{}{"version": "0.97.0", "path": "/backup/path"}, IsNil, NotNil}, + {"Random message ###Phase-output###: {\"key\":\"version\",\"value\":\"0.97.0\"}", map[string]interface{}{"version": "0.97.0"}, IsNil, NotNil}, + {"Random message with newline \n###Phase-output###: {\"key\":\"version\",\"value\":\"0.97.0\"}", map[string]interface{}{"version": "0.97.0"}, IsNil, NotNil}, {"###Phase-output###: Invalid message", nil, NotNil, IsNil}, {"Random message", nil, IsNil, IsNil}, } { diff --git a/pkg/function/kube_task.go b/pkg/function/kube_task.go index b30dcb512e..fa95fd4025 100644 --- a/pkg/function/kube_task.go +++ b/pkg/function/kube_task.go @@ -16,8 +16,10 @@ package function import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" @@ -27,6 +29,7 @@ import ( "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/output" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -45,7 +48,9 @@ func init() { var _ kanister.Func = (*kubeTaskFunc)(nil) -type kubeTaskFunc struct{} +type kubeTaskFunc struct { + progressPercent string +} func (*kubeTaskFunc) Name() string { return KubeTaskFuncName @@ -62,7 +67,7 @@ func kubeTask(ctx context.Context, cli kubernetes.Interface, namespace, image st pr := kube.NewPodRunner(cli, options) podFunc := kubeTaskPodFunc() - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func kubeTaskPodFunc() func(ctx context.Context, pc kube.PodController) (map[string]interface{}, error) { @@ -89,6 +94,10 @@ func kubeTaskPodFunc() func(ctx context.Context, pc kube.PodController) (map[str } func (ktf *kubeTaskFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + ktf.progressPercent = progress.StartedPercent + defer func() { ktf.progressPercent = progress.CompletedPercent }() + var namespace, image string var command []string var err error @@ -128,3 +137,11 @@ func (*kubeTaskFunc) Arguments() []string { KubeTaskPodOverrideArg, } } + +func (k *kubeTaskFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/kube_task_test.go b/pkg/function/kube_task_test.go index 413d6e96a0..79cbfc0676 100644 --- a/pkg/function/kube_task_test.go +++ b/pkg/function/kube_task_test.go @@ -71,7 +71,7 @@ func outputPhase(namespace string) crv1alpha1.BlueprintPhase { KubeTaskCommandArg: []string{ "sh", "-c", - "kando output version 0.96.0", + "kando output version 0.97.0", }, }, } @@ -144,7 +144,7 @@ func (s *KubeTaskSuite) TestKubeTask(c *C) { bp: newTaskBlueprint(outputPhase(s.namespace), sleepPhase(s.namespace), tickPhase(s.namespace)), outs: []map[string]interface{}{ { - "version": "0.96.0", + "version": "0.97.0", }, {}, {}, diff --git a/pkg/function/kubeops.go b/pkg/function/kubeops.go index 5fd901ae79..39cfa6c57a 100644 --- a/pkg/function/kubeops.go +++ b/pkg/function/kubeops.go @@ -19,6 +19,7 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,6 +29,7 @@ import ( crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -51,13 +53,19 @@ const ( KubeOpsOperationArg = "operation" ) -type kubeops struct{} +type kubeops struct { + progressPercent string +} func (*kubeops) Name() string { return KubeOpsFuncName } -func (crs *kubeops) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (k *kubeops) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + k.progressPercent = progress.StartedPercent + defer func() { k.progressPercent = progress.CompletedPercent }() + var spec, namespace string var op kube.Operation var objRefArg crv1alpha1.ObjectReference @@ -128,3 +136,11 @@ func (*kubeops) Arguments() []string { KubeOpsObjectReferenceArg, } } + +func (k *kubeops) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: k.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/location_delete.go b/pkg/function/location_delete.go index 1977b7fa04..0a3cdc079c 100644 --- a/pkg/function/location_delete.go +++ b/pkg/function/location_delete.go @@ -17,12 +17,16 @@ package function import ( "context" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/location" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -38,13 +42,19 @@ func init() { var _ kanister.Func = (*locationDeleteFunc)(nil) -type locationDeleteFunc struct{} +type locationDeleteFunc struct { + progressPercent string +} func (*locationDeleteFunc) Name() string { return LocationDeleteFuncName } -func (*locationDeleteFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (l *locationDeleteFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + l.progressPercent = progress.StartedPercent + defer func() { l.progressPercent = progress.CompletedPercent }() + var artifact string var err error if err = Arg(args, LocationDeleteArtifactArg, &artifact); err != nil { @@ -63,3 +73,11 @@ func (*locationDeleteFunc) RequiredArgs() []string { func (*locationDeleteFunc) Arguments() []string { return []string{LocationDeleteArtifactArg} } + +func (l *locationDeleteFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: l.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/prepare_data.go b/pkg/function/prepare_data.go index 37c5544b20..240e68de91 100644 --- a/pkg/function/prepare_data.go +++ b/pkg/function/prepare_data.go @@ -18,6 +18,7 @@ import ( "context" "fmt" "io" + "time" "github.com/kanisterio/kanister/pkg/consts" "github.com/kanisterio/kanister/pkg/field" @@ -30,6 +31,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -51,7 +53,9 @@ func init() { var _ kanister.Func = (*prepareDataFunc)(nil) -type prepareDataFunc struct{} +type prepareDataFunc struct { + progressPercent string +} func (*prepareDataFunc) Name() string { return PrepareDataFuncName @@ -81,23 +85,31 @@ func getVolumes(tp param.TemplateParams) (map[string]string, error) { func prepareData(ctx context.Context, cli kubernetes.Interface, namespace, serviceAccount, image string, vols map[string]string, podOverride crv1alpha1.JSONMap, command ...string) (map[string]interface{}, error) { // Validate volumes - for pvc := range vols { - if _, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvc, metav1.GetOptions{}); err != nil { - return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvc) + validatedVols := make(map[string]kube.VolumeMountOptions) + for pvcName, mountPoint := range vols { + pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvcName) + } + + validatedVols[pvcName] = kube.VolumeMountOptions{ + MountPath: mountPoint, + ReadOnly: kube.PVCContainsReadOnlyAccessMode(pvc), } } + options := &kube.PodOptions{ Namespace: namespace, GenerateName: prepareDataJobPrefix, Image: image, Command: command, - Volumes: vols, + Volumes: validatedVols, ServiceAccountName: serviceAccount, PodOverride: podOverride, } pr := kube.NewPodRunner(cli, options) podFunc := prepareDataPodFunc(cli) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func prepareDataPodFunc(cli kubernetes.Interface) func(ctx context.Context, pc kube.PodController) (map[string]interface{}, error) { @@ -129,7 +141,11 @@ func prepareDataPodFunc(cli kubernetes.Interface) func(ctx context.Context, pc k } } -func (*prepareDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (p *prepareDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + p.progressPercent = progress.StartedPercent + defer func() { p.progressPercent = progress.CompletedPercent }() + var namespace, image, serviceAccount string var command []string var vols map[string]string @@ -184,3 +200,11 @@ func (*prepareDataFunc) Arguments() []string { PrepareDataPodOverrideArg, } } + +func (p *prepareDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: p.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_csi_snapshot.go b/pkg/function/restore_csi_snapshot.go index 6196944a5d..c3a140f97a 100644 --- a/pkg/function/restore_csi_snapshot.go +++ b/pkg/function/restore_csi_snapshot.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "time" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -25,8 +26,10 @@ import ( "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -60,7 +63,9 @@ const ( RestoreCSISnapshotVolumeModeArg = "volumeMode" ) -type restoreCSISnapshotFunc struct{} +type restoreCSISnapshotFunc struct { + progressPercent string +} type restoreCSISnapshotArgs struct { Name string @@ -77,7 +82,11 @@ func (*restoreCSISnapshotFunc) Name() string { return RestoreCSISnapshotFuncName } -func (*restoreCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreCSISnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var restoreSize string var restoreArgs restoreCSISnapshotArgs if err := Arg(args, RestoreCSISnapshotNameArg, &restoreArgs.Name); err != nil { @@ -152,6 +161,14 @@ func (*restoreCSISnapshotFunc) Arguments() []string { } } +func (d *restoreCSISnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func getClient() (kubernetes.Interface, error) { kubeCli, err := kube.NewClient() return kubeCli, err diff --git a/pkg/function/restore_data.go b/pkg/function/restore_data.go index ad54550c1f..0c8a8e9318 100644 --- a/pkg/function/restore_data.go +++ b/pkg/function/restore_data.go @@ -17,6 +17,7 @@ package function import ( "bytes" "context" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,6 +28,7 @@ import ( "github.com/kanisterio/kanister/pkg/format" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -62,7 +64,9 @@ func init() { var _ kanister.Func = (*restoreDataFunc)(nil) -type restoreDataFunc struct{} +type restoreDataFunc struct { + progressPercent string +} func (*restoreDataFunc) Name() string { return RestoreDataFuncName @@ -111,22 +115,30 @@ func validateAndGetOptArgs(args map[string]interface{}, tp param.TemplateParams) func restoreData(ctx context.Context, cli kubernetes.Interface, tp param.TemplateParams, namespace, encryptionKey, backupArtifactPrefix, restorePath, backupTag, backupID, jobPrefix, image string, vols map[string]string, podOverride crv1alpha1.JSONMap) (map[string]interface{}, error) { // Validate volumes - for pvc := range vols { - if _, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvc, metav1.GetOptions{}); err != nil { - return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvc) + validatedVols := make(map[string]kube.VolumeMountOptions) + for pvcName, mountPoint := range vols { + pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvcName) + } + + validatedVols[pvcName] = kube.VolumeMountOptions{ + MountPath: mountPoint, + ReadOnly: kube.PVCContainsReadOnlyAccessMode(pvc), } } + options := &kube.PodOptions{ Namespace: namespace, GenerateName: jobPrefix, Image: image, Command: []string{"sh", "-c", "tail -f /dev/null"}, - Volumes: vols, + Volumes: validatedVols, PodOverride: podOverride, } pr := kube.NewPodRunner(cli, options) podFunc := restoreDataPodFunc(tp, encryptionKey, backupArtifactPrefix, restorePath, backupTag, backupID) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func restoreDataPodFunc( @@ -180,7 +192,11 @@ func restoreDataPodFunc( } } -func (*restoreDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, image, backupArtifactPrefix, backupTag, backupID string var podOverride crv1alpha1.JSONMap var err error @@ -254,3 +270,11 @@ func (*restoreDataFunc) Arguments() []string { RestoreDataPodOverrideArg, } } + +func (d *restoreDataFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: d.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_data_all.go b/pkg/function/restore_data_all.go index dd6fb967a9..31a2c626f1 100644 --- a/pkg/function/restore_data_all.go +++ b/pkg/function/restore_data_all.go @@ -19,13 +19,16 @@ import ( "encoding/json" "fmt" "strings" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" "github.com/kanisterio/kanister/pkg/restic" ) @@ -57,7 +60,9 @@ func init() { var _ kanister.Func = (*restoreDataAllFunc)(nil) -type restoreDataAllFunc struct{} +type restoreDataAllFunc struct { + progressPercent string +} func (*restoreDataAllFunc) Name() string { return RestoreDataAllFuncName @@ -99,7 +104,11 @@ func validateAndGetRestoreAllOptArgs(args map[string]interface{}, tp param.Templ return restorePath, encryptionKey, ps, podOverride, nil } -func (*restoreDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreDataAllFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, image, backupArtifactPrefix, backupInfo string var err error if err = Arg(args, RestoreDataAllNamespaceArg, &namespace); err != nil { @@ -190,3 +199,11 @@ func (*restoreDataAllFunc) Arguments() []string { RestoreDataAllPodOverrideArg, } } + +func (r *restoreDataAllFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} diff --git a/pkg/function/restore_data_using_kopia_server.go b/pkg/function/restore_data_using_kopia_server.go index 0d327fd5a0..1b44609218 100644 --- a/pkg/function/restore_data_using_kopia_server.go +++ b/pkg/function/restore_data_using_kopia_server.go @@ -18,6 +18,7 @@ import ( "bytes" "context" "fmt" + "time" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,6 +31,7 @@ import ( kopiacmd "github.com/kanisterio/kanister/pkg/kopia/command" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -38,7 +40,9 @@ const ( SparseRestoreOption = "sparseRestore" ) -type restoreDataUsingKopiaServerFunc struct{} +type restoreDataUsingKopiaServerFunc struct { + progressPercent string +} func init() { _ = kanister.Register(&restoreDataUsingKopiaServerFunc{}) @@ -72,7 +76,11 @@ func (*restoreDataUsingKopiaServerFunc) Arguments() []string { } } -func (*restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { +func (r *restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]any) (map[string]any, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var ( err error image string @@ -151,6 +159,14 @@ func (*restoreDataUsingKopiaServerFunc) Exec(ctx context.Context, tp param.Templ ) } +func (r *restoreDataUsingKopiaServerFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func restoreDataFromServer( ctx context.Context, cli kubernetes.Interface, @@ -168,9 +184,17 @@ func restoreDataFromServer( vols map[string]string, podOverride crv1alpha1.JSONMap, ) (map[string]any, error) { - for pvc := range vols { - if _, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvc, metav1.GetOptions{}); err != nil { - return nil, errors.Wrap(err, "Failed to retrieve PVC from namespace: "+namespace+" name: "+pvc) + validatedVols := make(map[string]kube.VolumeMountOptions) + // Validate volumes + for pvcName, mountPoint := range vols { + pvc, err := cli.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrapf(err, "Failed to retrieve PVC. Namespace %s, Name %s", namespace, pvcName) + } + + validatedVols[pvcName] = kube.VolumeMountOptions{ + MountPath: mountPoint, + ReadOnly: kube.PVCContainsReadOnlyAccessMode(pvc), } } @@ -179,7 +203,7 @@ func restoreDataFromServer( GenerateName: jobPrefix, Image: image, Command: []string{"bash", "-c", "tail -f /dev/null"}, - Volumes: vols, + Volumes: validatedVols, PodOverride: podOverride, } @@ -194,7 +218,7 @@ func restoreDataFromServer( userPassphrase, sparseRestore, ) - return pr.RunEx(ctx, podFunc) + return pr.Run(ctx, podFunc) } func restoreDataFromServerPodFunc( diff --git a/pkg/function/restore_rds_snapshot.go b/pkg/function/restore_rds_snapshot.go index 6d0afb6fb8..bec1e357eb 100644 --- a/pkg/function/restore_rds_snapshot.go +++ b/pkg/function/restore_rds_snapshot.go @@ -17,19 +17,23 @@ package function import ( "context" "fmt" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" rdserr "github.com/aws/aws-sdk-go/service/rds" "github.com/hashicorp/go-version" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/aws/rds" "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/postgres" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -74,7 +78,9 @@ const ( RDSPostgresDBInstanceEngineVersion = "13.0" ) -type restoreRDSSnapshotFunc struct{} +type restoreRDSSnapshotFunc struct { + progressPercent string +} func (*restoreRDSSnapshotFunc) Name() string { return RestoreRDSSnapshotFuncName @@ -99,7 +105,11 @@ func (*restoreRDSSnapshotFunc) Arguments() []string { } } -func (*restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (r *restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + r.progressPercent = progress.StartedPercent + defer func() { r.progressPercent = progress.CompletedPercent }() + var namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password string var dbEngine RDSDBEngine @@ -146,6 +156,14 @@ func (*restoreRDSSnapshotFunc) Exec(ctx context.Context, tp param.TemplateParams return restoreRDSSnapshot(ctx, namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password, dbEngine, sgIDs, tp.Profile) } +func (r *restoreRDSSnapshotFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: r.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func restoreRDSSnapshot(ctx context.Context, namespace, instanceID, subnetGroup, snapshotID, backupArtifactPrefix, backupID, username, password string, dbEngine RDSDBEngine, sgIDs []string, profile *param.Profile) (map[string]interface{}, error) { // Validate profile if err := ValidateProfile(profile); err != nil { diff --git a/pkg/function/scale_workload.go b/pkg/function/scale_workload.go index 673a4fe4e8..9d6de8ec0e 100644 --- a/pkg/function/scale_workload.go +++ b/pkg/function/scale_workload.go @@ -18,14 +18,18 @@ import ( "context" "strconv" "strings" + "time" osversioned "github.com/openshift/client-go/apps/clientset/versioned" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -46,13 +50,19 @@ var ( _ kanister.Func = (*scaleWorkloadFunc)(nil) ) -type scaleWorkloadFunc struct{} +type scaleWorkloadFunc struct { + progressPercent string +} func (*scaleWorkloadFunc) Name() string { return ScaleWorkloadFuncName } -func (*scaleWorkloadFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (s *scaleWorkloadFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + s.progressPercent = progress.StartedPercent + defer func() { s.progressPercent = progress.CompletedPercent }() + var namespace, kind, name string var replicas int32 namespace, kind, name, replicas, waitForReady, err := getArgs(tp, args) @@ -97,6 +107,14 @@ func (*scaleWorkloadFunc) Arguments() []string { } } +func (s *scaleWorkloadFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: s.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func getArgs(tp param.TemplateParams, args map[string]interface{}) (namespace, kind, name string, replicas int32, waitForReady bool, err error) { var rep interface{} waitForReady = true diff --git a/pkg/function/wait.go b/pkg/function/wait.go index e5e3e9d3d7..3d291db7dd 100644 --- a/pkg/function/wait.go +++ b/pkg/function/wait.go @@ -37,6 +37,7 @@ import ( "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/param" "github.com/kanisterio/kanister/pkg/poll" + "github.com/kanisterio/kanister/pkg/progress" ) type WaitConditions struct { @@ -62,13 +63,19 @@ func init() { var _ kanister.Func = (*waitFunc)(nil) -type waitFunc struct{} +type waitFunc struct { + progressPercent string +} func (*waitFunc) Name() string { return WaitFuncName } -func (ktf *waitFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + rendered, err := param.RenderArgs(args, tp) if err != nil { return nil, err @@ -112,6 +119,14 @@ func (*waitFunc) Arguments() []string { } } +func (w *waitFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + // waitForCondition wait till the condition satisfies within the timeout duration func waitForCondition( ctx context.Context, diff --git a/pkg/function/wait_for_snapshot_completion.go b/pkg/function/wait_for_snapshot_completion.go index 3195eb5074..c2ade04880 100644 --- a/pkg/function/wait_for_snapshot_completion.go +++ b/pkg/function/wait_for_snapshot_completion.go @@ -17,14 +17,18 @@ package function import ( "context" "encoding/json" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" awsconfig "github.com/kanisterio/kanister/pkg/aws" "github.com/kanisterio/kanister/pkg/blockstorage" "github.com/kanisterio/kanister/pkg/blockstorage/getter" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) func init() { @@ -41,7 +45,9 @@ const ( WaitForSnapshotCompletionSnapshotsArg = "snapshots" ) -type waitForSnapshotCompletionFunc struct{} +type waitForSnapshotCompletionFunc struct { + progressPercent string +} func (*waitForSnapshotCompletionFunc) Name() string { return WaitForSnapshotCompletionFuncName @@ -55,7 +61,11 @@ func (*waitForSnapshotCompletionFunc) Arguments() []string { return []string{WaitForSnapshotCompletionSnapshotsArg} } -func (kef *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + var snapshotinfo string if err := Arg(args, WaitForSnapshotCompletionSnapshotsArg, &snapshotinfo); err != nil { return nil, err @@ -63,6 +73,14 @@ func (kef *waitForSnapshotCompletionFunc) Exec(ctx context.Context, tp param.Tem return nil, waitForSnapshotsCompletion(ctx, snapshotinfo, tp.Profile, getter.New()) } +func (w *waitForSnapshotCompletionFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + func waitForSnapshotsCompletion(ctx context.Context, snapshotinfo string, profile *param.Profile, getter getter.Getter) error { PVCData := []VolumeSnapshotInfo{} err := json.Unmarshal([]byte(snapshotinfo), &PVCData) diff --git a/pkg/function/waitv2.go b/pkg/function/waitv2.go index 88ddef5254..7912ae2a62 100644 --- a/pkg/function/waitv2.go +++ b/pkg/function/waitv2.go @@ -21,13 +21,16 @@ import ( "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/cli-runtime/pkg/printers" "k8s.io/client-go/dynamic" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/kube" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -43,13 +46,19 @@ func init() { var _ kanister.Func = (*waitV2Func)(nil) -type waitV2Func struct{} +type waitV2Func struct { + progressPercent string +} func (*waitV2Func) Name() string { return WaitV2FuncName } -func (ktf *waitV2Func) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { +func (w *waitV2Func) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + // Set progress percent + w.progressPercent = progress.StartedPercent + defer func() { w.progressPercent = progress.CompletedPercent }() + var timeout string if err := Arg(args, WaitV2TimeoutArg, &timeout); err != nil { return nil, err @@ -88,6 +97,14 @@ func (*waitV2Func) Arguments() []string { } } +func (w *waitV2Func) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: w.progressPercent, + LastTransitionTime: &metav1Time, + }, nil +} + // evaluateWaitV2Condition evaluate the go template condition func evaluateWaitV2Condition(ctx context.Context, dynCli dynamic.Interface, cond Condition, tp param.TemplateParams) (bool, error) { objRef, err := resolveWaitConditionObjRefs(cond, tp) diff --git a/pkg/kando/chronicle_pull.go b/pkg/kando/chronicle_pull.go index 5f4338fae3..941ee4b335 100644 --- a/pkg/kando/chronicle_pull.go +++ b/pkg/kando/chronicle_pull.go @@ -17,11 +17,14 @@ package kando import ( "context" "encoding/json" + "io" + "os" - "github.com/kanisterio/kanister/pkg/chronicle" - "github.com/kanisterio/kanister/pkg/param" "github.com/pkg/errors" "github.com/spf13/cobra" + + "github.com/kanisterio/kanister/pkg/chronicle" + "github.com/kanisterio/kanister/pkg/param" ) func newChroniclePullCommand() *cobra.Command { @@ -64,3 +67,12 @@ func runChroniclePull(cmd *cobra.Command, p locationParams, arg string) error { ctx := context.Background() return chronicle.Pull(ctx, target, *prof, p.suffix) } + +const usePipeParam = `-` + +func targetWriter(target string) (io.Writer, error) { + if target != usePipeParam { + return os.OpenFile(target, os.O_RDWR|os.O_CREATE, 0755) + } + return os.Stdout, nil +} diff --git a/pkg/kando/kando_test.go b/pkg/kando/kando_test.go deleted file mode 100644 index 5d0ccb6092..0000000000 --- a/pkg/kando/kando_test.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 The Kanister Authors. -// -// 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. - -package kando - -import ( - "testing" - - . "gopkg.in/check.v1" -) - -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { TestingT(t) } diff --git a/pkg/kando/location_delete.go b/pkg/kando/location_delete.go index cbd1f40410..e93d793029 100644 --- a/pkg/kando/location_delete.go +++ b/pkg/kando/location_delete.go @@ -15,12 +15,7 @@ package kando import ( - "context" - "github.com/spf13/cobra" - - "github.com/kanisterio/kanister/pkg/location" - "github.com/kanisterio/kanister/pkg/param" ) func newLocationDeleteCommand() *cobra.Command { @@ -42,7 +37,3 @@ func newLocationDeleteCommand() *cobra.Command { cmd.Flags().StringP(kopiaSnapshotFlagName, "k", "", "Pass the kopia snapshot information from the location push command (optional)") return cmd } - -func locationDelete(ctx context.Context, p *param.Profile, path string) error { - return location.Delete(ctx, *p, path) -} diff --git a/pkg/kando/location_pull.go b/pkg/kando/location_pull.go index 95c485a4cd..ef3172c881 100644 --- a/pkg/kando/location_pull.go +++ b/pkg/kando/location_pull.go @@ -15,14 +15,7 @@ package kando import ( - "context" - "io" - "os" - "github.com/spf13/cobra" - - "github.com/kanisterio/kanister/pkg/location" - "github.com/kanisterio/kanister/pkg/param" ) const ( @@ -49,14 +42,3 @@ func newLocationPullCommand() *cobra.Command { cmd.Flags().StringP(kopiaSnapshotFlagName, "k", "", "Pass the kopia snapshot information from the location push command (optional)") return cmd } - -func targetWriter(target string) (io.Writer, error) { - if target != usePipeParam { - return os.OpenFile(target, os.O_RDWR|os.O_CREATE, 0755) - } - return os.Stdout, nil -} - -func locationPull(ctx context.Context, p *param.Profile, path string, target io.Writer) error { - return location.Read(ctx, target, *p, path) -} diff --git a/pkg/kando/location_push.go b/pkg/kando/location_push.go index cbc3842c81..c69ce04e87 100644 --- a/pkg/kando/location_push.go +++ b/pkg/kando/location_push.go @@ -15,13 +15,7 @@ package kando import ( - "context" - "io" - "github.com/spf13/cobra" - - "github.com/kanisterio/kanister/pkg/location" - "github.com/kanisterio/kanister/pkg/param" ) const ( @@ -50,9 +44,3 @@ func newLocationPushCommand() *cobra.Command { return cmd } - -const usePipeParam = `-` - -func locationPush(ctx context.Context, p *param.Profile, path string, source io.Reader) error { - return location.Write(ctx, source, *p, path) -} diff --git a/pkg/kando/location_test.go b/pkg/kando/location_test.go deleted file mode 100644 index a0b7585aaa..0000000000 --- a/pkg/kando/location_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019 The Kanister Authors. -// -// 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. - -package kando - -import ( - "bytes" - "context" - "path/filepath" - - . "gopkg.in/check.v1" - - crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" - "github.com/kanisterio/kanister/pkg/objectstore" - "github.com/kanisterio/kanister/pkg/testutil" -) - -type LocationSuite struct{} - -var _ = Suite(&LocationSuite{}) - -const testContent = "test-content" - -func (s *LocationSuite) TestLocationObjectStore(c *C) { - location := crv1alpha1.Location{ - Type: crv1alpha1.LocationTypeS3Compliant, - Bucket: testutil.TestS3BucketName, - } - p := testutil.ObjectStoreProfileOrSkip(c, objectstore.ProviderTypeS3, location) - ctx := context.Background() - dir := c.MkDir() - path := filepath.Join(dir, "test-object1.txt") - - source := bytes.NewBufferString(testContent) - err := locationPush(ctx, p, path, source) - c.Assert(err, IsNil) - - target := bytes.NewBuffer(nil) - err = locationPull(ctx, p, path, target) - c.Assert(err, IsNil) - c.Assert(target.String(), Equals, testContent) - - // test deleting single artifact - err = locationDelete(ctx, p, path) - c.Assert(err, IsNil) - - //test deleting dir with multiple artifacts - source = bytes.NewBufferString(testContent) - err = locationPush(ctx, p, path, source) - c.Assert(err, IsNil) - - path = filepath.Join(dir, "test-object2.txt") - - source = bytes.NewBufferString(testContent) - err = locationPush(ctx, p, path, source) - c.Assert(err, IsNil) - - err = locationDelete(ctx, p, dir) - c.Assert(err, IsNil) -} diff --git a/pkg/kanister.go b/pkg/kanister.go index 793814528c..4d2ffb2f8a 100644 --- a/pkg/kanister.go +++ b/pkg/kanister.go @@ -21,6 +21,7 @@ import ( "github.com/Masterminds/semver" "github.com/pkg/errors" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" ) @@ -39,6 +40,7 @@ type Func interface { RequiredArgs() []string Arguments() []string Exec(context.Context, param.TemplateParams, map[string]interface{}) (map[string]interface{}, error) + ExecutionProgress() (crv1alpha1.PhaseProgress, error) } // Register allows Funcs to be referenced by User Defined YAMLs diff --git a/pkg/kube/job.go b/pkg/kube/job.go index bd46702190..e5d3214c0c 100644 --- a/pkg/kube/job.go +++ b/pkg/kube/job.go @@ -40,12 +40,19 @@ type Job struct { name string sa string // vols is a map of PVC->Mount points to add to the job pod spec - vols map[string]string + vols map[string]VolumeMountOptions clientset kubernetes.Interface } // NewJob creates a new Job object. -func NewJob(clientset kubernetes.Interface, jobName string, namespace string, serviceAccount string, image string, vols map[string]string, command ...string) (*Job, error) { +func NewJob(clientset kubernetes.Interface, + jobName string, + namespace string, + serviceAccount string, + image string, + vols map[string]VolumeMountOptions, + command ...string, +) (*Job, error) { if jobName == "" { return nil, errors.New("Job name is required") } @@ -73,7 +80,8 @@ func NewJob(clientset kubernetes.Interface, jobName string, namespace string, se // Create creates the Job in Kubernetes. func (job *Job) Create() error { falseVal := false - volumeMounts, podVolumes, err := createFilesystemModeVolumeSpecs(job.vols) + ctx := context.TODO() + volumeMounts, podVolumes, err := createFilesystemModeVolumeSpecs(ctx, job.vols) if err != nil { return errors.Wrapf(err, "Failed to create volume spec for job %s", job.name) } @@ -115,7 +123,7 @@ func (job *Job) Create() error { batchClient := job.clientset.BatchV1() jobsClient := batchClient.Jobs(job.namespace) - newJob, err := jobsClient.Create(context.TODO(), k8sJob, metav1.CreateOptions{}) + newJob, err := jobsClient.Create(ctx, k8sJob, metav1.CreateOptions{}) if err != nil { return errors.Wrapf(err, "Failed to create job %s", job.name) } @@ -125,21 +133,30 @@ func (job *Job) Create() error { return nil } -func createFilesystemModeVolumeSpecs(vols map[string]string) (volumeMounts []v1.VolumeMount, podVolumes []v1.Volume, error error) { +func createFilesystemModeVolumeSpecs( + ctx context.Context, + vols map[string]VolumeMountOptions, +) (volumeMounts []v1.VolumeMount, podVolumes []v1.Volume, error error) { // Build filesystem mode volume specs - for pvc, mountPath := range vols { + for pvcName, mountOpts := range vols { id, err := uuid.NewV1() if err != nil { return nil, nil, err } + + if mountOpts.ReadOnly { + log.Debug().WithContext(ctx).Print("PVC will be mounted in read-only mode", field.M{"pvcName": pvcName}) + } + podVolName := fmt.Sprintf("vol-%s", id.String()) - volumeMounts = append(volumeMounts, v1.VolumeMount{Name: podVolName, MountPath: mountPath}) + volumeMounts = append(volumeMounts, v1.VolumeMount{Name: podVolName, MountPath: mountOpts.MountPath, ReadOnly: mountOpts.ReadOnly}) podVolumes = append(podVolumes, v1.Volume{ Name: podVolName, VolumeSource: v1.VolumeSource{ PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc, + ClaimName: pvcName, + ReadOnly: mountOpts.ReadOnly, }, }, }, diff --git a/pkg/kube/job_test.go b/pkg/kube/job_test.go index acf10cf9fa..a9cf5dbbef 100644 --- a/pkg/kube/job_test.go +++ b/pkg/kube/job_test.go @@ -36,7 +36,9 @@ type JobSuite struct{} var _ = Suite(&JobSuite{}) -var testJobName = "kanister-test-job" +// Name of test job for this suite. +// Initially it contains incorrect name of job for catching errors. +var testJobName = "" const testJobNamespace = "default" const testJobImage = "busybox" @@ -47,7 +49,7 @@ func (s *JobSuite) SetUpSuite(c *C) { } func (s *JobSuite) SetUpTest(c *C) { - testJobName = testJobName + rand.String(5) + testJobName = "kanister-test-job" + rand.String(5) } // Verifies that the Job object is not created if the job name is not specified. @@ -234,7 +236,27 @@ func (s *JobSuite) TestJobsWaitOnNonExistentJob(c *C) { func (s *JobSuite) TestJobsVolumes(c *C) { cli := fake.NewSimpleClientset() - vols := map[string]string{"pvc-test": "/mnt/data1"} + vols := map[string]VolumeMountOptions{"pvc-test": {MountPath: "/mnt/data1", ReadOnly: false}} + job, err := NewJob(cli, testJobName, testJobNamespace, testJobServiceAccount, testJobImage, vols, "sleep", "300") + c.Assert(err, IsNil) + c.Assert(job.Create(), IsNil) + + a := cli.Actions() + c.Assert(a, HasLen, 1) + createAction := a[0] + createdJob, ok := createAction.(k8stesting.CreateAction).GetObject().(*batch.Job) + c.Assert(ok, Equals, true) + + c.Assert(createdJob.Name, Equals, testJobName) + podSpec := createdJob.Spec.Template.Spec + c.Assert(podSpec.Volumes, HasLen, 1) + c.Assert(podSpec.Volumes[0].VolumeSource.PersistentVolumeClaim.ClaimName, Equals, "pvc-test") + c.Assert(podSpec.Containers[0].VolumeMounts[0].MountPath, Equals, "/mnt/data1") +} + +func (s *JobSuite) TestJobsReadOnlyVolumes(c *C) { + cli := fake.NewSimpleClientset() + vols := map[string]VolumeMountOptions{"pvc-test": {MountPath: "/mnt/data1", ReadOnly: true}} job, err := NewJob(cli, testJobName, testJobNamespace, testJobServiceAccount, testJobImage, vols, "sleep", "300") c.Assert(err, IsNil) c.Assert(job.Create(), IsNil) diff --git a/pkg/kube/pod.go b/pkg/kube/pod.go index 641b42ea71..67482ba86e 100644 --- a/pkg/kube/pod.go +++ b/pkg/kube/pod.go @@ -48,6 +48,11 @@ const ( defaultContainerName = "container" ) +type VolumeMountOptions struct { + MountPath string + ReadOnly bool +} + // PodOptions specifies options for `CreatePod` type PodOptions struct { Annotations map[string]string @@ -59,7 +64,7 @@ type PodOptions struct { Labels map[string]string Namespace string ServiceAccountName string - Volumes map[string]string + Volumes map[string]VolumeMountOptions BlockVolumes map[string]string // PodSecurityContext and ContainerSecurityContext can be used to set the security context // at the pod level and container level respectively. @@ -76,7 +81,7 @@ type PodOptions struct { Lifecycle *v1.Lifecycle } -func GetPodObjectFromPodOptions(cli kubernetes.Interface, opts *PodOptions) (*v1.Pod, error) { +func GetPodObjectFromPodOptions(ctx context.Context, cli kubernetes.Interface, opts *PodOptions) (*v1.Pod, error) { // If Namespace is not specified, use the controller Namespace. cns, err := GetControllerNamespace() if err != nil { @@ -101,7 +106,7 @@ func GetPodObjectFromPodOptions(cli kubernetes.Interface, opts *PodOptions) (*v1 opts.RestartPolicy = v1.RestartPolicyNever } - volumeMounts, podVolumes, err := createFilesystemModeVolumeSpecs(opts.Volumes) + volumeMounts, podVolumes, err := createFilesystemModeVolumeSpecs(ctx, opts.Volumes) if err != nil { return nil, errors.Wrapf(err, "Failed to create volume spec") } @@ -207,11 +212,13 @@ func ContainerNameFromPodOptsOrDefault(po *PodOptions) string { // CreatePod creates a pod with a single container based on the specified image func CreatePod(ctx context.Context, cli kubernetes.Interface, opts *PodOptions) (*v1.Pod, error) { - pod, err := GetPodObjectFromPodOptions(cli, opts) + pod, err := GetPodObjectFromPodOptions(ctx, cli, opts) if err != nil { return nil, errors.Wrapf(err, "Failed to get pod from podOptions. Namespace: %s, NameFmt: %s", opts.Namespace, opts.GenerateName) } + log.Debug().WithContext(ctx).Print("Creating POD", field.M{"name": pod.Name, "namespace": pod.Namespace}) + pod, err = cli.CoreV1().Pods(pod.Namespace).Create(ctx, pod, metav1.CreateOptions{}) if err != nil { return nil, errors.Wrapf(err, "Failed to create pod. Namespace: %s, NameFmt: %s", opts.Namespace, opts.GenerateName) diff --git a/pkg/kube/pod_runner.go b/pkg/kube/pod_runner.go index 64b864b0f7..2d0c2268dd 100644 --- a/pkg/kube/pod_runner.go +++ b/pkg/kube/pod_runner.go @@ -18,7 +18,6 @@ import ( "context" "github.com/pkg/errors" - v1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" "github.com/kanisterio/kanister/pkg/consts" @@ -28,16 +27,12 @@ import ( // PodRunner allows us to start / stop pod, write file to pod and execute command within it type PodRunner interface { - Run(ctx context.Context, fn func(context.Context, *v1.Pod) (map[string]interface{}, error)) (map[string]interface{}, error) - // RunEx utilizes the PodController interface and forwards it to the functor, simplifying the manipulation with - // particular pod from the functor. - // TODO: Since significant number of functions are currently using PodRunner, we'll keep Run for now. - // However, once all these functions have been refactored to use PodController, - // Run should be removed and RunEx has to be renamed to Run. - RunEx(ctx context.Context, fn func(context.Context, PodController) (map[string]interface{}, error)) (map[string]interface{}, error) + // Run creates pod using the PodController interface and forwards it to the functor. + // Pod will be deleted as soon as functor exits. + Run(ctx context.Context, fn func(context.Context, PodController) (map[string]interface{}, error)) (map[string]interface{}, error) } -// PodRunner specifies Kubernetes Client and PodOptions needed for creating Pod +// podRunner implements PodRunner interface type podRunner struct { pc PodController } @@ -60,14 +55,10 @@ func NewPodRunnerWithPodController(pc PodController) PodRunner { } // Run will create a new Pod based on PodRunner contents and execute the given function -func (p *podRunner) Run(ctx context.Context, fn func(context.Context, *v1.Pod) (map[string]interface{}, error)) (map[string]interface{}, error) { - return p.RunEx(ctx, func(innerCtx context.Context, pc PodController) (map[string]interface{}, error) { - return fn(innerCtx, pc.Pod()) - }) -} - -// RunEx will create a new Pod based on PodRunner contents and execute the given function -func (p *podRunner) RunEx(ctx context.Context, fn func(context.Context, PodController) (map[string]interface{}, error)) (map[string]interface{}, error) { +func (p *podRunner) Run( + ctx context.Context, + fn func(context.Context, PodController) (map[string]interface{}, error), +) (map[string]interface{}, error) { ctx, cancel := context.WithCancel(ctx) defer cancel() diff --git a/pkg/kube/pod_runner_test.go b/pkg/kube/pod_runner_test.go index 900d7df852..779d58c080 100644 --- a/pkg/kube/pod_runner_test.go +++ b/pkg/kube/pod_runner_test.go @@ -109,8 +109,8 @@ func (s *PodRunnerTestSuite) TestPodRunnerForSuccessCase(c *C) { cancel() } -func makePodRunnerTestFunc(ch chan struct{}) func(ctx context.Context, pod *v1.Pod) (map[string]interface{}, error) { - return func(ctx context.Context, pod *v1.Pod) (map[string]interface{}, error) { +func makePodRunnerTestFunc(ch chan struct{}) func(ctx context.Context, pc PodController) (map[string]interface{}, error) { + return func(ctx context.Context, pc PodController) (map[string]interface{}, error) { <-ch return nil, nil } diff --git a/pkg/kube/pod_test.go b/pkg/kube/pod_test.go index 236a07d101..6ff464cd68 100644 --- a/pkg/kube/pod_test.go +++ b/pkg/kube/pod_test.go @@ -304,7 +304,56 @@ func (s *PodSuite) TestPodWithFilesystemModeVolumes(c *C) { } pvc, err := cli.CoreV1().PersistentVolumeClaims(s.namespace).Create(context.TODO(), pvc, metav1.CreateOptions{}) c.Assert(err, IsNil) - vols := map[string]string{pvc.Name: "/mnt/data1"} + vols := map[string]VolumeMountOptions{pvc.Name: {MountPath: "/mnt/data1", ReadOnly: PVCContainsReadOnlyAccessMode(pvc)}} + ctx := context.Background() + var p *corev1.Pod + cli.PrependReactor("create", "pods", func(action testing.Action) (handled bool, ret runtime.Object, err error) { + fmt.Println("found pod") + ca := action.(testing.CreateAction) + p = ca.GetObject().(*corev1.Pod) + if len(p.Spec.Volumes[0].Name) > 63 { + return true, nil, errors.New("spec.volumes[0].name must be no more than 63 characters") + } + return false, nil, nil + }) + cli.PrependReactor("get", "pods", func(action testing.Action) (handled bool, ret runtime.Object, err error) { + p.Status.Phase = corev1.PodRunning + return true, p, nil + }) + pod, err := CreatePod(ctx, cli, &PodOptions{ + Namespace: s.namespace, + GenerateName: "test-", + Image: consts.LatestKanisterToolsImage, + Command: []string{"sh", "-c", "tail -f /dev/null"}, + Volumes: vols, + }) + c.Assert(err, IsNil) + c.Assert(WaitForPodReady(ctx, cli, s.namespace, pod.Name), IsNil) + c.Assert(pod.Spec.Volumes, HasLen, 1) + c.Assert(pod.Spec.Volumes[0].VolumeSource.PersistentVolumeClaim.ClaimName, Equals, pvcName) + c.Assert(pod.Spec.Containers[0].VolumeMounts[0].MountPath, Equals, "/mnt/data1") + c.Assert(len(pod.Spec.Containers[0].VolumeDevices), Equals, 0) +} + +func (s *PodSuite) TestPodWithFilesystemModeReadOnlyVolumes(c *C) { + cli := fake.NewSimpleClientset() + pvcName := "pvc-with-read-only-mount" + pvc := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadOnlyMany}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceName(corev1.ResourceStorage): resource.MustParse("1Gi"), + }, + }, + }, + } + pvc, err := cli.CoreV1().PersistentVolumeClaims(s.namespace).Create(context.TODO(), pvc, metav1.CreateOptions{}) + c.Assert(err, IsNil) + vols := map[string]VolumeMountOptions{pvc.Name: {MountPath: "/mnt/data1", ReadOnly: PVCContainsReadOnlyAccessMode(pvc)}} ctx := context.Background() var p *corev1.Pod cli.PrependReactor("create", "pods", func(action testing.Action) (handled bool, ret runtime.Object, err error) { @@ -415,7 +464,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -461,7 +510,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -501,7 +550,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -555,7 +604,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -616,7 +665,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -679,7 +728,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"echo", "override command"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -719,7 +768,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"echo", "override command"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ @@ -762,7 +811,7 @@ func (s *PodSuite) TestPatchDefaultPodSpecs(c *C) { Containers: []corev1.Container{ { Name: "container", - Image: "ghcr.io/kanisterio/kanister-tools:0.96.0", + Image: "ghcr.io/kanisterio/kanister-tools:0.97.0", Command: []string{"sh", "-c", "echo in default specs"}, ImagePullPolicy: corev1.PullPolicy(corev1.PullIfNotPresent), VolumeMounts: []corev1.VolumeMount{ diff --git a/pkg/kube/utils.go b/pkg/kube/utils.go index 5eee2ababe..00c9baf06f 100644 --- a/pkg/kube/utils.go +++ b/pkg/kube/utils.go @@ -160,3 +160,14 @@ func IsNodeReady(node *v1.Node) bool { } return false } + +// PVCContainsReadOnlyAccessMode return true if AccessModes of PVC contain `ReadOnlyMany` +func PVCContainsReadOnlyAccessMode(pvc *v1.PersistentVolumeClaim) bool { + for _, accessMode := range pvc.Spec.AccessModes { + if accessMode == v1.ReadOnlyMany { + return true + } + } + + return false +} diff --git a/pkg/log/log.go b/pkg/log/log.go index 2ffe9e99b1..8addf8f259 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -198,7 +198,7 @@ func (l *logger) entry(fields ...field.M) *logrus.Entry { } } - frame := caller.GetFrame(3) + frame := caller.GetFrame(4) logFields["Function"] = frame.Function logFields["File"] = frame.File logFields["Line"] = frame.Line diff --git a/pkg/phase.go b/pkg/phase.go index 3d9d45bd33..87198b551c 100644 --- a/pkg/phase.go +++ b/pkg/phase.go @@ -46,6 +46,11 @@ func (p *Phase) Name() string { return p.name } +// Progress return execution progress of the phase. +func (p *Phase) Progress() (crv1alpha1.PhaseProgress, error) { + return p.f.ExecutionProgress() +} + // Objects returns the phase object references func (p *Phase) Objects() map[string]crv1alpha1.ObjectReference { return p.objects diff --git a/pkg/phase_test.go b/pkg/phase_test.go index aaef64c02c..3ae63a09d7 100644 --- a/pkg/phase_test.go +++ b/pkg/phase_test.go @@ -31,8 +31,9 @@ var ( ) type testFunc struct { - output *string - err error + output *string + err error + progressPercent string } type anotherFunc struct { @@ -48,6 +49,9 @@ func (*testFunc) Name() string { } func (tf *testFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) { + tf.progressPercent = "0" + defer func() { tf.progressPercent = "100" }() + *tf.output = args["testKey"].(string) return nil, tf.err } @@ -60,6 +64,10 @@ func (tf *testFunc) Arguments() []string { return nil } +func (tf *testFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + return crv1alpha1.PhaseProgress{ProgressPercent: tf.progressPercent}, nil +} + func (s *PhaseSuite) TestExec(c *C) { for _, tc := range []struct { artifact string diff --git a/pkg/progress/action.go b/pkg/progress/action.go index db54209816..3cea9fcb41 100644 --- a/pkg/progress/action.go +++ b/pkg/progress/action.go @@ -2,41 +2,29 @@ package progress import ( "context" - "fmt" "strconv" "time" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + kanister "github.com/kanisterio/kanister/pkg" crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/client/clientset/versioned" "github.com/kanisterio/kanister/pkg/field" - fn "github.com/kanisterio/kanister/pkg/function" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/reconcile" "github.com/kanisterio/kanister/pkg/validate" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( - progressPercentCompleted = "100.00" - progressPercentStarted = "10.00" - progressPercentNotStarted = "0.00" - weightNormal = 1.0 - weightHeavy = 2.0 - pollDuration = time.Second * 2 -) + pollDuration = time.Second * 5 -var longRunningFuncs = []string{ - fn.BackupDataFuncName, - fn.BackupDataAllFuncName, - fn.RestoreDataFuncName, - fn.RestoreDataAllFuncName, - fn.CopyVolumeDataFuncName, - fn.CreateRDSSnapshotFuncName, - fn.ExportRDSSnapshotToLocFuncName, - fn.RestoreRDSSnapshotFuncName, -} + StartedPercent = "0" + CompletedPercent = "100" +) -// TrackActionsProgress tries to assess the progress of an actionSet by +// UpdateActionSetsProgress tries to assess the progress of an actionSet by // watching the states of all the phases in its actions. It starts an infinite // loop, using a ticker to determine when to assess the phases. The function // returns when the provided context is either done or cancelled. @@ -44,172 +32,168 @@ var longRunningFuncs = []string{ // introducing any latencies on Kanister critical path. // If an error happens while attempting to update the actionSet, the failed // iteration will be skipped with no further retries, until the next tick. -func TrackActionsProgress( +func UpdateActionSetsProgress( ctx context.Context, + aIDX int, client versioned.Interface, actionSetName string, namespace string, + p *kanister.Phase, ) error { ticker := time.NewTicker(pollDuration) defer ticker.Stop() - phaseWeights, totalWeight, err := calculatePhaseWeights(ctx, actionSetName, namespace, client) - if err != nil { - return err - } - for { select { case <-ctx.Done(): return ctx.Err() case <-ticker.C: - actionSet, err := client.CrV1alpha1().ActionSets(namespace).Get(ctx, actionSetName, metav1.GetOptions{}) + retry, err := updateActionProgress(ctx, aIDX, client, actionSetName, namespace, p) if err != nil { - return err - } - - if actionSet.Status == nil { - continue - } - - if err := updateActionsProgress(ctx, client, actionSet, phaseWeights, totalWeight, time.Now()); err != nil { fields := field.M{ - "actionSet": actionSet.Name, + "actionSet": actionSetName, "nextUpdateTime": time.Now().Add(pollDuration), } - log.Error().WithError(err).Print("failed to update phase progress", fields) - continue + log.Error().WithError(err).Print("failed to update action progress", fields) + return err } - - if completedOrFailed(actionSet) { + if !retry { return nil } } } } -func calculatePhaseWeights( +func updateActionProgress( ctx context.Context, + aIDX int, + client versioned.Interface, actionSetName string, namespace string, - client versioned.Interface, -) (map[string]float64, float64, error) { - var ( - phaseWeights = map[string]float64{} - totalWeight = 0.0 - ) - + p *kanister.Phase, +) (bool, error) { actionSet, err := client.CrV1alpha1().ActionSets(namespace).Get(ctx, actionSetName, metav1.GetOptions{}) if err != nil { - return nil, 0.0, err + return false, errors.Wrap(err, "Failed to get actionset") } - for _, action := range actionSet.Spec.Actions { - blueprintName := action.Blueprint - blueprint, err := client.CrV1alpha1().Blueprints(actionSet.GetNamespace()).Get(ctx, blueprintName, metav1.GetOptions{}) - if err != nil { - return nil, 0.0, err - } - - if err := validate.Blueprint(blueprint); err != nil { - return nil, 0.0, err - } - - blueprintAction, exists := blueprint.Actions[action.Name] - if !exists { - return nil, 0.0, fmt.Errorf("missing blueprint action: %s", action.Name) - } + if actionSet.Status == nil { + return true, nil + } - for _, phase := range blueprintAction.Phases { - phaseWeight := weight(&phase) - phaseWeights[phase.Name] = phaseWeight - totalWeight += phaseWeight - } + if completedOrFailed(aIDX, actionSet, p.Name()) { + return false, nil } - return phaseWeights, totalWeight, nil + if err := updateActionPhaseProgress(ctx, client, actionSet, p); err != nil { + return true, err + } + return true, nil } -func updateActionsProgress( +func updateActionPhaseProgress( ctx context.Context, client versioned.Interface, actionSet *crv1alpha1.ActionSet, - phaseWeights map[string]float64, - totalWeight float64, - now time.Time, + p *kanister.Phase, ) error { if err := validate.ActionSet(actionSet); err != nil { return err } - // assess the state of the phases in all the actions to determine progress - currentWeight := 0.0 - for _, action := range actionSet.Status.Actions { - for _, phase := range action.Phases { - if phase.State != crv1alpha1.StateComplete { - continue - } - currentWeight += phaseWeights[phase.Name] - } - } - - percent := (currentWeight / totalWeight) * 100.0 - progressPercent := strconv.FormatFloat(percent, 'f', 2, 64) - if progressPercent == progressPercentNotStarted { - progressPercent = progressPercentStarted + phaseProgress, err := p.Progress() + if err != nil { + log.Error().WithError(err).Print("Failed to get progress") + return err } + return updateActionSetStatus(ctx, client, actionSet, p.Name(), phaseProgress) +} +func updateActionSetStatus( + ctx context.Context, + client versioned.Interface, + actionSet *crv1alpha1.ActionSet, + phaseName string, + phaseProgress crv1alpha1.PhaseProgress, +) error { fields := field.M{ "actionSet": actionSet.GetName(), "namespace": actionSet.GetNamespace(), - "progress": progressPercent, + "phase": phaseName, + "progress": phaseProgress.ProgressPercent, } - log.Debug().Print("updating action progress", fields) - - return updateActionSet(ctx, client, actionSet, progressPercent, now) -} - -func weight(phase *crv1alpha1.BlueprintPhase) float64 { - if longRunning(phase) { - return weightHeavy + log.Debug().Print("Updating phase progress", fields) + updateFunc := func(actionSet *crv1alpha1.ActionSet) error { + return setActionSetPhaseProgress(actionSet, phaseName, phaseProgress) + } + if err := reconcile.ActionSet(ctx, client.CrV1alpha1(), actionSet.GetNamespace(), actionSet.GetName(), updateFunc); err != nil { + return err } - return weightNormal + return nil } -func longRunning(phase *crv1alpha1.BlueprintPhase) bool { - for _, f := range longRunningFuncs { - if phase.Func == f { - return true +func completedOrFailed(aIDX int, actionSet *crv1alpha1.ActionSet, phaseName string) bool { + for _, phase := range actionSet.Status.Actions[aIDX].Phases { + if phase.Name != phaseName { + continue } + return phase.State == crv1alpha1.StateFailed || + phase.State == crv1alpha1.StateComplete } - return false } -func updateActionSet( - ctx context.Context, - client versioned.Interface, - actionSet *crv1alpha1.ActionSet, - progressPercent string, - lastTransitionTime time.Time, -) error { - updateFunc := func(actionSet *crv1alpha1.ActionSet) error { - metav1Time := metav1.NewTime(lastTransitionTime) - - actionSet.Status.Progress.PercentCompleted = progressPercent - actionSet.Status.Progress.LastTransitionTime = &metav1Time - return nil +func setActionSetPhaseProgress(actionSet *crv1alpha1.ActionSet, phaseName string, phaseProgress crv1alpha1.PhaseProgress) error { + // Update or create phase status in ActionSet status + // Update phase progress if there is a change + for i := 0; i < len(actionSet.Status.Actions); i++ { + for j := 0; j < len(actionSet.Status.Actions[i].Phases); j++ { + if actionSet.Status.Actions[i].Phases[j].Name != phaseName { + continue + } + if actionSet.Status.Actions[i].Phases[j].State == crv1alpha1.StatePending || + actionSet.Status.Actions[i].Phases[j].State == crv1alpha1.StateFailed { + continue + } + if actionSet.Status.Actions[i].Phases[j].Progress.ProgressPercent != phaseProgress.ProgressPercent { + actionSet.Status.Actions[i].Phases[j].Progress = phaseProgress + if err := SetActionSetPercentCompleted(actionSet); err != nil { + return err + } + } + } } + return nil +} - if err := reconcile.ActionSet(ctx, client.CrV1alpha1(), actionSet.GetNamespace(), actionSet.GetName(), updateFunc); err != nil { - return err +// SetActionSetPercentCompleted calculate and set percent completion of the action. The action completion percentage +// is calculated by taking an average of all the involved phases. +func SetActionSetPercentCompleted(actionSet *crv1alpha1.ActionSet) error { + actionProgress := 0 + totalPhases := 0 + for _, actions := range actionSet.Status.Actions { + for _, phase := range actions.Phases { + if phase.Progress.ProgressPercent == "" { + totalPhases++ + continue + } + pp, err := strconv.Atoi(phase.Progress.ProgressPercent) + if err != nil { + return errors.Wrap(err, "Invalid phase progress percent") + } + actionProgress += pp + totalPhases++ + } } + actionProgress = actionProgress / totalPhases + // Update LastTransitionTime only if there is a change in action PercentCompleted + if strconv.Itoa(actionProgress) == actionSet.Status.Progress.PercentCompleted { + return nil + } + metav1Time := metav1.NewTime(time.Now()) + actionSet.Status.Progress.LastTransitionTime = &metav1Time + actionSet.Status.Progress.PercentCompleted = strconv.Itoa(actionProgress) return nil } - -func completedOrFailed(actionSet *crv1alpha1.ActionSet) bool { - return actionSet.Status.State == crv1alpha1.StateFailed || - actionSet.Status.State == crv1alpha1.StateComplete -} diff --git a/pkg/progress/action_multi_actions_test.go b/pkg/progress/action_multi_actions_test.go index 7ebddb71dc..a801085386 100644 --- a/pkg/progress/action_multi_actions_test.go +++ b/pkg/progress/action_multi_actions_test.go @@ -2,7 +2,6 @@ package progress import ( "context" - "time" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -31,12 +30,12 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, { - Name: "echo-world", - Func: "echo-world-func", + Name: "echo-hello-0-1", + Func: "echo-hello-func", }, }, }, @@ -44,12 +43,12 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-02", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-1-0", Func: "echo-hello-func", }, { - Name: "echo-world", - Func: "echo-world-func", + Name: "echo-hello-1-1", + Func: "echo-hello-func", }, }, }, @@ -91,11 +90,11 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-0-1", State: crv1alpha1.StatePending, }, }, @@ -104,11 +103,11 @@ func (s *TestSuiteMultiActions) SetUpTest(c *C) { Name: "action-02", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-1-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-1-1", State: crv1alpha1.StatePending, }, }, @@ -159,145 +158,185 @@ func (s *TestSuiteMultiActions) createFixtures(blueprint *crv1alpha1.Blueprint, } func (s *TestSuiteMultiActions) TestUpdateActionsProgress(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "40", + expectedPhasePercent: "40", + expectedActionPercent: "10", // Total 4 phases, calculating average to set action progress }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "25.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "25.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "25.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "60", + expectedPhasePercent: "60", + expectedActionPercent: "40", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: "50.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: "50.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "37", + expectedPhasePercent: "37", + expectedActionPercent: "59", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "75.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "23", + expectedPhasePercent: "23", + expectedActionPercent: "80", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } func (s *TestSuiteMultiActions) TestUpdateActionsProgressWithFailures(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "25.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "25", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "75.00", + indexAction: 1, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "75", }, { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateFailed, - expected: "75.00", + indexAction: 1, + indexPhase: 1, + phaseState: crv1alpha1.StateFailed, + phasePercent: "30", + expectedPhasePercent: "", + expectedActionPercent: "75", }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } diff --git a/pkg/progress/action_multi_phases_test.go b/pkg/progress/action_multi_phases_test.go index 7d20819171..f33b087d65 100644 --- a/pkg/progress/action_multi_phases_test.go +++ b/pkg/progress/action_multi_phases_test.go @@ -2,7 +2,6 @@ package progress import ( "context" - "time" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" . "gopkg.in/check.v1" @@ -31,11 +30,11 @@ func (s *TestSuiteMultiPhases) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, { - Name: "echo-world", + Name: "echo-hello-0-1", Func: "echo-world-func", }, }, @@ -69,11 +68,11 @@ func (s *TestSuiteMultiPhases) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, { - Name: "echo-world", + Name: "echo-hello-0-1", State: crv1alpha1.StatePending, }, }, @@ -124,97 +123,123 @@ func (s *TestSuiteMultiPhases) createFixtures(blueprint *crv1alpha1.Blueprint, a } func (s *TestSuiteMultiPhases) TestUpdateActionsProgress(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateRunning, + phasePercent: "30", + expectedPhasePercent: "30", + expectedActionPercent: "15", }, { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StatePending, + phasePercent: "0", + expectedPhasePercent: "", + expectedActionPercent: "50", // stays at 50% because 1st action is done }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateRunning, + phasePercent: "60", + expectedPhasePercent: "60", + expectedActionPercent: "80", // Averaging out action progress 100(phase-1)+60(phase-2)/2(total phases) }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } func (s *TestSuiteMultiPhases) TestUpdateActionsProgressWithFailures(c *C) { - now := time.Now() var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "50.00", + indexAction: 0, + indexPhase: 0, + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: "50", }, { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateFailed, - expected: "50.00", // stays at 50% because 1st action is done + indexAction: 0, + indexPhase: 1, + phaseState: crv1alpha1.StateFailed, + phasePercent: "30", + expectedPhasePercent: "", + expectedActionPercent: "50", // stays at 50% because 1st action is done }, } for id, tc := range testCases { + // Get latest rev of actionset resource + as, err := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Get(context.Background(), s.actionSet.GetName(), metav1.GetOptions{}) + c.Assert(err, IsNil) assertActionProgress( c, s.clientset, - s.actionSet, - now, + as, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } diff --git a/pkg/progress/action_single_phase_test.go b/pkg/progress/action_single_phase_test.go index c512683c25..8a843779e9 100644 --- a/pkg/progress/action_single_phase_test.go +++ b/pkg/progress/action_single_phase_test.go @@ -2,8 +2,8 @@ package progress import ( "context" + "fmt" "testing" - "time" "github.com/kanisterio/kanister/pkg/client/clientset/versioned" "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" @@ -43,7 +43,7 @@ func (s *TestSuiteSinglePhase) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.BlueprintPhase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", Func: "echo-hello-func", }, }, @@ -77,7 +77,7 @@ func (s *TestSuiteSinglePhase) SetUpTest(c *C) { Name: "action-01", Phases: []crv1alpha1.Phase{ { - Name: "echo-hello", + Name: "echo-hello-0-0", State: crv1alpha1.StatePending, }, }, @@ -127,42 +127,56 @@ func (s *TestSuiteSinglePhase) createFixtures(blueprint *crv1alpha1.Blueprint, a return nil } -func (s *TestSuiteSinglePhase) TestUpdateActionsProgress(c *C) { - now := time.Now() +func (s *TestSuiteSinglePhase) TestUpdateActionPhaseProgress(c *C) { var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string + indexAction int + indexPhase int + phaseState crv1alpha1.State + phasePercent string + expectedPhasePercent string + expectedActionPercent string }{ { - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, + phaseState: crv1alpha1.StatePending, + expectedPhasePercent: "", + expectedActionPercent: "", }, { - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, + phaseState: crv1alpha1.StateRunning, + phasePercent: "20", + expectedPhasePercent: "20", + expectedActionPercent: "20", }, { - phaseState: crv1alpha1.StateFailed, - expected: progressPercentStarted, + phaseState: crv1alpha1.StateRunning, + phasePercent: "50", + expectedPhasePercent: "50", + expectedActionPercent: "50", }, { - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, + phaseState: crv1alpha1.StateFailed, + phasePercent: "50", + expectedPhasePercent: "", + expectedActionPercent: "", + }, + { + phaseState: crv1alpha1.StateComplete, + phasePercent: CompletedPercent, + expectedPhasePercent: CompletedPercent, + expectedActionPercent: CompletedPercent, }, } - for id, tc := range testCases { assertActionProgress( c, s.clientset, s.actionSet, - now, tc.indexAction, tc.indexPhase, tc.phaseState, - tc.expected, + tc.phasePercent, + tc.expectedPhasePercent, + tc.expectedActionPercent, id) } } @@ -171,28 +185,29 @@ func assertActionProgress( c *C, clientset versioned.Interface, actionSet *crv1alpha1.ActionSet, - now time.Time, indexAction int, indexPhase int, - newState crv1alpha1.State, - expectedPercentCompleted string, + phaseState crv1alpha1.State, + phasePercent string, + expectedPhasePercent string, + expectedActionPercent string, testCaseID int) { - // update the phase state - actionSet.Status.Actions[indexAction].Phases[indexPhase].State = newState + now := metav1.Now() + actionSet.Status.Actions[indexAction].Phases[indexPhase].State = phaseState updated, err := clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Update(context.Background(), actionSet, metav1.UpdateOptions{}) c.Assert(err, IsNil) - - // calculate and update the progress so that it reflects the state change - phaseWeights, totalWeight, err := calculatePhaseWeights(context.Background(), actionSet.GetName(), actionSet.GetNamespace(), clientset) - c.Assert(err, IsNil) - - updateErr := updateActionsProgress(context.Background(), clientset, updated, phaseWeights, totalWeight, now) - c.Assert(updateErr, IsNil) - - // retrieve the latest actionSet resource to confirm its progress data + phaseName := fmt.Sprintf("echo-hello-%d-%d", indexAction, indexPhase) + err1 := updateActionSetStatus(context.Background(), clientset, actionSet, phaseName, crv1alpha1.PhaseProgress{ProgressPercent: phasePercent, LastTransitionTime: &now}) + c.Assert(err1, IsNil, Commentf("test case #: %d", testCaseID)) actual, err := clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Get(context.Background(), updated.GetName(), metav1.GetOptions{}) - c.Assert(err, IsNil, Commentf("test case #: %d", testCaseID)) - c.Assert(actual.Status.Progress.PercentCompleted, Equals, expectedPercentCompleted, Commentf("test case #: %d", testCaseID)) - c.Assert(actual.Status.Progress.LastTransitionTime, NotNil) - c.Assert(actual.Status.Progress.LastTransitionTime.Time, Equals, now, Commentf("test case #: %d", testCaseID)) + c.Assert(err, IsNil) + // Check phase progress percent + c.Assert(actual.Status.Actions[indexAction].Phases[indexPhase].Progress.ProgressPercent, Equals, expectedPhasePercent, Commentf("test case #: %d", testCaseID)) + // Check action progress percent + c.Assert(actual.Status.Progress.PercentCompleted, Equals, expectedActionPercent, Commentf("test case #: %d", testCaseID)) + if phaseState != crv1alpha1.StateFailed && + phaseState != crv1alpha1.StatePending { + c.Assert(actual.Status.Actions[indexAction].Phases[indexPhase].Progress.LastTransitionTime, NotNil) + c.Assert(*actual.Status.Actions[indexAction].Phases[indexPhase].Progress.LastTransitionTime, Equals, now, Commentf("test case #: %d", testCaseID)) + } } diff --git a/pkg/progress/action_weighted_funcs_test.go b/pkg/progress/action_weighted_funcs_test.go deleted file mode 100644 index ea39ca0b3c..0000000000 --- a/pkg/progress/action_weighted_funcs_test.go +++ /dev/null @@ -1,255 +0,0 @@ -package progress - -import ( - "context" - "time" - - "github.com/kanisterio/kanister/pkg/client/clientset/versioned/fake" - . "gopkg.in/check.v1" - - crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -type TestSuiteWeightedFuncs struct { - blueprint *crv1alpha1.Blueprint - actionSet *crv1alpha1.ActionSet - clientset *fake.Clientset -} - -var _ = Suite(&TestSuiteWeightedFuncs{}) - -func (s *TestSuiteWeightedFuncs) SetUpTest(c *C) { - mockBlueprint := &crv1alpha1.Blueprint{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: testBlueprint, - Namespace: testNamespace, - }, - Actions: map[string]*crv1alpha1.BlueprintAction{ - "action-weighted": { - Name: "action-weighted", - Phases: []crv1alpha1.BlueprintPhase{ - { - Name: "echo-00", - Func: "BackupData", - }, - { - Name: "echo-01", - Func: "CopyVolumeData", - }, - }, - }, - "action-normal": { - Name: "action-normal", - Phases: []crv1alpha1.BlueprintPhase{ - { - Name: "echo-02", - Func: "echo-hello-func", - }, - { - Name: "echo-03", - Func: "echo-hello-func", - }, - }, - }, - }, - } - - mockActionSet := &crv1alpha1.ActionSet{ - TypeMeta: metav1.TypeMeta{}, - ObjectMeta: metav1.ObjectMeta{ - Name: testActionset, - Namespace: testNamespace, - }, - Spec: &crv1alpha1.ActionSetSpec{ - Actions: []crv1alpha1.ActionSpec{ - { - Name: "action-weighted", - Object: crv1alpha1.ObjectReference{ - APIVersion: "v1", - Group: "", - Resource: "Namespace", - }, - Blueprint: testBlueprint, - }, - { - Name: "action-normal", - Object: crv1alpha1.ObjectReference{ - APIVersion: "v1", - Group: "", - Resource: "Namespace", - }, - Blueprint: testBlueprint, - }, - }, - }, - Status: &crv1alpha1.ActionSetStatus{ - State: crv1alpha1.StateRunning, - Actions: []crv1alpha1.ActionStatus{ - { - Name: "action-weighted", - Phases: []crv1alpha1.Phase{ - { - Name: "echo-00", - State: crv1alpha1.StatePending, - }, - { - Name: "echo-01", - State: crv1alpha1.StatePending, - }, - }, - }, - { - Name: "action-normal", - Phases: []crv1alpha1.Phase{ - { - Name: "echo-02", - State: crv1alpha1.StatePending, - }, - { - Name: "echo-03", - State: crv1alpha1.StatePending, - }, - }, - }, - }, - }, - } - - s.clientset = fake.NewSimpleClientset() - err := s.createFixtures(mockBlueprint, mockActionSet) - c.Assert(err, IsNil) -} - -func (s *TestSuiteWeightedFuncs) TearDownTest(c *C) { - blueprintErr := s.clientset.CrV1alpha1().Blueprints(s.blueprint.GetNamespace()).Delete( - context.Background(), - s.blueprint.GetName(), - metav1.DeleteOptions{}) - c.Assert(blueprintErr, IsNil) - - actionSetErr := s.clientset.CrV1alpha1().ActionSets(s.actionSet.GetNamespace()).Delete( - context.Background(), - s.actionSet.GetName(), - metav1.DeleteOptions{}) - c.Assert(actionSetErr, IsNil) -} - -func (s *TestSuiteWeightedFuncs) createFixtures(blueprint *crv1alpha1.Blueprint, actionSet *crv1alpha1.ActionSet) error { - createdBlueprint, err := s.clientset.CrV1alpha1().Blueprints(blueprint.GetNamespace()).Create( - context.Background(), - blueprint, - metav1.CreateOptions{}) - if err != nil { - return err - } - s.blueprint = createdBlueprint - - createdActionSet, err := s.clientset.CrV1alpha1().ActionSets(actionSet.GetNamespace()).Create( - context.Background(), - actionSet, - metav1.CreateOptions{}) - if err != nil { - return err - } - s.actionSet = createdActionSet - - return nil -} - -func (s *TestSuiteWeightedFuncs) TestUpdateActionsProgress(c *C) { - now := time.Now() - var testCases = []struct { - indexAction int - indexPhase int - phaseState crv1alpha1.State - expected string - }{ - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: progressPercentStarted, - }, - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: progressPercentStarted, - }, - { - indexAction: 0, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "33.33", - }, - { - indexAction: 0, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StatePending, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateRunning, - expected: "66.67", - }, - { - indexAction: 1, - indexPhase: 0, - phaseState: crv1alpha1.StateComplete, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StatePending, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateRunning, - expected: "83.33", - }, - { - indexAction: 1, - indexPhase: 1, - phaseState: crv1alpha1.StateComplete, - expected: progressPercentCompleted, - }, - } - - for id, tc := range testCases { - assertActionProgress( - c, - s.clientset, - s.actionSet, - now, - tc.indexAction, - tc.indexPhase, - tc.phaseState, - tc.expected, - id) - } -} diff --git a/pkg/testing/e2e_test.go b/pkg/testing/e2e_test.go index 8bc9d53d85..e94adaf0e0 100644 --- a/pkg/testing/e2e_test.go +++ b/pkg/testing/e2e_test.go @@ -228,7 +228,7 @@ func (s *E2ESuite) TestKubeTask(c *C) { Func: function.KubeTaskFuncName, Name: "test-kube-task", Args: map[string]interface{}{ - "image": "ghcr.io/kanisterio/kanister-tools:0.96.0", + "image": "ghcr.io/kanisterio/kanister-tools:0.97.0", "namespace": "{{ .Deployment.Namespace }}", "command": []string{"echo", "default specs"}, "podOverride": map[string]interface{}{ diff --git a/pkg/testutil/func.go b/pkg/testutil/func.go index e05ae68a92..e2f45f445b 100644 --- a/pkg/testutil/func.go +++ b/pkg/testutil/func.go @@ -16,11 +16,15 @@ package testutil import ( "context" + "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kanister "github.com/kanisterio/kanister/pkg" + crv1alpha1 "github.com/kanisterio/kanister/pkg/apis/cr/v1alpha1" "github.com/kanisterio/kanister/pkg/param" + "github.com/kanisterio/kanister/pkg/progress" ) const ( @@ -112,6 +116,13 @@ func (mf *mockKanisterFunc) Exec(ctx context.Context, tp param.TemplateParams, a func (mf *mockKanisterFunc) Name() string { return mf.name } +func (mf *mockKanisterFunc) ExecutionProgress() (crv1alpha1.PhaseProgress, error) { + metav1Time := metav1.NewTime(time.Now()) + return crv1alpha1.PhaseProgress{ + ProgressPercent: progress.StartedPercent, + LastTransitionTime: &metav1Time, + }, nil +} func FailFuncError() error { return <-failFuncCh diff --git a/scripts/get.sh b/scripts/get.sh index ccb3c82be5..aada893de0 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -140,7 +140,7 @@ cleanup() { } main() { - version="${1:-"0.96.0"}" + version="${1:-"0.97.0"}" initArch initOS verifySupported