From dae8f8cbf25c3336a73a1a94756c4483922c5b8f Mon Sep 17 00:00:00 2001 From: ChristianZaccaria Date: Mon, 14 Aug 2023 13:16:55 +0100 Subject: [PATCH] WIP - e2e --- .github/actions/kind/action.yml | 58 ++ .github/resources-kind/kind.yaml | 31 ++ .github/workflows/e2e_tests.yaml | 128 +++++ Dockerfile | 25 + Makefile | 465 ++++++++++++++++ go.mod | 56 ++ go.sum | 498 ++++++++++++++++++ pyproject.toml | 2 +- .../codeflare_sdk-0.0.0.dev0-py3-none-any.whl | Bin 0 -> 32670 bytes tests/e2e/kind.sh | 38 ++ tests/e2e/mnist.py | 160 ++++++ tests/e2e/mnist_pip_requirements.txt | 3 + tests/e2e/mnist_raycluster_sdk.py | 64 +++ tests/e2e/mnist_raycluster_sdk_test.go | 214 ++++++++ tests/e2e/setup.sh | 73 +++ tests/e2e/support.go | 44 ++ 16 files changed, 1858 insertions(+), 1 deletion(-) create mode 100644 .github/actions/kind/action.yml create mode 100644 .github/resources-kind/kind.yaml create mode 100644 .github/workflows/e2e_tests.yaml create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 go.mod create mode 100644 go.sum create mode 100644 tests/e2e/codeflare_sdk-0.0.0.dev0-py3-none-any.whl create mode 100755 tests/e2e/kind.sh create mode 100644 tests/e2e/mnist.py create mode 100644 tests/e2e/mnist_pip_requirements.txt create mode 100644 tests/e2e/mnist_raycluster_sdk.py create mode 100644 tests/e2e/mnist_raycluster_sdk_test.go create mode 100755 tests/e2e/setup.sh create mode 100644 tests/e2e/support.go diff --git a/.github/actions/kind/action.yml b/.github/actions/kind/action.yml new file mode 100644 index 000000000..59dcafef7 --- /dev/null +++ b/.github/actions/kind/action.yml @@ -0,0 +1,58 @@ +name: "Set up KinD" +description: "Step to start and configure KinD cluster" + +runs: + using: "composite" + steps: + - name: Init directories + shell: bash + run: | + TEMP_DIR="$(pwd)/tmp" + mkdir -p "${TEMP_DIR}" + echo "TEMP_DIR=${TEMP_DIR}" >> $GITHUB_ENV + + mkdir -p "$(pwd)/bin" + echo "$(pwd)/bin" >> $GITHUB_PATH + + - name: Container image registry + shell: bash + run: | + podman run -d -p 5000:5000 --name registry registry:2.8.1 + + export REGISTRY_ADDRESS=$(hostname -i):5000 + echo "REGISTRY_ADDRESS=${REGISTRY_ADDRESS}" >> $GITHUB_ENV + echo "Container image registry started at ${REGISTRY_ADDRESS}" + + KIND_CONFIG_FILE=${{ env.TEMP_DIR }}/kind.yaml + echo "KIND_CONFIG_FILE=${KIND_CONFIG_FILE}" >> $GITHUB_ENV + envsubst < .github/resources-kind/kind.yaml > ${KIND_CONFIG_FILE} + + sudo --preserve-env=REGISTRY_ADDRESS sh -c 'cat > /etc/containers/registries.conf.d/local.conf <> $GITHUB_ENV + + set -euo pipefail + go test -timeout 30m -v ./tests/e2e -json 2>&1 | tee ${CODEFLARE_TEST_OUTPUT_DIR}/gotest.log | gotestfmt + + - name: Print CodeFlare operator logs + if: always() && steps.deploy.outcome == 'success' + run: | + echo "Printing CodeFlare operator logs" + kubectl logs -n openshift-operators --tail -1 -l app.kubernetes.io/name=codeflare-operator | tee ${CODEFLARE_TEST_OUTPUT_DIR}/codeflare-operator.log + + - name: Print MCAD controller logs + if: always() && steps.deploy.outcome == 'success' + run: | + echo "Printing MCAD controller logs" + kubectl logs -n codeflare-system --tail -1 -l component=multi-cluster-application-dispatcher | tee ${CODEFLARE_TEST_OUTPUT_DIR}/mcad.log + + - name: Print KubeRay operator logs + if: always() && steps.deploy.outcome == 'success' + run: | + echo "Printing KubeRay operator logs" + kubectl logs -n ray-system --tail -1 -l app.kubernetes.io/name=kuberay | tee ${CODEFLARE_TEST_OUTPUT_DIR}/kuberay.log + + - name: Upload logs + uses: actions/upload-artifact@v3 + if: always() && steps.deploy.outcome == 'success' + with: + name: logs + retention-days: 10 + path: | + ${{ env.CODEFLARE_TEST_OUTPUT_DIR }}/**/*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..302b31e1c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Build the manager binary +FROM registry.access.redhat.com/ubi8/go-toolset:1.19.10-10 as builder + +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +RUN go mod download + +# Copy the go source +COPY main.go main.go +COPY api/ api/ +COPY controllers/ controllers/ + +# Build +USER root +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go + +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.7 +WORKDIR / +COPY --from=builder /workspace/manager . +COPY config/internal config/internal + +USER 65532:65532 +ENTRYPOINT ["/manager"] diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..955c2de08 --- /dev/null +++ b/Makefile @@ -0,0 +1,465 @@ +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=v0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=v0.0.2) +# best if we could detect this. If we cannot, we need to document it somewhere. +# then we can add a patch in the `PHONY: bundle` +# BUNDLE_VERSION is declared as bundle versioning doesn't use semver + +PREVIOUS_VERSION ?= v0.0.0-dev +VERSION ?= v0.0.0-dev +BUNDLE_VERSION ?= $(VERSION:v%=%) + +# INSTASCALE_VERSION defines the default version of the InstaScale controller +INSTASCALE_VERSION ?= v0.0.6 + +# MCAD_VERSION defines the default version of the MCAD controller +MCAD_VERSION ?= v1.33.0 +# MCAD_REF, MCAD_REPO and MCAD_CRD define the reference to MCAD CRD resources +MCAD_REF ?= release-${MCAD_VERSION} +MCAD_REPO ?= github.com/project-codeflare/multi-cluster-app-dispatcher +# Upstream MCAD is currently only creating release tags of the form `vX.Y.Z` (i.e the version) +# The image is still published using the MCAD_REF format (i.e release-vX.Y.Z) +MCAD_CRD ?= ${MCAD_REPO}/config/crd?ref=${MCAD_VERSION} + +# KUBERAY_VERSION defines the default version of the KubeRay operator (used for testing) +KUBERAY_VERSION ?= v0.5.0 + +# RAY_VERSION defines the default version of Ray (used for testing) +RAY_VERSION ?= 2.5.0 + +# CODEFLARE_SDK_VERSION defines the default version of the CodeFlare SDK +CODEFLARE_SDK_VERSION ?= 0.6.1 + +# OPERATORS_REPO_ORG points to GitHub repository organization where bundle PR is opened against +# OPERATORS_REPO_FORK_ORG points to GitHub repository fork organization where bundle build is pushed to +OPERATORS_REPO_ORG ?= redhat-openshift-ecosystem +OPERATORS_REPO_FORK_ORG ?= project-codeflare + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# IMAGE_ORG_BASE defines the base container registry and organization for container images. +IMAGE_ORG_BASE ?= quay.io/project-codeflare + +# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. +# This variable is used to construct full image tags for bundle and catalog images. +# +# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both +# codeflare.dev/codeflare-operator-bundle:$VERSION and codeflare.dev/codeflare-operator-catalog:$VERSION. +IMAGE_TAG_BASE ?= $(IMAGE_ORG_BASE)/codeflare-operator + +# MCAD_IMAGE defines the default container image for the MCAD controller +MCAD_IMAGE ?= $(IMAGE_ORG_BASE)/mcad-controller:$(MCAD_REF) + +# INSTASCALE_IMAGE defines the default container image for the InstaScale controller +INSTASCALE_IMAGE ?= $(IMAGE_ORG_BASE)/instascale-controller:$(INSTASCALE_VERSION) + +# RAY_IMAGE defines the default container image for Ray (used for testing) +RAY_IMAGE ?= rayproject/ray:$(RAY_VERSION) + +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:$(VERSION) + +# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command +BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(BUNDLE_VERSION) $(BUNDLE_METADATA_OPTS) + +# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests +# You can enable this value if you would like to use SHA Based Digests +# To enable set flag to true +USE_IMAGE_DIGESTS ?= false +ifeq ($(USE_IMAGE_DIGESTS), true) + BUNDLE_GEN_FLAGS += --use-image-digests +endif + +# Image URL to use all building/pushing image targets +IMG ?= ${IMAGE_TAG_BASE}:${VERSION} +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. +ENVTEST_K8S_VERSION = 1.24.2 + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +# Setting SHELL to bash allows bash commands to be executed by recipes. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec + +.PHONY: all +all: build + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Development + +DEFAULTS_FILE := controllers/defaults.go +DEFAULTS_TEST_FILE := tests/support/defaults.go + +.PHONY: defaults +defaults: + $(info Regenerating $(DEFAULTS_FILE)) + @echo "package controllers" > $(DEFAULTS_FILE) + @echo "" >> $(DEFAULTS_FILE) + @echo "// ***********************" >> $(DEFAULTS_FILE) + @echo "// DO NOT EDIT THIS FILE" >> $(DEFAULTS_FILE) + @echo "// ***********************" >> $(DEFAULTS_FILE) + @echo "" >> $(DEFAULTS_FILE) + @echo "const (" >> $(DEFAULTS_FILE) + @echo " MCADImage = \"$(MCAD_IMAGE)\"" >> $(DEFAULTS_FILE) + @echo " InstaScaleImage = \"$(INSTASCALE_IMAGE)\"" >> $(DEFAULTS_FILE) + @echo "" >> $(DEFAULTS_FILE) + @echo ")" >> $(DEFAULTS_FILE) + @echo "" >> $(DEFAULTS_FILE) + + $(info Regenerating $(DEFAULTS_TEST_FILE)) + @echo "package support" > $(DEFAULTS_TEST_FILE) + @echo "" >> $(DEFAULTS_TEST_FILE) + @echo "// ***********************" >> $(DEFAULTS_TEST_FILE) + @echo "// DO NOT EDIT THIS FILE" >> $(DEFAULTS_TEST_FILE) + @echo "// ***********************" >> $(DEFAULTS_TEST_FILE) + @echo "" >> $(DEFAULTS_TEST_FILE) + @echo "const (" >> $(DEFAULTS_TEST_FILE) + @echo " CodeFlareSDKVersion = \"$(CODEFLARE_SDK_VERSION)\"" >> $(DEFAULTS_TEST_FILE) + @echo " RayVersion = \"$(RAY_VERSION)\"" >> $(DEFAULTS_TEST_FILE) + @echo " RayImage = \"$(RAY_IMAGE)\"" >> $(DEFAULTS_TEST_FILE) + @echo "" >> $(DEFAULTS_TEST_FILE) + @echo ")" >> $(DEFAULTS_TEST_FILE) + @echo "" >> $(DEFAULTS_TEST_FILE) + + gofmt -w $(DEFAULTS_FILE) $(DEFAULTS_TEST_FILE) + +.PHONY: manifests +manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases + +.PHONY: generate +generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." + +.PHONY: generate-client ## Generate client packages and organize the goimports +generate-client: generate-client-files imports + +.PHONY: generate-client-files +generate-client-files: code-generator + rm -rf client + $(APPLYCONFIGURATION_GEN) \ + --input-dirs="github.com/project-codeflare/codeflare-operator/api/codeflare/v1alpha1" \ + --go-header-file="hack/boilerplate.go.txt" \ + --output-package="github.com/project-codeflare/codeflare-operator/client/applyconfiguration" \ + --output-base="." \ + --trim-path-prefix "github.com/project-codeflare/codeflare-operator" + $(CLIENT_GEN) \ + --input="codeflare/v1alpha1" \ + --input-base="github.com/project-codeflare/codeflare-operator/api" \ + --apply-configuration-package="github.com/project-codeflare/codeflare-operator/client/applyconfiguration" \ + --go-header-file="hack/boilerplate.go.txt" \ + --clientset-name "versioned" \ + --output-package="github.com/project-codeflare/codeflare-operator/client/clientset" \ + --output-base="." \ + --trim-path-prefix "github.com/project-codeflare/codeflare-operator" + $(LISTER_GEN) \ + --input-dirs="github.com/project-codeflare/codeflare-operator/api/codeflare/v1alpha1" \ + --go-header-file="hack/boilerplate.go.txt" \ + --output-base="." \ + --output-package="github.com/project-codeflare/codeflare-operator/client/listers" \ + --trim-path-prefix "github.com/project-codeflare/codeflare-operator" + $(INFORMER_GEN) \ + --input-dirs="github.com/project-codeflare/codeflare-operator/api/codeflare/v1alpha1" \ + --versioned-clientset-package="github.com/project-codeflare/codeflare-operator/client/clientset/versioned" \ + --listers-package="github.com/project-codeflare/codeflare-operator/client/listers" \ + --go-header-file="hack/boilerplate.go.txt" \ + --output-base="." \ + --output-package="github.com/project-codeflare/codeflare-operator/client/informer" \ + --trim-path-prefix "github.com/project-codeflare/codeflare-operator" + +.PHONY: fmt +fmt: ## Run go fmt against code. + go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code. + go vet ./... + + +##@ Build + +.PHONY: modules +modules: ## Update Go dependencies. + go get $(MCAD_REPO)@$(MCAD_VERSION) + go get github.com/ray-project/kuberay/ray-operator + +.PHONY: build +build: modules defaults generate fmt vet ## Build manager binary. + go build -o bin/manager main.go + +.PHONY: run +run: modules defaults manifests generate fmt vet ## Run a controller from your host. + go run ./main.go + +.PHONY: image-build +image-build: test-unit ## Build container image with the manager. + podman build -t ${IMG} . + +.PHONY: image-push +image-push: image-build ## Push container image with the manager. + podman push ${IMG} + +##@ Deployment + +ifndef ignore-not-found + ignore-not-found = false +endif + +.PHONY: install +install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) fn run config/crd/mcad --image gcr.io/kpt-fn/apply-setters:v0.2.0 -- MCAD_CRD=$(MCAD_CRD) + $(KUSTOMIZE) build config/crd | kubectl apply -f - + git restore config/* + +.PHONY: uninstall +uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. + $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - + +.PHONY: deploy +deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) fn run config/crd/mcad --image gcr.io/kpt-fn/apply-setters:v0.2.0 -- MCAD_CRD=$(MCAD_CRD) + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + git restore config/* + +.PHONY: undeploy +undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. + $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f - + +##@ Build Dependencies + +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +## Tool Binaries +KUSTOMIZE ?= $(LOCALBIN)/kustomize +APPLYCONFIGURATION_GEN ?= $(LOCALBIN)/applyconfiguration-gen +CLIENT_GEN ?= $(LOCALBIN)/client-gen +LISTER_GEN ?= $(LOCALBIN)/lister-gen +INFORMER_GEN ?= $(LOCALBIN)/informer-gen +CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen +ENVTEST ?= $(LOCALBIN)/setup-envtest +OPENSHIFT-GOIMPORTS ?= $(LOCALBIN)/openshift-goimports +OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk +GH_CLI ?= $(LOCALBIN)/gh + +## Tool Versions +KUSTOMIZE_VERSION ?= v4.5.4 +CODEGEN_VERSION ?= v0.27.2 +CONTROLLER_TOOLS_VERSION ?= v0.9.2 +OPERATOR_SDK_VERSION ?= v1.27.0 +GH_CLI_VERSION ?= 2.30.0 + +KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" +.PHONY: kustomize +kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. +$(KUSTOMIZE): $(LOCALBIN) + test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } + +GH_CLI_DL_URL := https://github.com/cli/cli/releases/download/v$(GH_CLI_VERSION) +GH_CLI_DL_FILENAME := gh_$(GH_CLI_VERSION)_$(shell go env GOOS)_$(shell go env GOARCH) +.PHONY: install-gh-cli +install-gh-cli: $(GH_CLI) +$(GH_CLI): $(LOCALBIN) + curl -L $(GH_CLI_DL_URL)/$(GH_CLI_DL_FILENAME).tar.gz --output $(GH_CLI_DL_FILENAME).tar.gz + tar -xvzf $(GH_CLI_DL_FILENAME).tar.gz + cp $(GH_CLI_DL_FILENAME)/bin/gh $(GH_CLI) + rm -rf $(GH_CLI_DL_FILENAME) + rm $(GH_CLI_DL_FILENAME).tar.gz + +.PHONY: code-generator +code-generator: $(APPLYCONFIGURATION_GEN) $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN) + +.PHONY: applyconfiguration-gen +applyconfiguration-gen: $(APPLYCONFIGURATION_GEN) +$(APPLYCONFIGURATION_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/applyconfiguration-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/applyconfiguration-gen@$(CODEGEN_VERSION) + +.PHONY: client-gen +client-gen: $(CLIENT_GEN) +$(CLIENT_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/client-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/client-gen@$(CODEGEN_VERSION) + +.PHONY: lister-gen +lister-gen: $(LISTER_GEN) +$(LISTER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/lister-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/lister-gen@$(CODEGEN_VERSION) + +.PHONY: informer-gen +informer-gen: $(INFORMER_GEN) +$(INFORMER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/informer-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/informer-gen@$(CODEGEN_VERSION) + +.PHONY: controller-gen +controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. +$(CONTROLLER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) + +.PHONY: envtest +envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. +$(ENVTEST): $(LOCALBIN) + test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest + +.PHONY: openshift-goimports +openshift-goimports: $(OPENSHIFT-GOIMPORTS) ## Download openshift-goimports locally if necessary. +$(OPENSHIFT-GOIMPORTS): $(LOCALBIN) + test -s $(LOCALBIN)/openshift-goimports || GOBIN=$(LOCALBIN) go install github.com/openshift-eng/openshift-goimports@latest + +OPERATOR_SDK_DL_URL := https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION) +.PHONY: install-operator-sdk +install-operator-sdk: $(OPERATOR_SDK) ## Download fixed version operator-sdk binary for consist outcome +$(OPERATOR_SDK): $(LOCALBIN) + curl -L $(OPERATOR_SDK_DL_URL)/operator-sdk_$(shell go env GOOS)_$(shell go env GOARCH) --output $(LOCALBIN)/operator-sdk + chmod +x $(OPERATOR_SDK) + +.PHONY: validate-bundle +validate-bundle: install-operator-sdk + $(OPERATOR_SDK) bundle validate ./bundle --select-optional suite=operatorframework + +.PHONY: bundle +bundle: defaults manifests kustomize install-operator-sdk ## Generate bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests -q + $(KUSTOMIZE) fn run config/crd/mcad --image gcr.io/kpt-fn/apply-setters:v0.2.0 -- MCAD_CRD=$(MCAD_CRD) + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + cd config/manifests && $(KUSTOMIZE) edit add patch --patch '[{"op":"add", "path":"/metadata/annotations/containerImage", "value": "$(IMG)" }]' --kind ClusterServiceVersion + cd config/manifests && $(KUSTOMIZE) edit add patch --patch '[{"op":"add", "path":"/spec/replaces", "value": "codeflare-operator.$(PREVIOUS_VERSION)" }]' --kind ClusterServiceVersion + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + $(MAKE) validate-bundle + git restore config/* + +.PHONY: bundle-build +bundle-build: bundle ## Build the bundle image. + podman build -f bundle.Dockerfile -t $(BUNDLE_IMG) . + +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + podman push $(BUNDLE_IMG) $(BUNDLE_PUSH_OPT) + +.PHONY: openshift-community-operator-release +openshift-community-operator-release: install-gh-cli bundle ## build bundle and create PR in OpenShift community operators repository + git clone https://x-access-token:$(GH_TOKEN)@github.com/$(OPERATORS_REPO_FORK_ORG)/community-operators-prod.git + cd community-operators-prod && git remote add upstream https://github.com/$(OPERATORS_REPO_ORG)/community-operators-prod.git && git pull upstream main && git push origin main + cp -r bundle community-operators-prod/operators/codeflare-operator/$(BUNDLE_VERSION) + cd community-operators-prod && git checkout -b codeflare-release-$(BUNDLE_VERSION) && git add operators/codeflare-operator/$(BUNDLE_VERSION)/* && git commit -m "add bundle manifests codeflare version $(BUNDLE_VERSION)" --signoff && git push origin codeflare-release-$(BUNDLE_VERSION) + gh pr create --repo $(OPERATORS_REPO_ORG)/community-operators-prod --title "CodeFlare $(BUNDLE_VERSION)" --body "New release of codeflare operator" --head $(OPERATORS_REPO_FORK_ORG):codeflare-release-$(BUNDLE_VERSION) --base main + rm -rf community-operators-prod + +.PHONY: opm +OPM = ./bin/opm +opm: ## Download opm locally if necessary. +ifeq (,$(wildcard $(OPM))) +ifeq (,$(shell which opm 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(OPM)) ;\ + OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ + curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\ + chmod +x $(OPM) ;\ + } +else +OPM = $(shell which opm) +endif +endif + +# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). +# These images MUST exist in a registry and be pull-able. +BUNDLE_IMGS ?= $(BUNDLE_IMG) + +# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). +CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:$(VERSION) + +# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. +ifneq ($(origin CATALOG_BASE_IMG), undefined) +FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) +endif + +# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. +# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: +# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator +.PHONY: catalog-build +catalog-build: opm ## Build a catalog image. + $(OPM) index add --container-tool podman --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) + +# Build a catalog image by adding bundle images to existing catalog using the operator package manager tool, 'opm'. +.PHONY: catalog-build-from-index +catalog-build-from-index: opm ## Build a catalog image. + mkdir catalog + $(OPM) render $(CATALOG_BASE_IMG) -o yaml > catalog/bundles.yaml + $(OPM) render $(BUNDLE_IMG) $(OPM_BUNDLE_OPT) > catalog/codeflare-operator-bundle.yaml + sed -i -E "s/(.*)(- name: codeflare-operator.$(PREVIOUS_VERSION).*)/\1- name: codeflare-operator.$(VERSION)\n replaces: codeflare-operator.$(PREVIOUS_VERSION)\n\2/" catalog/bundles.yaml + $(OPM) validate catalog + $(OPM) generate dockerfile catalog + podman build . -f catalog.Dockerfile -t $(CATALOG_IMG) + +# Push the catalog image. +.PHONY: catalog-push +catalog-push: ## Push a catalog image. + podman push $(CATALOG_IMG) $(CATALOG_PUSH_OPT) + +.PHONY: test-unit +test-unit: defaults manifests generate fmt vet envtest ## Run unit tests. + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $(go list ./... | grep -v /test/) -coverprofile cover.out + +.PHONY: test-e2e +test-e2e: ## Run e2e tests. + go test -timeout 30m -v ./tests/e2e -run TestMNISTRayClusterSDK + +.PHONY: kind-e2e +kind-e2e: ## Set up e2e KinD cluster. + tests/e2e/kind.sh + +.PHONY: setup-e2e +setup-e2e: ## Set up e2e tests. + KUBERAY_VERSION=$(KUBERAY_VERSION) tests/e2e/setup.sh + +.PHONY: imports +imports: openshift-goimports ## Organize imports in go files using openshift-goimports. Example: make imports + $(OPENSHIFT-GOIMPORTS) + +.PHONY: verify-imports +verify-imports: openshift-goimports ## Run import verifications. + ./hack/verify-imports.sh $(OPENSHIFT-GOIMPORTS) diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..5d37ffccf --- /dev/null +++ b/go.mod @@ -0,0 +1,56 @@ +module github.com/project-codeflare/codeflare-sdk + +go 1.19 + +require ( + github.com/onsi/gomega v1.27.10 + github.com/project-codeflare/codeflare-operator v0.1.0 + github.com/project-codeflare/multi-cluster-app-dispatcher v1.33.0 + github.com/ray-project/kuberay/ray-operator v0.0.0-20230813033553-4892ac1094e7 + k8s.io/api v0.26.3 + k8s.io/apimachinery v0.26.3 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openshift/api v0.0.0-20230213134911-7ba313770556 // indirect + github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/client-go v0.26.3 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect + sigs.k8s.io/controller-runtime v0.14.6 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 000000000..c1d8a2436 --- /dev/null +++ b/go.sum @@ -0,0 +1,498 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +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.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +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/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +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= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/openshift/api v0.0.0-20230213134911-7ba313770556 h1:7W2fOhJicyEff24VaF7ASNzPtYvr+iSCVft4SIBAzaE= +github.com/openshift/api v0.0.0-20230213134911-7ba313770556/go.mod h1:aQ6LDasvHMvHZXqLHnX2GRmnfTWCF/iIwz8EMTTIE9A= +github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c h1:CV76yFOTXmq9VciBR3Bve5ZWzSxdft7gaMVB3kS0rwg= +github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c/go.mod h1:lFMO8mLHXWFzSdYvGNo8ivF9SfF6zInA8ZGw4phRnUE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/project-codeflare/codeflare-operator v0.1.0 h1:1CWC0osxabJSP/fMH/SqmME3PFke7tkWgOYR9fV4beU= +github.com/project-codeflare/codeflare-operator v0.1.0/go.mod h1:aj/Tm9HiEQ6Qcb1Jgvc5RHwwiSryLYYWAY/55sZ56wI= +github.com/project-codeflare/multi-cluster-app-dispatcher v1.33.0 h1:6a+MnxcFSlheC7RIPGg3s/QCt5+7dD8mJKwdpST7i70= +github.com/project-codeflare/multi-cluster-app-dispatcher v1.33.0/go.mod h1:0J0BDSaIN5lvlmgw+32FcMqe8SflXHtHByUbHmPl4w8= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/ray-project/kuberay/ray-operator v0.0.0-20230813033553-4892ac1094e7 h1:n1KkXM5ZJ6MQ72hE8wTch2k/bZAw0dffqGcU7ethTLs= +github.com/ray-project/kuberay/ray-operator v0.0.0-20230813033553-4892ac1094e7/go.mod h1:hqphTv0O5l6hHf4/OtEn4ie/OHPoVydLograwaK5cHI= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +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 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +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.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +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= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +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.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +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= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +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= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +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.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= +k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= +k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +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/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= +k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA= +sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pyproject.toml b/pyproject.toml index 6f8393ef2..2eb947ab9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ python = "^3.7" openshift-client = "1.0.18" rich = "^12.5" ray = {version = "2.5.0", extras = ["default"]} -kubernetes = ">= 25.3.0, < 27" +kubernetes = "11.0.0" codeflare-torchx = "0.6.0.dev0" cryptography = "40.0.2" executing = "1.2.0" diff --git a/tests/e2e/codeflare_sdk-0.0.0.dev0-py3-none-any.whl b/tests/e2e/codeflare_sdk-0.0.0.dev0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..62ac97f8a701d1a12a47a740dd6788a1b248e772 GIT binary patch literal 32670 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 timeout: + raise TimeoutError(f"job has timed out after waiting {timeout}s") + sleep(5) + time += 5 + +print(f"Job has completed: {status.state}") + +print(job.logs()) + +cluster.down() + +if not status.state == AppState.SUCCEEDED: + exit(1) +else: + exit(0) diff --git a/tests/e2e/mnist_raycluster_sdk_test.go b/tests/e2e/mnist_raycluster_sdk_test.go new file mode 100644 index 000000000..e8c76f903 --- /dev/null +++ b/tests/e2e/mnist_raycluster_sdk_test.go @@ -0,0 +1,214 @@ +/* +Copyright 2023. + +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 e2e + +import ( + "testing" + + . "github.com/onsi/gomega" + mcadv1beta1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1" + rayv1alpha1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1alpha1" + + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + . "github.com/project-codeflare/codeflare-operator/test/support" +) + +// Creates a Ray cluster, and trains the MNIST dataset using the CodeFlare SDK. +// Asserts successful completion of the training job. +// +// This covers the installation of the CodeFlare SDK, as well as the RBAC required +// for the SDK to successfully perform requests to the cluster, on behalf of the +// impersonated user. +func TestMNISTRayClusterSDK(t *testing.T) { + test := With(t) + test.T().Parallel() + + // if !IsOpenShift(test) { + // test.T().Skip("Requires https://github.com/project-codeflare/codeflare-sdk/pull/146") + // } + + // // Currently blocked by https://github.com/project-codeflare/codeflare-sdk/pull/271 , remove the skip once SDK with the PR is released + // test.T().Skip("Requires https://github.com/project-codeflare/codeflare-sdk/pull/271") + + // Create a namespace + namespace := test.NewTestNamespace() + + // Test configuration + config := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "mnist-raycluster-sdk", + Namespace: namespace.Name, + }, + BinaryData: map[string][]byte{ + // SDK script + "mnist_raycluster_sdk.py": ReadFile(test, "mnist_raycluster_sdk.py"), + // pip requirements + "requirements.txt": ReadFile(test, "mnist_pip_requirements.txt"), + // MNIST training script + "mnist.py": ReadFile(test, "mnist.py"), + // SDK Wheel File + "codeflare_sdk-0.0.0.dev0-py3-none-any.whl": ReadWhlFile(test, "codeflare_sdk-0.0.0.dev0-py3-none-any.whl"), + }, + Immutable: Ptr(true), + } + config, err := test.Client().Core().CoreV1().ConfigMaps(namespace.Name).Create(test.Ctx(), config, metav1.CreateOptions{}) + test.Expect(err).NotTo(HaveOccurred()) + test.T().Logf("Created ConfigMap %s/%s successfully", config.Namespace, config.Name) + + // SDK client RBAC + serviceAccount := &corev1.ServiceAccount{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "ServiceAccount", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sdk-user", + Namespace: namespace.Name, + }, + } + serviceAccount, err = test.Client().Core().CoreV1().ServiceAccounts(namespace.Name).Create(test.Ctx(), serviceAccount, metav1.CreateOptions{}) + test.Expect(err).NotTo(HaveOccurred()) + + role := &rbacv1.Role{ + TypeMeta: metav1.TypeMeta{ + APIVersion: rbacv1.SchemeGroupVersion.String(), + Kind: "Role", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sdk", + Namespace: namespace.Name, + }, + Rules: []rbacv1.PolicyRule{ + { + Verbs: []string{"get", "create", "delete", "list", "patch", "update"}, + APIGroups: []string{mcadv1beta1.GroupName}, + Resources: []string{"appwrappers"}, + }, + { + Verbs: []string{"get", "list"}, + APIGroups: []string{rayv1alpha1.GroupVersion.Group}, + Resources: []string{"rayclusters", "rayclusters/status"}, + }, + { + Verbs: []string{"get", "list"}, + APIGroups: []string{"route.openshift.io"}, + Resources: []string{"routes"}, + }, + }, + } + role, err = test.Client().Core().RbacV1().Roles(namespace.Name).Create(test.Ctx(), role, metav1.CreateOptions{}) + test.Expect(err).NotTo(HaveOccurred()) + + roleBinding := &rbacv1.RoleBinding{ + TypeMeta: metav1.TypeMeta{ + APIVersion: rbacv1.SchemeGroupVersion.String(), + Kind: "RoleBinding", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sdk", + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.SchemeGroupVersion.Group, + Kind: "Role", + Name: role.Name, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + APIGroup: corev1.SchemeGroupVersion.Group, + Name: serviceAccount.Name, + Namespace: serviceAccount.Namespace, + }, + }, + } + _, err = test.Client().Core().RbacV1().RoleBindings(namespace.Name).Create(test.Ctx(), roleBinding, metav1.CreateOptions{}) + test.Expect(err).NotTo(HaveOccurred()) + + job := &batchv1.Job{ + TypeMeta: metav1.TypeMeta{ + APIVersion: batchv1.SchemeGroupVersion.String(), + Kind: "Job", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sdk", + Namespace: namespace.Name, + }, + Spec: batchv1.JobSpec{ + Completions: Ptr(int32(1)), + Parallelism: Ptr(int32(1)), + BackoffLimit: Ptr(int32(0)), + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + // FIXME: switch to base Python image once the dependency on OpenShift CLI is removed + // See https://github.com/project-codeflare/codeflare-sdk/pull/146 + Image: "quay.io/opendatahub/notebooks:jupyter-minimal-ubi8-python-3.8-4c8f26e", + Command: []string{"/bin/sh", "-c", "pip install /test/codeflare_sdk-0.0.0.dev0-py3-none-any.whl && cp /test/* . && python mnist_raycluster_sdk.py" + " " + namespace.Name}, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "test", + MountPath: "/test", + }, + }, + }, + }, + Volumes: []corev1.Volume{ + { + Name: "test", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: config.Name, + }, + }, + }, + }, + }, + RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: serviceAccount.Name, + }, + }, + }, + } + job, err = test.Client().Core().BatchV1().Jobs(namespace.Name).Create(test.Ctx(), job, metav1.CreateOptions{}) + test.Expect(err).NotTo(HaveOccurred()) + test.T().Logf("Created Job %s/%s successfully", job.Namespace, job.Name) + + // Retrieving the job logs once it has completed or timed out + defer WriteJobLogs(test, job.Namespace, job.Name) + + test.T().Logf("Waiting for Job %s/%s to complete", job.Namespace, job.Name) + test.Eventually(Job(test, job.Namespace, job.Name), TestTimeoutLong).Should( + Or( + WithTransform(ConditionStatus(batchv1.JobComplete), Equal(corev1.ConditionTrue)), + WithTransform(ConditionStatus(batchv1.JobFailed), Equal(corev1.ConditionTrue)), + )) + + // Assert the job has completed successfully + test.Expect(GetJob(test, job.Namespace, job.Name)). + To(WithTransform(ConditionStatus(batchv1.JobComplete), Equal(corev1.ConditionTrue))) +} diff --git a/tests/e2e/setup.sh b/tests/e2e/setup.sh new file mode 100755 index 000000000..dbc973dd2 --- /dev/null +++ b/tests/e2e/setup.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Copyright 2022 IBM, Red Hat +# +# 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 -euo pipefail +: "${KUBERAY_VERSION}" + +echo Deploying KubeRay "${KUBERAY_VERSION}" +kubectl apply --server-side -k "github.com/ray-project/kuberay/ray-operator/config/default?ref=${KUBERAY_VERSION}&timeout=90s" + +kubectl create ns codeflare-system --dry-run=client -o yaml | kubectl apply -f - + +echo Deploying MCAD controller +cat <