From 9051b1f2f77a57407bf346eefec80089fc501268 Mon Sep 17 00:00:00 2001 From: Pavan <25031267+Pavan-SAP@users.noreply.github.com> Date: Wed, 6 Sep 2023 09:54:08 +0200 Subject: [PATCH] [GEN] OperatorManager regenerated (#3) * [GEN] OperatorManager regenerated - Regenerate code of CAP Operator Manager using latest `scaffolder`. - Fix/cleanup/update overall code. - Update to the latest version of `Go` dependencies. Change-Id: I24c6b54bba6697dd9c1c6891858da1689c1d7885 * switched to transformer and removed manifest pkg * default subdomain change to cap-op * Depenencies tidied Change-Id: I25b80908d30cf4cb2e270da537a2320e0945d5a1 --------- Co-authored-by: i325261 --- .project | 19 +++ .vscode/launch.json | 7 +- Dockerfile | 7 +- Makefile | 135 +++++++--------- api/v1alpha1/groupversion_info.go | 12 +- api/v1alpha1/status.go | 38 ----- api/v1alpha1/zz_generated.deepcopy.go | 16 -- .../operator_v1alpha1_capoperator.yaml | 2 +- go.mod | 34 ++-- go.sum | 76 ++++----- hack/genclient.sh | 49 ++++++ .../transformer/transformer.go | 76 ++++----- .../transformer/transformer_test.go | 92 ++--------- main.go | 112 ++++++++------ pkg/manifests/types.go | 16 -- pkg/operator/operator.go | 146 ++++++++++++++++++ pkg/operator/operator_test.go | 30 ++++ 17 files changed, 471 insertions(+), 396 deletions(-) create mode 100644 .project delete mode 100644 api/v1alpha1/status.go create mode 100644 hack/genclient.sh rename pkg/manifests/helm.go => internal/transformer/transformer.go (72%) rename pkg/manifests/helm_test.go => internal/transformer/transformer_test.go (53%) delete mode 100644 pkg/manifests/types.go create mode 100644 pkg/operator/operator.go create mode 100644 pkg/operator/operator_test.go diff --git a/.project b/.project new file mode 100644 index 0000000..46f7e55 --- /dev/null +++ b/.project @@ -0,0 +1,19 @@ +admissionWebhookRuntimeVersion: v0.1.0 +codeGeneratorVersion: v0.28.1 +controllerRuntimeVersion: v0.16.0 +controllerToolsVersion: v0.13.0 +envtestKubernetesVersion: 1.27.1 +goModule: github.com/sap/cap-operator-lifecycle +goVersion: "1.21" +groupName: operator.sme.sap.com +groupVersion: v1alpha1 +image: cap-operator-manager:latest +kind: CAPOperator +kubernetesVersion: v0.28.1 +mutatingWebhookEnabled: false +operatorName: cap-operator.sme.sap.com +owner: SAP SE +resource: capoperators +spdxLicenseHeaders: false +validatingWebhookEnabled: false +version: v0.1.9 diff --git a/.vscode/launch.json b/.vscode/launch.json index d4c8c3d..4bbaf46 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,11 +5,14 @@ "version": "0.2.0", "configurations": [ { - "name": "Launch Controller", + "name": "Launch Operator", "type": "go", "request": "launch", "mode": "auto", - "program": "main.go" + "program": "main.go", + "env": { + "POD_NAMESPACE": "cap-operator-system" + } } ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d075314..1669da5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,16 +5,17 @@ ARG TARGETARCH ENV CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} WORKDIR /workspace -# Copy the Go Modules manifests +# Copy the go module manifests COPY go.mod go.mod COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much +# Cache deps before building and copying source so that we don't need to re-download as much # and so that source changes don't invalidate our downloaded layer RUN go mod download -# Copy the go source +# Copy the go sources COPY main.go main.go COPY api/ api/ +COPY internal/ internal/ COPY pkg/ pkg/ # Build diff --git a/Makefile b/Makefile index dcb8c20..f1c4b9c 100644 --- a/Makefile +++ b/Makefile @@ -1,37 +1,17 @@ - # Image URL to use all building/pushing image targets -IMG ?= controller:latest -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.26.1 - -# 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 +IMG ?= cap-operator-manager:latest +# K8s version used by envtest +ENVTEST_K8S_VERSION = 1.27.1 + +# Set shell to bash +SHELL = /usr/bin/env bash +.SHELLFLAGS = -o pipefail -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) @@ -39,13 +19,17 @@ help: ## Display this help. ##@ Development .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 +manifests: controller-gen ## Generate ClusterRole & CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd paths="./..." output:crd:artifacts:config=config/crd .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: client-gen informer-gen lister-gen ## Generate typed client. + ./hack/genclient.sh + .PHONY: fmt fmt: ## Run go fmt against code. go fmt ./... @@ -54,9 +38,11 @@ fmt: ## Run go fmt against code. vet: ## Run go vet against code. go vet ./... +##@ Testing + .PHONY: test test: manifests generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out + KUBEBUILDER_ASSETS="$(LOCALBIN)/k8s/current" go test ./... -coverprofile cover.out ##@ Build @@ -68,56 +54,24 @@ build: generate fmt vet ## Build manager binary. run: manifests generate fmt vet ## Run a controller from your host. go run ./main.go -# If you wish built the manager image targeting other platforms you can use the --platform flag. -# (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it. -# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +# Build docker image in current architecture and tag it as ${IMG}. .PHONY: docker-build -docker-build: test ## Build docker image with the manager. +docker-build: ## Build docker image with the manager. docker build -t ${IMG} . +# Push docker image to the target specified in ${IMG}. .PHONY: docker-push docker-push: ## Push docker image with the manager. docker push ${IMG} -# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ -# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> than the export will fail) -# To properly provided solutions that supports more than one platform you should use this option. +# Build and push docker image for all given platforms. PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le .PHONY: docker-buildx -docker-buildx: test ## Build and push docker image for the manager for cross-platform support - # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile - sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross +docker-buildx: ## Build and push docker image for the manager for cross-platform support. - docker buildx create --name project-v3-builder docker buildx use project-v3-builder - - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross + - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} . - docker buildx rm project-v3-builder - rm Dockerfile.cross - -##@ 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) build config/crd | kubectl apply -f - - -.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. - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl apply -f - - -.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 @@ -127,26 +81,45 @@ $(LOCALBIN): mkdir -p $(LOCALBIN) ## Tool Binaries -KUSTOMIZE ?= $(LOCALBIN)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest +CLIENT_GEN ?= $(LOCALBIN)/client-gen +INFORMER_GEN ?= $(LOCALBIN)/informer-gen +LISTER_GEN ?= $(LOCALBIN)/lister-gen +SETUP_ENVTEST ?= $(LOCALBIN)/setup-envtest ## Tool Versions -KUSTOMIZE_VERSION ?= v4.5.5 -CONTROLLER_TOOLS_VERSION ?= v0.9.2 - -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 -Ss $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } +CONTROLLER_TOOLS_VERSION ?= v0.13.0 +CODE_GENERATOR_VERSION ?= v0.28.1 +SETUP_ENVTEST_VERSION ?= latest .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: client-gen +client-gen: $(CLIENT_GEN) ## Download client-gen locally if necessary. +$(CLIENT_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/client-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/client-gen@$(CODE_GENERATOR_VERSION) + +.PHONY: informer-gen +informer-gen: $(INFORMER_GEN) ## Download informer-gen locally if necessary. +$(INFORMER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/informer-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/informer-gen@$(CODE_GENERATOR_VERSION) + +.PHONY: lister-gen +lister-gen: $(LISTER_GEN) ## Download lister-gen locally if necessary. +$(LISTER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/lister-gen || GOBIN=$(LOCALBIN) go install k8s.io/code-generator/cmd/lister-gen@$(CODE_GENERATOR_VERSION) + +.PHONY: setup-envtest +setup-envtest: $(SETUP_ENVTEST) ## Download setup-envtest locally if necessary. +$(SETUP_ENVTEST): $(LOCALBIN) + test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(SETUP_ENVTEST_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 +envtest: setup-envtest + ENVTESTDIR=$$($(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path) ;\ + chmod -R u+w $$ENVTESTDIR ;\ + rm -f $(LOCALBIN)/k8s/current ;\ + ln -s $$ENVTESTDIR $(LOCALBIN)/k8s/current diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go index cfbf3ad..a8a960d 100644 --- a/api/v1alpha1/groupversion_info.go +++ b/api/v1alpha1/groupversion_info.go @@ -14,12 +14,20 @@ import ( ) var ( - // GroupVersion is group version used to register these objects + // GroupVersion is group version used to register these objects. GroupVersion = schema.GroupVersion{Group: "operator.sme.sap.com", Version: "v1alpha1"} - // SchemeBuilder is used to add go types to the GroupVersionKind scheme + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme + + // Needed by kubernetes/code-generator. + SchemeGroupVersion = GroupVersion ) + +// Needed by kubernetes/code-generator. +func Resource(resource string) schema.GroupResource { + return GroupVersion.WithResource(resource).GroupResource() +} diff --git a/api/v1alpha1/status.go b/api/v1alpha1/status.go deleted file mode 100644 index 5e32cb7..0000000 --- a/api/v1alpha1/status.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator contributors -SPDX-License-Identifier: Apache-2.0 -*/ - -package v1alpha1 - -type State string - -// Valid Module CR States. -const ( - // StateReady signifies Module CR is Ready and has been installed successfully. - StateReady State = "Ready" - - // StateProcessing signifies Module CR is reconciling and is in the process of installation. - // Processing can also signal that the Installation previously encountered an error and is now recovering. - StateProcessing State = "Processing" - - // StateError signifies an error for Module CR. This signifies that the Installation - // process encountered an error. - // Contrary to Processing, it can be expected that this state should change on the next retry. - StateError State = "Error" - - // StateDeleting signifies Module CR is being deleted. This is the state that is used - // when a deletionTimestamp was detected and Finalizers are picked up. - StateDeleting State = "Deleting" -) - -// +k8s:deepcopy-gen=true - -// Status defines the observed state of Module CR. -type Status struct { - // State signifies current state of Module CR. - // Value can be one of ("Ready", "Processing", "Error", "Deleting"). - // +kubebuilder:validation:Required - // +kubebuilder:validation:Enum=Processing;Deleting;Ready;Error - State State `json:"state"` -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index fe9a65b..5c4b21c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator-lifecycle contributors @@ -121,21 +120,6 @@ func (in *IngressGatewayLabels) DeepCopy() *IngressGatewayLabels { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Status) DeepCopyInto(out *Status) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. -func (in *Status) DeepCopy() *Status { - if in == nil { - return nil - } - out := new(Status) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionServer) DeepCopyInto(out *SubscriptionServer) { *out = *in diff --git a/config/samples/operator_v1alpha1_capoperator.yaml b/config/samples/operator_v1alpha1_capoperator.yaml index 11d3f3c..ad9e559 100644 --- a/config/samples/operator_v1alpha1_capoperator.yaml +++ b/config/samples/operator_v1alpha1_capoperator.yaml @@ -9,7 +9,7 @@ metadata: name: cap-operator spec: subscriptionServer: - subDomain: cop + subDomain: cap-op ingressGatewayLabels: istio: ingressgateway app: istio-ingressgateway diff --git a/go.mod b/go.mod index d94e896..cf1ba69 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/sap/cap-operator-lifecycle go 1.21 require ( - github.com/sap/component-operator-runtime v0.1.6 - golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb - k8s.io/api v0.28.0 - k8s.io/apiextensions-apiserver v0.28.0 - k8s.io/apimachinery v0.28.0 - k8s.io/client-go v0.28.0 - k8s.io/kube-aggregator v0.28.0 - sigs.k8s.io/controller-runtime v0.15.1 + github.com/pkg/errors v0.9.1 + github.com/sap/component-operator-runtime v0.1.9 + k8s.io/api v0.28.1 + k8s.io/apiextensions-apiserver v0.28.1 + k8s.io/apimachinery v0.28.1 + k8s.io/client-go v0.28.1 + k8s.io/kube-aggregator v0.28.1 + sigs.k8s.io/controller-runtime v0.16.1 ) require ( @@ -20,7 +20,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -37,7 +37,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/huandu/xstrings v1.4.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -50,7 +50,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -60,15 +59,16 @@ require ( github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.starlark.net v0.0.0-20230814145427-12f4cb8177e4 // indirect + go.starlark.net v0.0.0-20230831151029-c9e9adf3fde2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/crypto v0.12.0 // indirect + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/net v0.14.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/term v0.11.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -76,9 +76,9 @@ require ( 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/component-base v0.28.0 // indirect + k8s.io/component-base v0.28.1 // indirect k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 // indirect + k8s.io/kube-openapi v0.0.0-20230901164831-6c774f458599 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/cli-utils v0.35.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 1d620d2..d76291b 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 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/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= -github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= @@ -89,8 +89,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= @@ -131,10 +131,10 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= 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/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= -github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= 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= @@ -151,8 +151,8 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/sap/component-operator-runtime v0.1.6 h1:uJQ0zj4vNJbjQBOi0aiiKmCeePySpFbA42tX2c+4HmQ= -github.com/sap/component-operator-runtime v0.1.6/go.mod h1:5cMR7EGRQBv+/dhzNDiKTibvklTyZVYTfSbuone8edk= +github.com/sap/component-operator-runtime v0.1.9 h1:fn3UuS+nD3WnEeNK4HgFjCGGSqQb5XITZxVE5rhVPgM= +github.com/sap/component-operator-runtime v0.1.9/go.mod h1:GyPbB0Cmk3CbVpkv8BW+1Rrh/BlmrWnZAP6xfUmckAI= github.com/sap/go-generics v0.1.1 h1:3T4McSGF5epH8Yp4bbxD07oa5J0pH7Nfx4r4zwdsr4o= github.com/sap/go-generics v0.1.1/go.mod h1:8L5jyDKi/FHKG/R+qwyy9h1TymA7XO5YSu+J/27gTCg= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= @@ -184,8 +184,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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= -go.starlark.net v0.0.0-20230814145427-12f4cb8177e4 h1:Ydko8M6UfXgvSpGOnbAjRMQDIvBheUsjBjkm6Azcpf4= -go.starlark.net v0.0.0-20230814145427-12f4cb8177e4/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= +go.starlark.net v0.0.0-20230831151029-c9e9adf3fde2 h1:JVsWByUy+MOggHrZ2zLfLUBOcinE2w18iSbLb7WAAIc= +go.starlark.net v0.0.0-20230831151029-c9e9adf3fde2/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -204,8 +204,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4 golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA= -golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -253,21 +253,21 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.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/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.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= @@ -280,8 +280,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= 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= @@ -326,28 +326,28 @@ 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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.28.0 h1:3j3VPWmN9tTDI68NETBWlDiA9qOiGJ7sdKeufehBYsM= -k8s.io/api v0.28.0/go.mod h1:0l8NZJzB0i/etuWnIXcwfIv+xnDOhL3lLW919AWYDuY= -k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= -k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= -k8s.io/apimachinery v0.28.0 h1:ScHS2AG16UlYWk63r46oU3D5y54T53cVI5mMJwwqFNA= -k8s.io/apimachinery v0.28.0/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= -k8s.io/client-go v0.28.0 h1:ebcPRDZsCjpj62+cMk1eGNX1QkMdRmQ6lmz5BLoFWeM= -k8s.io/client-go v0.28.0/go.mod h1:0Asy9Xt3U98RypWJmU1ZrRAGKhP6NqDPmptlAzK2kMc= -k8s.io/component-base v0.28.0 h1:HQKy1enJrOeJlTlN4a6dU09wtmXaUvThC0irImfqyxI= -k8s.io/component-base v0.28.0/go.mod h1:Yyf3+ZypLfMydVzuLBqJ5V7Kx6WwDr/5cN+dFjw1FNk= +k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= +k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/apiextensions-apiserver v0.28.1 h1:l2ThkBRjrWpw4f24uq0Da2HaEgqJZ7pcgiEUTKSmQZw= +k8s.io/apiextensions-apiserver v0.28.1/go.mod h1:sVvrI+P4vxh2YBBcm8n2ThjNyzU4BQGilCQ/JAY5kGs= +k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= +k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= +k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= +k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= +k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= +k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= 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-aggregator v0.28.0 h1:8uH1SoRLlDdhdaW64eAK1BDWUXr2jLtVhiShysTzcok= -k8s.io/kube-aggregator v0.28.0/go.mod h1:wD7UarSU4HRyeDUIZLEHpvXNqL613w59yaM7ctjYapA= -k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 h1:CAIciCnJnSOQxPd0xvpV6JU3D4AJvnYbImPpFpO9Hnw= -k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/kube-aggregator v0.28.1 h1:rvG4llYnQKHjj6YjjoBPEJxfD1uH0DJwkrJTNKGAaCs= +k8s.io/kube-aggregator v0.28.1/go.mod h1:JaLizMe+AECSpO2OmrWVsvnG0V3dX1RpW+Wq/QHbu18= +k8s.io/kube-openapi v0.0.0-20230901164831-6c774f458599 h1:nVKRi5eItf3x9kkIMfdT4D1/LqPzj0bLjxLYWbdUtV0= +k8s.io/kube-openapi v0.0.0-20230901164831-6c774f458599/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/cli-utils v0.35.0 h1:dfSJaF1W0frW74PtjwiyoB4cwdRygbHnC7qe7HF0g/Y= sigs.k8s.io/cli-utils v0.35.0/go.mod h1:ITitykCJxP1vaj1Cew/FZEaVJ2YsTN9Q71m02jebkoE= -sigs.k8s.io/controller-runtime v0.15.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c= -sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/controller-runtime v0.16.1 h1:+15lzrmHsE0s2kNl0Dl8cTchI5Cs8qofo5PGcPrV9z0= +sigs.k8s.io/controller-runtime v0.16.1/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= 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/kustomize/api v0.14.0 h1:6+QLmXXA8X4eDM7ejeaNUyruA1DDB3PVIjbpVhDOJRA= diff --git a/hack/genclient.sh b/hack/genclient.sh new file mode 100644 index 0000000..0dc0d5b --- /dev/null +++ b/hack/genclient.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +set -eo pipefail + +export GOROOT=$(go env GOROOT) + +BASEDIR=$(realpath $(dirname "$0")/..) +TEMPDIR=$BASEDIR/tmp/gen +trap 'rm -rf "$TEMPDIR"' EXIT +mkdir -p "$TEMPDIR" + +mkdir -p "$TEMPDIR"/apis +ln -s "$BASEDIR"/api/v1alpha1 "$TEMPDIR"/apis/v1alpha1 + +"$BASEDIR"/bin/client-gen \ + --clientset-name versioned \ + --input-base "" \ + --input github.com/sap/cap-operator-lifecycle/tmp/gen/apis/v1alpha1 \ + --go-header-file "$BASEDIR"/hack/boilerplate.go.txt \ + --output-package github.com/sap/cap-operator-lifecycle/pkg/client/clientset \ + --output-base "$TEMPDIR"/pkg/client \ + --plural-exceptions CAPOperator:capoperators + +"$BASEDIR"/bin/lister-gen \ + --input-dirs github.com/sap/cap-operator-lifecycle/tmp/gen/apis/v1alpha1 \ + --go-header-file "$BASEDIR"/hack/boilerplate.go.txt \ + --output-package github.com/sap/cap-operator-lifecycle/pkg/client/listers \ + --output-base "$TEMPDIR"/pkg/client \ + --plural-exceptions CAPOperator:capoperators + +"$BASEDIR"/bin/informer-gen \ + --input-dirs github.com/sap/cap-operator-lifecycle/tmp/gen/apis/v1alpha1 \ + --versioned-clientset-package github.com/sap/cap-operator-lifecycle/pkg/client/clientset/versioned \ + --listers-package github.com/sap/cap-operator-lifecycle/pkg/client/listers \ + --go-header-file "$BASEDIR"/hack/boilerplate.go.txt \ + --output-package github.com/sap/cap-operator-lifecycle/pkg/client/informers \ + --output-base "$TEMPDIR"/pkg/client \ + --plural-exceptions CAPOperator:capoperators + +find "$TEMPDIR"/pkg/client -name "*.go" -exec \ + perl -pi -e "s#github\.com/sap/cap-operator-lifecycle/tmp/gen/apis/operator\.kyma-project\.io/v1alpha1#github.com/sap/cap-operator-lifecycle/api/v1alpha1#g" \ + {} + + +rm -rf "$BASEDIR"/pkg/client +mv "$TEMPDIR"/pkg/client/github.com/sap/cap-operator-lifecycle/pkg/client "$BASEDIR"/pkg + +cd "$BASEDIR" +go fmt ./pkg/client/... +go vet ./pkg/client/... diff --git a/pkg/manifests/helm.go b/internal/transformer/transformer.go similarity index 72% rename from pkg/manifests/helm.go rename to internal/transformer/transformer.go index a3b5b15..03de176 100644 --- a/pkg/manifests/helm.go +++ b/internal/transformer/transformer.go @@ -3,27 +3,21 @@ SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator SPDX-License-Identifier: Apache-2.0 */ -package manifests +package transformer import ( "context" "fmt" - "io/fs" "strings" - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/sap/component-operator-runtime/pkg/manifests" - "github.com/sap/component-operator-runtime/pkg/types" - - "github.com/sap/cap-operator-lifecycle/api/v1alpha1" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" apitypes "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/discovery" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/sap/cap-operator-lifecycle/api/v1alpha1" + componentoperatorruntimetypes "github.com/sap/component-operator-runtime/pkg/types" ) const ( @@ -33,42 +27,26 @@ const ( annotationDNSNames = "dns.gardener.cloud/dnsnames" ) -type HelmGenerator struct { - resourceGenerator *manifests.HelmGenerator - client client.Client +type transformer struct { + client client.Client } -type unstructurableMap struct { - data map[string]any -} - -func (m *unstructurableMap) ToUnstructured() map[string]any { - return runtime.DeepCopyJSON(m.data) -} - -var _ Generator = &HelmGenerator{} - -func NewHelmGenerator(name string, fsys fs.FS, chartPath string, client client.Client, discoveryClient discovery.DiscoveryInterface) (*HelmGenerator, error) { - resourceGenerator, err := manifests.NewHelmGenerator(name, fsys, chartPath, client, discoveryClient) - if err != nil { - return nil, err - } - g := HelmGenerator{resourceGenerator: resourceGenerator, client: client} - return &g, nil +func NewParameterTransformer(client client.Client) *transformer { + return &transformer{client: client} } -func (g *HelmGenerator) Generate(namespace string, name string, parameters types.Unstructurable) ([]client.Object, error) { +func (t *transformer) TransformParameters(namespace string, name string, parameters componentoperatorruntimetypes.Unstructurable) (componentoperatorruntimetypes.Unstructurable, error) { parameterMap := parameters.ToUnstructured() - if err := g.fillDomain(parameterMap); err != nil { + if err := t.fillDomain(parameterMap); err != nil { return nil, err } - if err := g.fillDNSTarget(parameterMap); err != nil { + if err := t.fillDNSTarget(parameterMap); err != nil { return nil, err } - return g.resourceGenerator.Generate(namespace, name, &unstructurableMap{data: parameterMap}) + return componentoperatorruntimetypes.UnstructurableMap(parameterMap), nil } func trimDNSTarget(dnsTarget string) string { @@ -80,7 +58,7 @@ func trimDNSTarget(dnsTarget string) string { return strings.ReplaceAll(dnsTarget, "*", "x") } -func (g *HelmGenerator) fillDNSTarget(parameters map[string]any) error { +func (t *transformer) fillDNSTarget(parameters map[string]any) error { // get DNSTarget subscriptionServer := parameters["subscriptionServer"].(map[string]interface{}) if subscriptionServer["dnsTarget"] != nil { // already filled in CRO @@ -98,7 +76,7 @@ func (g *HelmGenerator) fillDNSTarget(parameters map[string]any) error { return fmt.Errorf("cannot get dnsTarget; provide ingressGatewayLabels/app and ingressGatewayLabels/istio values in the CRO") } - dnsTarget, err := g.getDNSTarget(&v1alpha1.IngressGatewayLabels{App: ingressGatewayLabels["app"].(string), Istio: ingressGatewayLabels["istio"].(string)}) + dnsTarget, err := t.getDNSTarget(&v1alpha1.IngressGatewayLabels{App: ingressGatewayLabels["app"].(string), Istio: ingressGatewayLabels["istio"].(string)}) if err != nil { return err } @@ -108,7 +86,7 @@ func (g *HelmGenerator) fillDNSTarget(parameters map[string]any) error { return nil } -func (g *HelmGenerator) getDNSTarget(ingressGatewayLabels *v1alpha1.IngressGatewayLabels) (dnsTarget string, err error) { +func (t *transformer) getDNSTarget(ingressGatewayLabels *v1alpha1.IngressGatewayLabels) (dnsTarget string, err error) { ctx := context.TODO() @@ -120,7 +98,7 @@ func (g *HelmGenerator) getDNSTarget(ingressGatewayLabels *v1alpha1.IngressGatew // Get relevant Ingress Gateway pods ingressPods := &corev1.PodList{TypeMeta: metav1.TypeMeta{Kind: "Pod"}} - err = g.client.List(ctx, ingressPods, &client.ListOptions{Namespace: metav1.NamespaceAll, LabelSelector: ingressLabelSelector}) + err = t.client.List(ctx, ingressPods, &client.ListOptions{Namespace: metav1.NamespaceAll, LabelSelector: ingressLabelSelector}) if err != nil { return "", err } @@ -143,7 +121,7 @@ func (g *HelmGenerator) getDNSTarget(ingressGatewayLabels *v1alpha1.IngressGatew } // Get dnsTarget - ingressGWSvc, err := g.getIngressGatewayService(ctx, relevantsPodsNames) + ingressGWSvc, err := t.getIngressGatewayService(ctx, relevantsPodsNames) if err != nil { return "", err } @@ -169,10 +147,10 @@ func getIngressGatewayLabels(ingressGatewayLabels *v1alpha1.IngressGatewayLabels return ingressLabels } -func (g *HelmGenerator) getLoadBalancerSvcs(ctx context.Context) ([]corev1.Service, error) { +func (t *transformer) getLoadBalancerSvcs(ctx context.Context) ([]corev1.Service, error) { // List all services in the same namespace as the istio-ingressgateway pod namespace svcList := &corev1.ServiceList{TypeMeta: metav1.TypeMeta{Kind: "Service"}} - if err := g.client.List(ctx, svcList, &client.ListOptions{Namespace: istioIngressGWNamespace}); err != nil { + if err := t.client.List(ctx, svcList, &client.ListOptions{Namespace: istioIngressGWNamespace}); err != nil { return nil, err } @@ -186,8 +164,8 @@ func (g *HelmGenerator) getLoadBalancerSvcs(ctx context.Context) ([]corev1.Servi return loadBalancerSvcs, nil } -func (g *HelmGenerator) getIngressGatewayService(ctx context.Context, relevantPodNames map[string]struct{}) (*corev1.Service, error) { - loadBalancerSvcs, err := g.getLoadBalancerSvcs(ctx) +func (t *transformer) getIngressGatewayService(ctx context.Context, relevantPodNames map[string]struct{}) (*corev1.Service, error) { + loadBalancerSvcs, err := t.getLoadBalancerSvcs(ctx) if err != nil { return nil, err } @@ -196,7 +174,7 @@ func (g *HelmGenerator) getIngressGatewayService(ctx context.Context, relevantPo podList := &corev1.PodList{TypeMeta: metav1.TypeMeta{Kind: "Pod"}} for _, svc := range loadBalancerSvcs { // Get all matching ingress GW pods in the ingress gw namespace via ingress gw service selectors - err := g.client.List(ctx, podList, &client.ListOptions{LabelSelector: labels.SelectorFromValidatedSet(svc.Spec.Selector)}) + err := t.client.List(ctx, podList, &client.ListOptions{LabelSelector: labels.SelectorFromValidatedSet(svc.Spec.Selector)}) if err != nil { return nil, err } @@ -219,10 +197,10 @@ func (g *HelmGenerator) getIngressGatewayService(ctx context.Context, relevantPo return &ingressGwSvc, nil } -func (g *HelmGenerator) fillDomain(parameters map[string]any) error { +func (t *transformer) fillDomain(parameters map[string]any) error { // get domain subscriptionServer := parameters["subscriptionServer"].(map[string]interface{}) - domain, err := g.getDomain(subscriptionServer["subDomain"].(string)) + domain, err := t.getDomain(subscriptionServer["subDomain"].(string)) if err != nil { return err } @@ -233,7 +211,7 @@ func (g *HelmGenerator) fillDomain(parameters map[string]any) error { return nil } -func (g *HelmGenerator) getDomain(subDomain string) (string, error) { +func (t *transformer) getDomain(subDomain string) (string, error) { configMapObj := &corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{ Kind: "ConfigMap", @@ -248,7 +226,7 @@ func (g *HelmGenerator) getDomain(subDomain string) (string, error) { } ctx := context.TODO() - err := g.client.Get(ctx, apitypes.NamespacedName{Namespace: configMapObj.GetNamespace(), Name: configMapObj.GetName()}, configMapObj) + err := t.client.Get(ctx, apitypes.NamespacedName{Namespace: configMapObj.GetNamespace(), Name: configMapObj.GetName()}, configMapObj) if err != nil { return "", err } diff --git a/pkg/manifests/helm_test.go b/internal/transformer/transformer_test.go similarity index 53% rename from pkg/manifests/helm_test.go rename to internal/transformer/transformer_test.go index 8d93b9c..0e3094c 100644 --- a/pkg/manifests/helm_test.go +++ b/internal/transformer/transformer_test.go @@ -2,28 +2,18 @@ SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator contributors SPDX-License-Identifier: Apache-2.0 */ -package manifests +package transformer import ( "testing" - "golang.org/x/exp/slices" + componentoperatorruntimetypes "github.com/sap/component-operator-runtime/pkg/types" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" fake "sigs.k8s.io/controller-runtime/pkg/client/fake" - - fakediscovery "k8s.io/client-go/discovery/fake" - fakeclientset "k8s.io/client-go/kubernetes/fake" ) -func ContainsFunc(clientObjects []client.Object, name string, kind string) bool { - return slices.ContainsFunc(clientObjects, func(object client.Object) bool { - return object.GetName() == name && object.GetObjectKind().GroupVersionKind().Kind == kind - }) -} - -func TestHelmResourceGenerator(t *testing.T) { +func TestTransformer(t *testing.T) { tests := []struct { name string dnsTargetFilled bool @@ -96,48 +86,7 @@ func TestHelmResourceGenerator(t *testing.T) { kubeClient := clientBuilder.Build() - fakeclientset := fakeclientset.NewSimpleClientset() - fakeDiscovery, ok := fakeclientset.Discovery().(*fakediscovery.FakeDiscovery) - if !ok { - t.Error("fake discovery client creation failed") - } - fakeDiscovery.Resources = []*metav1.APIResourceList{ - { - GroupVersion: "cert.gardener.cloud/v1alpha1", - TypeMeta: metav1.TypeMeta{ - Kind: "APIResourceList", - APIVersion: "v1", - }, - APIResources: []metav1.APIResource{ - { - Name: "certificates", - SingularName: "certificate", - Namespaced: true, - Kind: "Certificate", - }, - }, - }, - { - GroupVersion: "dns.gardener.cloud/v1alpha1", - TypeMeta: metav1.TypeMeta{ - Kind: "APIResourceList", - APIVersion: "v1", - }, - APIResources: []metav1.APIResource{ - { - Name: "dnsentries", - SingularName: "dnsentry", - Namespaced: true, - Kind: "DNSEntry", - }, - }, - }, - } - - helmGenerator, err := NewHelmGenerator("cap-operator.sme.sap.com", nil, "../../chart", kubeClient, fakeDiscovery) - if err != nil { - t.Error(err) - } + transformer := NewParameterTransformer(kubeClient) parameter := make(map[string]interface{}) @@ -157,7 +106,7 @@ func TestHelmResourceGenerator(t *testing.T) { } } - clientObjects, err := helmGenerator.Generate("cap-operator-system", "cap-operator", &unstructurableMap{parameter}) + transformedParameters, err := transformer.TransformParameters("cap-operator-system", "cap-operator.sme.sap.com", componentoperatorruntimetypes.UnstructurableMap(parameter)) if !tt.expectError && err != nil { t.Error(err) } @@ -170,33 +119,12 @@ func TestHelmResourceGenerator(t *testing.T) { t.Log(err) return } - - if len(clientObjects) != 24 { - t.Error("wrong number of returned client objects") - } - - if !ContainsFunc(clientObjects, "cap-operator-controller", "Deployment") { - t.Error("controller deployment not found") - } - - if !ContainsFunc(clientObjects, "cap-operator-subscription-server", "Deployment") { - t.Error("subscription-server deployment not found") - } - - if !ContainsFunc(clientObjects, "cap-operator-webhook", "Deployment") { - t.Error("webhook deployment not found") - } - - if !ContainsFunc(clientObjects, "cap-operator-subscription-server", "VirtualService") { - t.Error("virutal service not found") - } - - if !ContainsFunc(clientObjects, "cap-operator-subscription-server", "Gateway") { - t.Error("gateway not found") + transformedParametersMap := transformedParameters.ToUnstructured() + if transformedParametersMap["subscriptionServer"].(map[string]interface{})["dnsTarget"].(string) != "public-ingress.some.cluster.sap" { + t.Error("unexpected value returned") } - - if !ContainsFunc(clientObjects, "cap-operator-subscription-server", "DNSEntry") { - t.Error("DNSEntry not found") + if transformedParametersMap["subscriptionServer"].(map[string]interface{})["domain"].(string) != "cop.some.cluster.sap" { + t.Error("unexpected value returned") } }) } diff --git a/main.go b/main.go index 26491ba..9ee27c2 100644 --- a/main.go +++ b/main.go @@ -19,29 +19,21 @@ package main import ( "flag" - "fmt" "os" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - - "k8s.io/client-go/discovery" - _ "k8s.io/client-go/plugin/pkg/client/auth" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/discovery" clientgoscheme "k8s.io/client-go/kubernetes/scheme" apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - operatorv1alpha1 "github.com/sap/cap-operator-lifecycle/api/v1alpha1" - "github.com/sap/cap-operator-lifecycle/pkg/manifests" - "github.com/sap/component-operator-runtime/pkg/component" - //+kubebuilder:scaffold:imports + "github.com/sap/cap-operator-lifecycle/pkg/operator" ) var ( @@ -53,15 +45,16 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(apiextensionsv1.AddToScheme(scheme)) utilruntime.Must(apiregistrationv1.AddToScheme(scheme)) - utilruntime.Must(operatorv1alpha1.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme -} -const myself = "cap-operator.sme.sap.com" + operator.InitScheme(scheme) +} func main() { var metricsAddr string var probeAddr string + // Uncomment the following lines to enable webhooks. + // var webhookAddr string + // var webhookCertDir string var enableLeaderElection bool var chartDir string @@ -69,11 +62,16 @@ func main() { "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + // Uncomment the following lines to enable webhooks. + // flag.StringVar(&webhookAddr, "webhook-bind-address", ":2443", + // "The address the webhooks endpoint binds to.") + // flag.StringVar(&webhookCertDir, "webhook-tls-directory", "", + // "The directory containing tls server key and certificate, as tls.key and tls.crt; defaults to $TMPDIR/k8s-webhook-server/serving-certs") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") flag.StringVar(&chartDir, "manifest-directory", "./chart", "The directory containing the deployment manifests for the managed operator.") - + operator.InitFlags(flag.CommandLine) opts := zap.Options{ Development: false, } @@ -87,49 +85,59 @@ func main() { os.Exit(1) } - if err := checkDirectoryExists(chartDir); err != nil { - setupLog.Error(err, "error checking manifest directory") - os.Exit(1) - } + // Uncomment the following lines to enable webhooks. + // webhookHost, webhookPort, err := parseAddress(webhookAddr) + // if err != nil { + // setupLog.Error(err, "error parsing webhook address") + // os.Exit(1) + // } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - HealthProbeBindAddress: probeAddr, + Scheme: scheme, + Client: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: append(operator.GetUncacheableTypes(), &apiextensionsv1.CustomResourceDefinition{}, &apiregistrationv1.APIService{}), + }, + }, LeaderElection: enableLeaderElection, - LeaderElectionID: myself, + LeaderElectionID: operator.GetName(), LeaderElectionReleaseOnCancel: true, - ClientDisableCacheFor: []client.Object{&operatorv1alpha1.CAPOperator{}, &apiextensionsv1.CustomResourceDefinition{}, &apiregistrationv1.APIService{}}, + // Uncomment the following lines to enable webhooks. + // WebhookServer: webhook.NewServer(webhook.Options{ + // Host: webhookHost, + // Port: webhookPort, + // CertDir: webhookCertDir, + // }), + Metrics: metricsserver.Options{ + BindAddress: metricsAddr, + }, + HealthProbeBindAddress: probeAddr, }) if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1) } + // Uncomment to enable conversion webhook (in case additional api versions are added in ./api). + // Note: to make conversion work, additional changes are necessary: + // - additional api versions have to be added to InitScheme() in pkg/operator/operator.go + // - one of the api versions has to marked as Hub, all other versions need to implement the + // conversion.Convertible interface (see https://book.kubebuilder.io/multiversion-tutorial/conversion.html) + // - one of the api versions has to be marked as storage version (+kubebuilder:storageversion) + // - the crd resource has to be enhanced with a conversion section, telling the Kubernetes API server how to + // connect to the conversion endpoint. + // mgr.GetWebhookServer().Register("/convert", conversion.NewWebhookHandler(mgr.GetScheme())) + discoveryClient, err := discovery.NewDiscoveryClientForConfig(mgr.GetConfig()) if err != nil { setupLog.Error(err, "error creating discovery client") os.Exit(1) } - resourceGenerator, err := manifests.NewHelmGenerator(myself, nil, chartDir, mgr.GetClient(), discoveryClient) - if err != nil { - setupLog.Error(err, "error initializing manifest generator") - os.Exit(1) - } - - if err := component.NewReconciler[*operatorv1alpha1.CAPOperator]( - myself, - mgr.GetClient(), - discoveryClient, - mgr.GetEventRecorderFor(myself), - mgr.GetScheme(), - resourceGenerator, - ).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "CAPOperatorManager") + if err := operator.Setup(mgr, discoveryClient); err != nil { + setupLog.Error(err, "error registering controller with manager") os.Exit(1) } - //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { setupLog.Error(err, "unable to set up health check") @@ -147,13 +155,15 @@ func main() { } } -func checkDirectoryExists(path string) error { - fsinfo, err := os.Stat(path) - if err != nil { - return err - } - if !fsinfo.IsDir() { - return fmt.Errorf("not a directory: %s", path) - } - return nil -} +// Uncomment the following lines to enable webhooks. +// func parseAddress(address string) (string, int, error) { +// host, p, err := net.SplitHostPort(address) +// if err != nil { +// return "", -1, err +// } +// port, err := strconv.Atoi(p) +// if err != nil { +// return "", -1, err +// } +// return host, port, nil +// } diff --git a/pkg/manifests/types.go b/pkg/manifests/types.go deleted file mode 100644 index 1a6d622..0000000 --- a/pkg/manifests/types.go +++ /dev/null @@ -1,16 +0,0 @@ -/* -SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator contributors -SPDX-License-Identifier: Apache-2.0 -*/ - -package manifests - -import ( - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/sap/component-operator-runtime/pkg/types" -) - -type Generator interface { - Generate(string, string, types.Unstructurable) ([]client.Object, error) -} diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go new file mode 100644 index 0000000..fc7effd --- /dev/null +++ b/pkg/operator/operator.go @@ -0,0 +1,146 @@ +/* +SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator contributors +SPDX-License-Identifier: Apache-2.0 +*/ + +package operator + +import ( + "flag" + "os" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/discovery" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/sap/component-operator-runtime/pkg/component" + "github.com/sap/component-operator-runtime/pkg/manifests" + "github.com/sap/component-operator-runtime/pkg/operator" + + operatorv1alpha1 "github.com/sap/cap-operator-lifecycle/api/v1alpha1" + "github.com/sap/cap-operator-lifecycle/internal/transformer" +) + +const Name = "cap-operator.sme.sap.com" +const FlagPrefix = "manifest-directory" + +type Options struct { + Name string + FlagPrefix string +} + +type Operator struct { + options Options +} + +var defaultOperator operator.Operator = New() + +func GetName() string { + return defaultOperator.GetName() +} + +func InitScheme(scheme *runtime.Scheme) { + defaultOperator.InitScheme(scheme) +} + +func InitFlags(flagset *flag.FlagSet) { + defaultOperator.InitFlags(flagset) +} + +func ValidateFlags() error { + return defaultOperator.ValidateFlags() +} + +func GetUncacheableTypes() []client.Object { + return defaultOperator.GetUncacheableTypes() +} + +func Setup(mgr ctrl.Manager, discoveryClient discovery.DiscoveryInterface) error { + return defaultOperator.Setup(mgr, discoveryClient) +} + +func New() *Operator { + return NewWithOptions(Options{}) +} + +func NewWithOptions(options Options) *Operator { + operator := &Operator{options: options} + if operator.options.Name == "" { + operator.options.Name = Name + } + if operator.options.FlagPrefix == "" { + operator.options.FlagPrefix = FlagPrefix + } + return operator +} + +func (o *Operator) GetName() string { + return o.options.Name +} + +func (o *Operator) InitScheme(scheme *runtime.Scheme) { + utilruntime.Must(operatorv1alpha1.AddToScheme(scheme)) +} + +var chartFlag *flag.Flag + +func (o *Operator) InitFlags(flagset *flag.FlagSet) { + chartFlag = flagset.Lookup(o.options.FlagPrefix) +} + +func (o *Operator) ValidateFlags() error { + // Add logic to validate flags (if running in a combined controller you might want to evaluate o.options.FlagPrefix). + return nil +} + +func (o *Operator) GetUncacheableTypes() []client.Object { + // Add types which should bypass informer caching. + return []client.Object{&operatorv1alpha1.CAPOperator{}} +} + +func (o *Operator) Setup(mgr ctrl.Manager, discoveryClient discovery.DiscoveryInterface) error { + chartDir := chartFlag.Value.String() + + if err := checkDirectoryExists(chartDir); err != nil { + return errors.Wrap(err, "error checking manifest directory") + } + + resourceGenerator, err := manifests.NewHelmGeneratorWithParameterTransformer( + o.options.Name, + nil, + chartDir, + mgr.GetClient(), + discoveryClient, + transformer.NewParameterTransformer(mgr.GetClient()), + ) + if err != nil { + return errors.Wrap(err, "error initializing resource generator") + } + + if err := component.NewReconciler[*operatorv1alpha1.CAPOperator]( + o.options.Name, + mgr.GetClient(), + discoveryClient, + mgr.GetEventRecorderFor(o.options.Name), + mgr.GetScheme(), + resourceGenerator, + ).SetupWithManager(mgr); err != nil { + return errors.Wrapf(err, "unable to create controller") + } + + return nil +} + +func checkDirectoryExists(path string) error { + fsinfo, err := os.Stat(path) + if err != nil { + return err + } + if !fsinfo.IsDir() { + return errors.Errorf("not a directory: %s", path) + } + return nil +} diff --git a/pkg/operator/operator_test.go b/pkg/operator/operator_test.go new file mode 100644 index 0000000..74f7d89 --- /dev/null +++ b/pkg/operator/operator_test.go @@ -0,0 +1,30 @@ +/* +SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and cap-operator contributors +SPDX-License-Identifier: Apache-2.0 +*/ +package operator + +import ( + "testing" +) + +func TestCheckDirectoryExists(t *testing.T) { + + // invalid directory + if err := checkDirectoryExists("invalid"); err == nil { + t.Error("error expected but not returned") + return + } + + // valid directory + if err := checkDirectoryExists("../../chart"); err != nil { + t.Error("error not expected but returned") + return + } + + // File path passed instead of a directory + if err := checkDirectoryExists("../../chart/values.yaml"); err == nil { + t.Error("error expected but not returned") + return + } +}