diff --git a/.gitignore b/.gitignore index 1d922612db..113edc01e9 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,8 @@ atlassian-ide-plugin.xml ## VSCode -.vscode +**/*.vscode +**/*.devcontainer* ### OSX template *.DS_Store @@ -90,5 +91,8 @@ out.txt **/go.work **/go.work.sum +# ignore .pem key files +**/*.pem + # rendered manifest **/manifest.yaml \ No newline at end of file diff --git a/operator/Dockerfile b/operator/Dockerfile index 1827964d16..b461176871 100644 --- a/operator/Dockerfile +++ b/operator/Dockerfile @@ -23,7 +23,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go FROM gcr.io/distroless/static:nonroot WORKDIR / COPY --from=builder /workspace/manager . -COPY --from=builder /workspace/internal/charts/skr-webhook ./skr-webhook +COPY charts/skr-webhook charts/skr-webhook USER 65532:65532 ENTRYPOINT ["/manager"] diff --git a/operator/api/v1alpha1/condition_builder.go b/operator/api/v1alpha1/condition_builder.go index 4f28c88fa6..38c3a81123 100644 --- a/operator/api/v1alpha1/condition_builder.go +++ b/operator/api/v1alpha1/condition_builder.go @@ -17,6 +17,15 @@ const ( MessageModuleNotInReadyState = "not all modules are in ready state" MessageModuleCatalogIsSynced = "module catalog is synchronized" MessageModuleCatalogIsOutOfSync = "module catalog is out of sync and needs to be resynchronized" + MessageSKRWebhookIsSynced = "skrwebhook is synchronized" + MessageSKRWebhookIsOutOfSync = "skrwebhook is out of sync and needs to be resynchronized" +) + +// Extend this list by actual needs. +const ( + ConditionReasonModulesAreReady KymaConditionReason = "ModulesAreReady" + ConditionReasonModuleCatalogIsReady KymaConditionReason = "ModuleCatalogIsReady" + ConditionReasonSKRWebhookIsReady KymaConditionReason = "SKRWebhookIsReady" ) func NewConditionBuilder() *ConditionBuilder { @@ -69,6 +78,15 @@ func (cb *ConditionBuilder) generateMessage() string { } return MessageModuleCatalogIsOutOfSync + case ConditionReasonSKRWebhookIsReady: + switch cb.Status { + case metav1.ConditionTrue: + return MessageSKRWebhookIsSynced + case metav1.ConditionUnknown: + case metav1.ConditionFalse: + } + + return MessageSKRWebhookIsOutOfSync } return "no detailed message available as reason is unknown to API" diff --git a/operator/api/v1alpha1/kyma_types.go b/operator/api/v1alpha1/kyma_types.go index a94865339d..df0b653682 100644 --- a/operator/api/v1alpha1/kyma_types.go +++ b/operator/api/v1alpha1/kyma_types.go @@ -249,12 +249,6 @@ const ( // and the actual state of individual module can be found in related ModuleStatus. type KymaConditionReason string -// Extend this list by actual needs. -const ( - ConditionReasonModulesAreReady KymaConditionReason = "ModulesAreReady" - ConditionReasonModuleCatalogIsReady KymaConditionReason = "ModuleCatalogIsReady" -) - //+genclient //+kubebuilder:object:root=true //+kubebuilder:subresource:status diff --git a/operator/api/v1alpha1/watcher_types.go b/operator/api/v1alpha1/watcher_types.go index 8159d7cac1..94a3007fe0 100644 --- a/operator/api/v1alpha1/watcher_types.go +++ b/operator/api/v1alpha1/watcher_types.go @@ -17,8 +17,6 @@ limitations under the License. package v1alpha1 import ( - "time" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -143,8 +141,6 @@ const ( ) //+kubebuilder:object:root=true -//+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="State",type=string,JSONPath=".status.state" //+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // Watcher is the Schema for the watchers API. @@ -156,14 +152,6 @@ type Watcher struct { // +kubebuilder:validation:Optional Spec WatcherSpec `json:"spec"` - - // +kubebuilder:validation:Optional - Status WatcherStatus `json:"status"` -} - -func (w *Watcher) SetObservedGeneration() *Watcher { - w.Status.ObservedGeneration = w.Generation - return w } func (w *Watcher) GetModuleName() string { @@ -173,25 +161,6 @@ func (w *Watcher) GetModuleName() string { return w.Labels[ManagedBylabel] } -func (w *Watcher) AddOrUpdateReadyCondition(state WatcherConditionStatus, msg string) { - lastTransitionTime := &metav1.Time{Time: time.Now()} - if len(w.Status.Conditions) == 0 { - w.Status.Conditions = []WatcherCondition{{ - Type: WatcherConditionTypeReady, - Status: state, - Message: msg, - LastTransitionTime: lastTransitionTime, - }} - } - for i := range w.Status.Conditions { - condition := &w.Status.Conditions[i] - if condition.Type == WatcherConditionTypeReady { - condition.Status = state - condition.LastTransitionTime = lastTransitionTime - } - } -} - //+kubebuilder:object:root=true // WatcherList contains a list of Watcher. diff --git a/operator/api/v1alpha1/zz_generated.deepcopy.go b/operator/api/v1alpha1/zz_generated.deepcopy.go index 67c4ae8182..0999345668 100644 --- a/operator/api/v1alpha1/zz_generated.deepcopy.go +++ b/operator/api/v1alpha1/zz_generated.deepcopy.go @@ -372,7 +372,6 @@ func (in *Watcher) DeepCopyInto(out *Watcher) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Watcher. diff --git a/operator/internal/charts/skr-webhook/.helmignore b/operator/charts/skr-webhook/.helmignore similarity index 100% rename from operator/internal/charts/skr-webhook/.helmignore rename to operator/charts/skr-webhook/.helmignore diff --git a/operator/internal/charts/skr-webhook/Chart.yaml b/operator/charts/skr-webhook/Chart.yaml similarity index 100% rename from operator/internal/charts/skr-webhook/Chart.yaml rename to operator/charts/skr-webhook/Chart.yaml diff --git a/operator/internal/charts/skr-webhook/templates/deployment.yaml b/operator/charts/skr-webhook/templates/deployment.yaml similarity index 97% rename from operator/internal/charts/skr-webhook/templates/deployment.yaml rename to operator/charts/skr-webhook/templates/deployment.yaml index cfd0210abc..c71c8b44a8 100644 --- a/operator/internal/charts/skr-webhook/templates/deployment.yaml +++ b/operator/charts/skr-webhook/templates/deployment.yaml @@ -30,6 +30,7 @@ spec: metadata: labels: app: skr-webhook + operator.kyma-project.io/pod-restart-trigger: "{{.Values.triggerLabel}}" spec: serviceAccountName: {{.Release.Name}}-webhook-sa containers: diff --git a/operator/internal/charts/skr-webhook/templates/rbac.yaml b/operator/charts/skr-webhook/templates/rbac.yaml similarity index 100% rename from operator/internal/charts/skr-webhook/templates/rbac.yaml rename to operator/charts/skr-webhook/templates/rbac.yaml diff --git a/operator/internal/charts/skr-webhook/templates/secret.yaml b/operator/charts/skr-webhook/templates/secret.yaml similarity index 88% rename from operator/internal/charts/skr-webhook/templates/secret.yaml rename to operator/charts/skr-webhook/templates/secret.yaml index bef891897b..d7cdd711f7 100644 --- a/operator/internal/charts/skr-webhook/templates/secret.yaml +++ b/operator/charts/skr-webhook/templates/secret.yaml @@ -6,11 +6,6 @@ type: Opaque data: {{- $caCert := "" }} {{- if .Values.tls.helmCertGen }} - {{- $data := (lookup "v1" "Secret" .Release.Namespace (printf "%s-webhook-tls" .Release.Name )).data }} - {{- if $data }} - {{ $data | toYaml | nindent 2 }} - {{- $caCert = index $data "ca.crt" }} - {{- else }} {{- $cn := printf "%s-webhook.%s.svc" .Release.Name .Release.Namespace }} {{- $ca := genCA (printf "%s-webhook-ca" .Release.Name ) 36500 }} {{- $cert := genSignedCert $cn (list "127.0.0.1") (list $cn "localhost") 36500 $ca }} @@ -18,7 +13,6 @@ data: tls.crt: {{ $cert.Cert | b64enc }} tls.key: {{ $cert.Key | b64enc }} {{- $caCert = $ca.Cert | b64enc }} - {{- end }} {{- else }} ca.crt: {{.Values.tls.caCert}} tls.crt: {{.Values.tls.clientCert }} diff --git a/operator/internal/charts/skr-webhook/values.yaml b/operator/charts/skr-webhook/values.yaml similarity index 97% rename from operator/internal/charts/skr-webhook/values.yaml rename to operator/charts/skr-webhook/values.yaml index a567882e61..f466eba21b 100644 --- a/operator/internal/charts/skr-webhook/values.yaml +++ b/operator/charts/skr-webhook/values.yaml @@ -2,6 +2,8 @@ sidecar: true # -- Replicas replicas: 1 +# -- Trigger pod restart +triggerLabel: "" image: # -- Image repository repository: "eu.gcr.io/kyma-project" diff --git a/operator/config/crd/bases/operator.kyma-project.io_watchers.yaml b/operator/config/crd/bases/operator.kyma-project.io_watchers.yaml index c72c2ed3aa..c7fe661722 100644 --- a/operator/config/crd/bases/operator.kyma-project.io_watchers.yaml +++ b/operator/config/crd/bases/operator.kyma-project.io_watchers.yaml @@ -16,9 +16,6 @@ spec: scope: Namespaced versions: - additionalPrinterColumns: - - jsonPath: .status.state - name: State - type: string - jsonPath: .metadata.creationTimestamp name: Age type: date @@ -78,67 +75,7 @@ spec: - labelsToWatch - serviceInfo type: object - status: - description: WatcherStatus defines the observed state of Watcher. - properties: - conditions: - description: List of status conditions to indicate the status of a - Watcher. - items: - description: WatcherCondition describes condition information for - Watcher. - properties: - lastTransitionTime: - description: Timestamp for when Watcher last transitioned from - one status to another. - format: date-time - type: string - message: - description: Human-readable message indicating details about - the last status transition. - type: string - reason: - description: Machine-readable text indicating the reason for - the condition's last transition. - type: string - status: - description: Status of the Watcher Condition. Value can be one - of ("True", "False", "Unknown"). - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: Type is used to reflect what type of condition - we are dealing with. Most commonly WatcherConditionTypeReady - it is used as extension marker in the future. - enum: - - Ready - type: string - required: - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration - format: int64 - type: integer - state: - description: State signifies current state of a Watcher. Value can - be one of ("Ready", "Processing", "Error", "Deleting") - enum: - - Processing - - Deleting - - Ready - - Error - type: string - required: - - state - type: object type: object served: true storage: true - subresources: - status: {} + subresources: {} diff --git a/operator/config/watcher/kustomization.yaml b/operator/config/watcher/kustomization.yaml index 18a0e32f39..30d3a216f7 100644 --- a/operator/config/watcher/kustomization.yaml +++ b/operator/config/watcher/kustomization.yaml @@ -11,7 +11,7 @@ patches: - patch: |- - op: add path: /spec/template/spec/containers/0/args/- - value: --enable-kcp-watcher=false + value: --enable-kcp-watcher - op: add path: /spec/template/spec/containers/0/args/- value: --skr-watcher-path=/skr-webhook diff --git a/operator/controllers/kyma_controller.go b/operator/controllers/kyma_controller.go index f047e25128..6b068139e1 100644 --- a/operator/controllers/kyma_controller.go +++ b/operator/controllers/kyma_controller.go @@ -18,9 +18,16 @@ package controllers import ( "context" + "errors" "fmt" "time" + "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + "k8s.io/client-go/rest" + + manifestV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" "github.com/kyma-project/lifecycle-manager/operator/pkg/adapter" "github.com/kyma-project/lifecycle-manager/operator/pkg/catalog" @@ -31,8 +38,6 @@ import ( "github.com/kyma-project/lifecycle-manager/operator/pkg/remote" "github.com/kyma-project/lifecycle-manager/operator/pkg/signature" "github.com/kyma-project/lifecycle-manager/operator/pkg/status" - manifestV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" @@ -45,6 +50,8 @@ type EventErrorType string const ModuleReconciliationError EventErrorType = "ModuleReconciliationError" +var ErrSkrChartConfigNotSet = errors.New("skr chart config is not set") + type RequeueIntervals struct { Success time.Duration } @@ -56,6 +63,8 @@ type KymaReconciler struct { RequeueIntervals signature.VerificationSettings RemoteClientCache *remote.ClientCache + deploy.SKRWebhookChartManager + KcpRestConfig *rest.Config } //nolint:lll @@ -248,7 +257,14 @@ func (r *KymaReconciler) HandleProcessingState(ctx context.Context, kyma *v1alph return r.UpdateStatusWithEventFromErr(ctx, kyma, v1alpha1.StateError, fmt.Errorf("error while syncing conditions during deleting non exists modules: %w", err)) } - + statusUpdateRequiredFromSKRWebhookSync := false + if kyma.Spec.Sync.Enabled { + if statusUpdateRequiredFromSKRWebhookSync, err = r.InstallWebhookChart(ctx, kyma, + r.RemoteClientCache, r.Client); err != nil { + kyma.UpdateCondition(v1alpha1.ConditionReasonSKRWebhookIsReady, metav1.ConditionFalse) + return err + } + } kyma.SyncConditionsWithModuleStates() // set ready condition if applicable if kyma.AreAllConditionsReadyForKyma() && kyma.Status.State != v1alpha1.StateReady { @@ -258,10 +274,10 @@ func (r *KymaReconciler) HandleProcessingState(ctx context.Context, kyma *v1alph return r.UpdateStatusWithEvent(ctx, kyma, v1alpha1.StateReady, message) } + isStatusUpdateRequired := statusUpdateRequiredFromModuleSync || statusUpdateRequiredFromModuleStatusSync || + statusUpdateRequiredFromDeletion || statusUpdateRequiredFromSKRWebhookSync // if the ready condition is not applicable, but we changed the conditions, we still need to issue an update - if statusUpdateRequiredFromModuleSync || - statusUpdateRequiredFromModuleStatusSync || - statusUpdateRequiredFromDeletion { + if isStatusUpdateRequired { if err := r.UpdateStatusWithEvent(ctx, kyma, v1alpha1.StateProcessing, "updating component conditions"); err != nil { return fmt.Errorf("error while updating status for condition change: %w", err) } @@ -279,6 +295,9 @@ func (r *KymaReconciler) HandleDeletingState(ctx context.Context, kyma *v1alpha1 if err != nil { return false, fmt.Errorf("remote sync initialization failed: %w", err) } + if err = r.RemoveWebhookChart(ctx, kyma, syncContext); err != nil { + return true, nil + } force := true if err := catalog.NewRemoteCatalog( syncContext, catalog.Settings{ diff --git a/operator/controllers/kyma_controller_helper_test.go b/operator/controllers/kyma_controller_helper_test.go index dcb5c9bd36..a019e12b70 100644 --- a/operator/controllers/kyma_controller_helper_test.go +++ b/operator/controllers/kyma_controller_helper_test.go @@ -4,7 +4,8 @@ import ( "encoding/json" "errors" "fmt" - "math/rand" + + . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" ocm "github.com/gardener/component-spec/bindings-go/apis/v2" . "github.com/onsi/ginkgo/v2" @@ -24,61 +25,14 @@ import ( manifestV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" ) -func NewTestKyma(name string) *v1alpha1.Kyma { - return &v1alpha1.Kyma{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1alpha1.GroupVersion.String(), - Kind: string(v1alpha1.KymaKind), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name + RandString(8), - Namespace: namespace, - }, - Spec: v1alpha1.KymaSpec{ - Modules: []v1alpha1.Module{}, - Channel: v1alpha1.DefaultChannel, - }, - } -} - -func NewUniqModuleName() string { - return RandString(8) -} - -const letterBytes = "abcdefghijklmnopqrstuvwxyz" - -func RandString(n int) string { - b := make([]byte, n) - for i := range b { - b[i] = letterBytes[rand.Intn(len(letterBytes))] //nolint:gosec - } - return string(b) -} - -func DeployModuleTemplates(kyma *v1alpha1.Kyma) { - for _, module := range kyma.Spec.Modules { - template, err := test.ModuleTemplateFactory(module, unstructured.Unstructured{}) - Expect(err).ShouldNot(HaveOccurred()) - Expect(controlPlaneClient.Create(ctx, template)).To(Succeed()) - } -} - -func DeleteModuleTemplates(kyma *v1alpha1.Kyma) { - for _, module := range kyma.Spec.Modules { - template, err := test.ModuleTemplateFactory(module, unstructured.Unstructured{}) - Expect(err).ShouldNot(HaveOccurred()) - Expect(controlPlaneClient.Delete(ctx, template)).To(Succeed()) - } -} - func RegisterDefaultLifecycleForKyma(kyma *v1alpha1.Kyma) { BeforeAll(func() { Expect(controlPlaneClient.Create(ctx, kyma)).Should(Succeed()) - DeployModuleTemplates(kyma) + DeployModuleTemplates(ctx, controlPlaneClient, kyma) }) AfterAll(func() { - DeleteModuleTemplates(kyma) + DeleteModuleTemplates(ctx, controlPlaneClient, kyma) }) AfterAll(func() { @@ -87,23 +41,16 @@ func RegisterDefaultLifecycleForKyma(kyma *v1alpha1.Kyma) { BeforeEach(func() { By("get latest kyma CR") - Expect(controlPlaneClient.Get(ctx, client.ObjectKey{Name: kyma.Name, Namespace: namespace}, kyma)).Should(Succeed()) + Expect(controlPlaneClient.Get(ctx, client.ObjectKey{ + Name: kyma.Name, + Namespace: metav1.NamespaceDefault, + }, kyma)).Should(Succeed()) }) } -func IsKymaInState(kymaName string, state v1alpha1.State) func() bool { - return func() bool { - kymaFromCluster, err := GetKyma(controlPlaneClient, kymaName) - if err != nil || kymaFromCluster.Status.State != state { - return false - } - return true - } -} - func GetKymaState(kymaName string) func() string { return func() string { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return "" } @@ -113,7 +60,7 @@ func GetKymaState(kymaName string) func() string { func GetKymaConditions(kymaName string) func() []metav1.Condition { return func() []metav1.Condition { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return []metav1.Condition{} } @@ -179,7 +126,7 @@ func getModule(kymaName, moduleName string) (*unstructured.Unstructured, error) Kind: "Manifest", }) err := controlPlaneClient.Get(ctx, client.ObjectKey{ - Namespace: namespace, + Namespace: metav1.NamespaceDefault, Name: common.CreateModuleName(moduleName, kymaName), }, component) if err != nil { @@ -188,24 +135,10 @@ func getModule(kymaName, moduleName string) (*unstructured.Unstructured, error) return component, nil } -func GetKyma( - testClient client.Client, - kymaName string, -) (*v1alpha1.Kyma, error) { - kymaInCluster := &v1alpha1.Kyma{} - err := testClient.Get(ctx, client.ObjectKey{ - Namespace: namespace, - Name: kymaName, - }, kymaInCluster) - if err != nil { - return nil, err - } - return kymaInCluster, nil -} - func GetModuleTemplate(name string) (*v1alpha1.ModuleTemplate, error) { moduleTemplateInCluster := &v1alpha1.ModuleTemplate{} - err := controlPlaneClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, moduleTemplateInCluster) + err := controlPlaneClient.Get(ctx, client.ObjectKey{Namespace: metav1.NamespaceDefault, Name: name}, + moduleTemplateInCluster) if err != nil { return nil, err } @@ -214,7 +147,7 @@ func GetModuleTemplate(name string) (*v1alpha1.ModuleTemplate, error) { func RemoteKymaExists(remoteClient client.Client, kymaName string) func() error { return func() error { - _, err := GetKyma(remoteClient, kymaName) + _, err := GetKyma(ctx, remoteClient, kymaName) return err } } @@ -302,7 +235,7 @@ func deleteModule(kymaName, moduleName string) func() error { Version: v1alpha1.Version, Kind: "Manifest", }) - component.SetNamespace(namespace) + component.SetNamespace(metav1.NamespaceDefault) component.SetName(common.CreateModuleName(moduleName, kymaName)) err := controlPlaneClient.Delete(ctx, component) return client.IgnoreNotFound(err) @@ -310,7 +243,7 @@ func deleteModule(kymaName, moduleName string) func() error { } func UpdateKymaModuleChannels(kymaName string, channel v1alpha1.Channel) error { - kyma, err := GetKyma(controlPlaneClient, kymaName) + kyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } @@ -326,7 +259,7 @@ func UpdateKymaModuleChannels(kymaName string, channel v1alpha1.Channel) error { var ErrTemplateInfoChannelMismatch = errors.New("mismatch in template info channel") func TemplateInfosMatchChannel(kymaName string, channel v1alpha1.Channel) error { - kyma, err := GetKyma(controlPlaneClient, kymaName) + kyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } diff --git a/operator/controllers/kyma_controller_remote_sync_test.go b/operator/controllers/kyma_controller_remote_sync_test.go index ff2b1c6fcb..3e7d11c479 100644 --- a/operator/controllers/kyma_controller_remote_sync_test.go +++ b/operator/controllers/kyma_controller_remote_sync_test.go @@ -4,14 +4,15 @@ import ( "encoding/json" "time" - ocm "github.com/gardener/component-spec/bindings-go/apis/v2" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ocm "github.com/gardener/component-spec/bindings-go/apis/v2" "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" "github.com/kyma-project/lifecycle-manager/operator/pkg/test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) var _ = Describe("Kyma with multiple module CRs in remote sync mode", Ordered, func() { @@ -32,7 +33,7 @@ var _ = Describe("Kyma with multiple module CRs in remote sync mode", Ordered, f kyma.Spec.Sync = v1alpha1.Sync{ Enabled: true, Strategy: v1alpha1.SyncStrategyLocalClient, - Namespace: namespace, + Namespace: metav1.NamespaceDefault, NoModuleCopy: true, } kyma.Spec.Modules = append(kyma.Spec.Modules, *skrModule) @@ -48,7 +49,7 @@ var _ = Describe("Kyma with multiple module CRs in remote sync mode", Ordered, f It("CR add from client should be synced in both clusters", func() { By("Remote Kyma created") Eventually(RemoteKymaExists(runtimeClient, kyma.GetName()), 30*time.Second, Interval).Should(Succeed()) - remoteKyma, err := GetKyma(runtimeClient, kyma.GetName()) + remoteKyma, err := GetKyma(ctx, runtimeClient, kyma.GetName()) Expect(err).ShouldNot(HaveOccurred()) By("add skr-module-client to remoteKyma.spec.modules") @@ -58,7 +59,8 @@ var _ = Describe("Kyma with multiple module CRs in remote sync mode", Ordered, f Eventually(runtimeClient.Update(ctx, remoteKyma), Timeout, Interval).Should(Succeed()) By("skr-module-client created in kcp") - Eventually(ModuleExists(kyma.GetName(), skrModuleFromClient.Name), Timeout, Interval).Should(BeTrue()) + Eventually(ModuleExists(kyma.GetName(), skrModuleFromClient.Name), + Timeout, Interval).Should(BeTrue()) }) }) @@ -68,7 +70,7 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { kyma.Spec.Sync = v1alpha1.Sync{ Enabled: true, Strategy: v1alpha1.SyncStrategyLocalClient, - Namespace: namespace, + Namespace: metav1.NamespaceDefault, NoModuleCopy: true, } @@ -90,7 +92,7 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { } By("No spec.module in remote Kyma") - remoteKyma, err := GetKyma(runtimeClient, kyma.GetName()) + remoteKyma, err := GetKyma(ctx, runtimeClient, kyma.GetName()) Expect(err).ShouldNot(HaveOccurred()) Expect(remoteKyma.Spec.Modules).To(BeEmpty()) @@ -101,8 +103,7 @@ var _ = Describe("Kyma sync into Remote Cluster", Ordered, func() { By("updating a module template in the remote cluster to simulate unwanted modification") Eventually(ModifyModuleTemplateSpecThroughLabels(runtimeClient, kyma, - ocm.Labels{ocm.Label{Name: "test", Value: json.RawMessage(`{"foo":"bar"}`)}}), Timeout, - Interval).Should(Succeed()) + ocm.Labels{ocm.Label{Name: "test", Value: json.RawMessage(`{"foo":"bar"}`)}}), Timeout, Interval).Should(Succeed()) By("verifying the discovered override and checking the resetted label") Eventually(ModuleTemplatesLabelsCountMatch(runtimeClient, kyma, 0), Timeout, Interval).Should(Succeed()) diff --git a/operator/controllers/kyma_controller_test.go b/operator/controllers/kyma_controller_test.go index 7834ee93f9..811072d906 100644 --- a/operator/controllers/kyma_controller_test.go +++ b/operator/controllers/kyma_controller_test.go @@ -3,18 +3,12 @@ package controllers_test import ( "time" - v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" -) - -const ( - namespace = v1.NamespaceDefault + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) var _ = Describe("Kyma with no ModuleTemplate", Ordered, func() { @@ -23,7 +17,8 @@ var _ = Describe("Kyma with no ModuleTemplate", Ordered, func() { It("Should result in a ready state immediately", func() { By("having transitioned the CR State to Ready as there are no modules") - Eventually(IsKymaInState(kyma.GetName(), v1alpha1.StateReady), Timeout, Interval).Should(BeTrue()) + Eventually(IsKymaInState(ctx, controlPlaneClient, kyma.GetName(), v1alpha1.StateReady), + Timeout, Interval).Should(BeTrue()) }) }) @@ -47,8 +42,8 @@ var _ = Describe("Kyma with empty ModuleTemplate", Ordered, func() { Eventually(GetKymaConditions(kyma.GetName()), Timeout, Interval).ShouldNot(BeEmpty()) By("reacting to a change of its Modules when they are set to ready") for _, activeModule := range kyma.Spec.Modules { - Eventually(UpdateModuleState(kyma.GetName(), activeModule.Name, v1alpha1.StateReady), 20*time.Second, - Interval).Should(Succeed()) + Eventually(UpdateModuleState(kyma.GetName(), activeModule.Name, v1alpha1.StateReady), + 20*time.Second, Interval).Should(Succeed()) } By("having updated the Kyma CR state to ready") @@ -56,13 +51,13 @@ var _ = Describe("Kyma with empty ModuleTemplate", Ordered, func() { Should(BeEquivalentTo(string(v1alpha1.StateReady))) By("Kyma status contains expected condition") - kymaInCluster, err := GetKyma(controlPlaneClient, kyma.GetName()) + kymaInCluster, err := GetKyma(ctx, controlPlaneClient, kyma.GetName()) Expect(err).ShouldNot(HaveOccurred()) Expect(kymaInCluster.ContainsCondition(v1alpha1.ConditionTypeReady, v1alpha1.ConditionReasonModulesAreReady, metav1.ConditionTrue)).To(BeTrue()) By("Module Catalog created") Eventually(ModuleTemplatesExist(controlPlaneClient, kyma), 10*time.Second, Interval).Should(Succeed()) - kymaInCluster, err = GetKyma(controlPlaneClient, kyma.GetName()) + kymaInCluster, err = GetKyma(ctx, controlPlaneClient, kyma.GetName()) Expect(err).ShouldNot(HaveOccurred()) Expect(kymaInCluster.ContainsCondition(v1alpha1.ConditionTypeReady, v1alpha1.ConditionReasonModuleCatalogIsReady)).To(BeFalse()) diff --git a/operator/controllers/kyma_module_channel_test.go b/operator/controllers/kyma_module_channel_test.go index 4151286d5a..389473cce2 100644 --- a/operator/controllers/kyma_module_channel_test.go +++ b/operator/controllers/kyma_module_channel_test.go @@ -5,13 +5,12 @@ import ( "time" "github.com/Masterminds/semver/v3" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" "github.com/kyma-project/lifecycle-manager/operator/pkg/test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) var _ = Describe("Switching of a Channel leading to an Upgrade", Ordered, func() { @@ -70,7 +69,7 @@ var _ = Describe("Switching of a Channel leading to an Upgrade", Ordered, func() It( "should lead to kyma being ready in the end of the channel switch", func() { By("having updated the Kyma CR state to ready") - Eventually(GetKymaState(kyma.Name), 20*time.Second, Interval). + Eventually(GetKymaState(kyma.Name), 20*time.Second, Timeout). Should(BeEquivalentTo(string(v1alpha1.StateReady))) }, ) diff --git a/operator/controllers/kyma_moduleinfo_test.go b/operator/controllers/kyma_moduleinfo_test.go index cc283370d3..e7d4d488f9 100644 --- a/operator/controllers/kyma_moduleinfo_test.go +++ b/operator/controllers/kyma_moduleinfo_test.go @@ -4,11 +4,10 @@ import ( "errors" "fmt" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" ) var ( @@ -24,7 +23,7 @@ func noCondition() func() error { func expectCorrectNumberOfmoduleStatus(kymaName string) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } @@ -37,7 +36,7 @@ func expectCorrectNumberOfmoduleStatus(kymaName string) func() error { func expectmoduleStatusStateBecomeReady(kymaName string) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } @@ -52,7 +51,7 @@ func expectmoduleStatusStateBecomeReady(kymaName string) func() error { func updateAllModuleState(kymaName string, state v1alpha1.State) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } @@ -67,7 +66,7 @@ func updateAllModuleState(kymaName string, state v1alpha1.State) func() error { func removeModule(kymaName string) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) Expect(err).ShouldNot(HaveOccurred()) createdKyma.Spec.Modules = v1alpha1.Modules{} return controlPlaneClient.Update(ctx, createdKyma) diff --git a/operator/controllers/moduletemplate_test.go b/operator/controllers/moduletemplate_test.go index ad1c8479bc..8dbe07a6b9 100644 --- a/operator/controllers/moduletemplate_test.go +++ b/operator/controllers/moduletemplate_test.go @@ -5,7 +5,6 @@ import ( "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -14,7 +13,7 @@ var ErrManifestRemoteIsNotMatch = errors.New("Manifest.Spec.Remote is not match" func expectManifestSpecRemoteMatched(kymaName string, remoteFlag bool) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } @@ -38,7 +37,7 @@ func expectManifestSpecRemoteMatched(kymaName string, remoteFlag bool) func() er func updateModuleTemplateTarget(kymaName string, target v1alpha1.Target) func() error { return func() error { - createdKyma, err := GetKyma(controlPlaneClient, kymaName) + createdKyma, err := GetKyma(ctx, controlPlaneClient, kymaName) if err != nil { return err } diff --git a/operator/controllers/setup.go b/operator/controllers/setup.go index 5da465b274..f70827cd89 100644 --- a/operator/controllers/setup.go +++ b/operator/controllers/setup.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/kyma-project/lifecycle-manager/operator/internal/custom" "k8s.io/client-go/util/workqueue" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" @@ -24,9 +25,7 @@ import ( ) // SetupWithManager sets up the Kyma controller with the Manager. -func (r *KymaReconciler) SetupWithManager(mgr ctrl.Manager, - options controller.Options, listenerAddr string, -) error { +func (r *KymaReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options, listenerAddr string) error { controllerBuilder := ctrl.NewControllerManagedBy(mgr).For(&v1alpha1.Kyma{}).WithOptions(options). Watches( &source.Kind{Type: &v1alpha1.ModuleTemplate{}}, @@ -80,12 +79,16 @@ func (r *KymaReconciler) watchEventChannel(controllerBuilder *builder.Builder, e } // SetupWithManager sets up the Watcher controller with the Manager. -func (r *WatcherReconciler) SetupWithManager( - mgr ctrl.Manager, - options controller.Options, +func (r *WatcherReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options, + virtualServiceName, gatewayName string, ) error { - if err := r.SetIstioClient(); err != nil { - return fmt.Errorf("unable to set istio client for controller watcher: %w", err) + if r.RestConfig == nil { + return ErrRestConfigIsNotSet + } + var err error + r.IstioClient, err = custom.NewVersionedIstioClient(r.RestConfig, virtualServiceName, gatewayName) + if err != nil { + return fmt.Errorf("unable to set istio client for watcher controller: %w", err) } return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.Watcher{}). diff --git a/operator/controllers/suite_helper_test.go b/operator/controllers/suite_helper_test.go deleted file mode 100644 index 0a2b824182..0000000000 --- a/operator/controllers/suite_helper_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package controllers_test - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "time" - - apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/util/yaml" -) - -func parseRemoteCRDs(testCrdURLs []string) ([]*apiextv1.CustomResourceDefinition, error) { - var crds []*apiextv1.CustomResourceDefinition - for _, testCrdURL := range testCrdURLs { - _, err := url.Parse(testCrdURL) - if err != nil { - return nil, err - } - request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, testCrdURL, nil) - if err != nil { - return nil, fmt.Errorf("failed pulling content for URL (%s) :%w", testCrdURL, err) - } - client := &http.Client{Timeout: time.Second * 2} - response, err := client.Do(request) - if err != nil { - return nil, err - } - if response.StatusCode != http.StatusOK { - //nolint:goerr113 - return nil, fmt.Errorf("failed pulling content for URL (%s) with status code: %d", - testCrdURL, response.StatusCode) - } - defer response.Body.Close() - decoder := yaml.NewYAMLOrJSONDecoder(response.Body, defaultBufferSize) - for { - crd := &apiextv1.CustomResourceDefinition{} - err = decoder.Decode(crd) - if err == nil { - crds = append(crds, crd) - } - if errors.Is(err, io.EOF) { - break - } - } - } - return crds, nil -} diff --git a/operator/controllers/suite_test.go b/operator/controllers/suite_test.go index 533d1f6cc0..55f8ed77c2 100644 --- a/operator/controllers/suite_test.go +++ b/operator/controllers/suite_test.go @@ -23,6 +23,8 @@ import ( "testing" "time" + "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + moduleManagerV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" //nolint:gci v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -43,9 +45,9 @@ import ( operatorv1alpha1 "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" "github.com/kyma-project/lifecycle-manager/operator/controllers" + . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" "github.com/kyma-project/lifecycle-manager/operator/pkg/remote" "github.com/kyma-project/lifecycle-manager/operator/pkg/signature" - //+kubebuilder:scaffold:imports ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -64,11 +66,6 @@ var ( cfg *rest.Config //nolint:gochecknoglobals ) -const ( - webhookChartPath = "../internal/charts/skr-webhook" - istioResourcesFilePath = "../internal/assets/istio-test-resources.yaml" -) - func TestAPIs(t *testing.T) { t.Parallel() RegisterFailHandler(Fail) @@ -84,9 +81,8 @@ var _ = BeforeSuite(func() { // manifest CRD // istio CRDs - remoteCrds, err := parseRemoteCRDs([]string{ + remoteCrds, err := ParseRemoteCRDs([]string{ "https://raw.githubusercontent.com/kyma-project/module-manager/main/operator/config/crd/bases/operator.kyma-project.io_manifests.yaml", //nolint:lll - "https://raw.githubusercontent.com/istio/istio/master/manifests/charts/base/crds/crd-all.gen.yaml", //nolint:lll }) Expect(err).NotTo(HaveOccurred()) @@ -138,11 +134,11 @@ var _ = BeforeSuite(func() { } remoteClientCache := remote.NewClientCache() - err = (&controllers.KymaReconciler{ - Client: k8sManager.GetClient(), - EventRecorder: k8sManager.GetEventRecorderFor(operatorv1alpha1.OperatorName), - RequeueIntervals: intervals, + Client: k8sManager.GetClient(), + EventRecorder: k8sManager.GetEventRecorderFor(operatorv1alpha1.OperatorName), + RequeueIntervals: intervals, + SKRWebhookChartManager: &deploy.DisabledSKRWebhookChartManager{}, VerificationSettings: signature.VerificationSettings{ EnableVerification: false, }, @@ -150,19 +146,6 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager, controller.Options{}, listenerAddr) Expect(err).ToNot(HaveOccurred()) - err = (&controllers.WatcherReconciler{ - Client: k8sManager.GetClient(), - RestConfig: k8sManager.GetConfig(), - Scheme: scheme.Scheme, - RequeueIntervals: intervals, - Config: &controllers.WatcherConfig{ - WebhookChartPath: webhookChartPath, - SkrWebhookMemoryLimits: "200Mi", - SkrWebhookCPULimits: "1", - }, - }).SetupWithManager(k8sManager, controller.Options{}) - Expect(err).ToNot(HaveOccurred()) - go func() { defer GinkgoRecover() err = k8sManager.Start(ctx) diff --git a/operator/controllers/watcher_controller.go b/operator/controllers/watcher_controller.go index 57870e3f8e..a89e0ef4f0 100644 --- a/operator/controllers/watcher_controller.go +++ b/operator/controllers/watcher_controller.go @@ -18,44 +18,35 @@ package controllers import ( "context" - "fmt" + "errors" - "github.com/go-logr/logr" - "k8s.io/client-go/rest" - - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" + "k8s.io/client-go/rest" + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" "github.com/kyma-project/lifecycle-manager/operator/internal/custom" - "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( watcherFinalizer = "operator.kyma-project.io/watcher" ) +var ErrRestConfigIsNotSet = errors.New("reconciler rest config is not set") + // WatcherReconciler reconciles a Watcher object. type WatcherReconciler struct { client.Client *custom.IstioClient RestConfig *rest.Config Scheme *runtime.Scheme - Config *WatcherConfig RequeueIntervals } -type WatcherConfig struct { - // WebhookChartPath represents the path of the webhook chart - // to be installed on SKR clusters upon reconciling watcher CRs. - WebhookChartPath string - SkrWebhookMemoryLimits string - SkrWebhookCPULimits string -} - // +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers/status,verbs=get;update;patch // +kubebuilder:rbac:groups=operator.kyma-project.io,resources=watchers/finalizers,verbs=update @@ -69,155 +60,41 @@ type WatcherConfig struct { // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. func (r *WatcherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - logger := log.FromContext(ctx) - logger.Info("Reconciliation loop start") + logger := log.FromContext(ctx).WithName(req.NamespacedName.String()) + logger.Info("Reconciliation loop starting") watcherObj := &v1alpha1.Watcher{} - err := r.Get(ctx, client.ObjectKey{Name: req.Name, Namespace: req.Namespace}, watcherObj) - if err != nil { + if err := r.Get(ctx, client.ObjectKey{Name: req.Name, Namespace: req.Namespace}, watcherObj); err != nil { logger.Error(err, "Failed to get reconciliation object") return ctrl.Result{}, client.IgnoreNotFound(err) } // check if deletionTimestamp is set, retry until it gets fully deleted - if !watcherObj.DeletionTimestamp.IsZero() && watcherObj.Status.State != v1alpha1.WatcherStateDeleting { - // if the status is not yet set to deleting, also update the status - return ctrl.Result{}, r.updateWatcherCRStatus(ctx, watcherObj, v1alpha1.WatcherStateDeleting, - "deletion timestamp set") + if !watcherObj.DeletionTimestamp.IsZero() { + err := r.RemoveVirtualServiceConfigForCR(ctx, req.NamespacedName) + if err != nil { + return ctrl.Result{Requeue: true}, err + } + controllerutil.RemoveFinalizer(watcherObj, watcherFinalizer) + err = r.Update(ctx, watcherObj) + if err != nil { + return ctrl.Result{Requeue: true}, err + } + return ctrl.Result{}, nil } // check finalizer on native object if !controllerutil.ContainsFinalizer(watcherObj, watcherFinalizer) { controllerutil.AddFinalizer(watcherObj, watcherFinalizer) - return ctrl.Result{}, r.Update(ctx, watcherObj) - } - - // state handling - switch watcherObj.Status.State { - case "": - return ctrl.Result{}, r.HandleInitialState(ctx, watcherObj) - case v1alpha1.WatcherStateProcessing: - return ctrl.Result{Requeue: true}, - r.HandleProcessingState(ctx, logger, watcherObj) - case v1alpha1.WatcherStateDeleting: - return ctrl.Result{Requeue: true}, - r.HandleDeletingState(ctx, logger, watcherObj) - case v1alpha1.WatcherStateError: - return ctrl.Result{Requeue: true}, - r.HandleProcessingState(ctx, logger, watcherObj) - case v1alpha1.WatcherStateReady: - return ctrl.Result{RequeueAfter: r.RequeueIntervals.Success}, - r.HandleProcessingState(ctx, logger, watcherObj) - } - - return ctrl.Result{}, nil -} - -func (r *WatcherReconciler) HandleInitialState(ctx context.Context, obj *v1alpha1.Watcher) error { - return r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateProcessing, "watcher cr created") -} - -func (r *WatcherReconciler) HandleProcessingState(ctx context.Context, - logger logr.Logger, obj *v1alpha1.Watcher, -) error { - err := r.UpdateVirtualServiceConfig(ctx, obj) - if err != nil { - updateErr := r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateError, - "failed to create or update service mesh config") - if updateErr == nil { - return err + err := r.Update(ctx, watcherObj) + if err != nil { + return ctrl.Result{Requeue: true}, err } - return updateErr + return ctrl.Result{}, nil } - err = deploy.UpdateWebhookConfig(ctx, r.Config.WebhookChartPath, obj, - r.RestConfig, r.Client, r.Config.SkrWebhookMemoryLimits, r.Config.SkrWebhookCPULimits) + err := r.UpdateVirtualServiceConfig(ctx, watcherObj) if err != nil { - updateErr := r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateError, "failed to update SKR config") - if updateErr == nil { - return err - } - return updateErr - } - err = r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateReady, "successfully reconciled watcher cr") - if err != nil { - msg := "failed to update watcher cr to ready status" - logger.Error(err, msg) - updateErr := r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateError, msg) - if updateErr == nil { - return err - } - return updateErr - } - logger.Info("watcher cr is Ready!") - return nil -} - -func (r *WatcherReconciler) HandleDeletingState(ctx context.Context, logger logr.Logger, - obj *v1alpha1.Watcher, -) error { - // remove virtual service - err := r.RemoveVirtualServiceConfigForCR(ctx, obj) - if err != nil { - updateErr := r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateError, - "failed to delete service mesh config") - if updateErr == nil { - return err - } - return updateErr - } - - // remove webhook config - err = deploy.RemoveWebhookConfig(ctx, r.Config.WebhookChartPath, obj, - r.RestConfig, r.Client, r.Config.SkrWebhookMemoryLimits, r.Config.SkrWebhookCPULimits) - if err != nil { - updateErr := r.updateWatcherCRStatus(ctx, obj, v1alpha1.WatcherStateError, "failed to delete SKR config") - if updateErr == nil { - return err - } - return updateErr - } - - // if finalizers was removed - return - if updated := controllerutil.RemoveFinalizer(obj, watcherFinalizer); !updated { - return nil - } - - if err = r.Update(ctx, obj); err != nil { - msg := "failed to remove finalizer" - logger.Error(err, msg) - return err - } - logger.Info("deletion state handling was successful") - return nil -} - -func (r *WatcherReconciler) updateWatcherCRStatus(ctx context.Context, obj *v1alpha1.Watcher, - state v1alpha1.WatcherState, msg string, -) error { - obj.Status.State = state - - switch state { - case v1alpha1.WatcherStateReady: - obj.AddOrUpdateReadyCondition(v1alpha1.ConditionStatusTrue, msg) - case "": - obj.AddOrUpdateReadyCondition(v1alpha1.ConditionStatusUnknown, msg) - case v1alpha1.WatcherStateProcessing: - obj.AddOrUpdateReadyCondition(v1alpha1.ConditionStatusFalse, msg) - case v1alpha1.WatcherStateDeleting: - obj.AddOrUpdateReadyCondition(v1alpha1.ConditionStatusFalse, msg) - case v1alpha1.WatcherStateError: - obj.AddOrUpdateReadyCondition(v1alpha1.ConditionStatusFalse, msg) - } - - return r.Status().Update(ctx, obj.SetObservedGeneration()) -} - -func (r *WatcherReconciler) SetIstioClient() error { - //nolint:goerr113 - if r.RestConfig == nil { - return fmt.Errorf("reconciler rest config is not set") + return ctrl.Result{Requeue: true}, err } - customIstioClient, err := custom.NewVersionedIstioClient(r.RestConfig) - r.IstioClient = customIstioClient - return err + return ctrl.Result{RequeueAfter: r.RequeueIntervals.Success}, nil } diff --git a/operator/controllers/watcher_controller_test.go b/operator/controllers/watcher_controller_test.go deleted file mode 100644 index b0710831e9..0000000000 --- a/operator/controllers/watcher_controller_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package controllers_test - -import ( - "os" - "path/filepath" - - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" - "github.com/kyma-project/lifecycle-manager/operator/internal/custom" - "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" - . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -func cRSpecsUpdates() func(customIstioClient *custom.IstioClient) { - return func(customIstioClient *custom.IstioClient) { - watcherList := v1alpha1.WatcherList{} - Expect(controlPlaneClient.List(ctx, &watcherList)).To(Succeed()) - Expect(watcherList.Items).NotTo(BeEmpty()) - for idx, watcherCR := range watcherList.Items { - // update spec - watcherCR.Spec.ServiceInfo.Port = 9090 - watcherCR.Spec.Field = v1alpha1.StatusField - Expect(controlPlaneClient.Update(ctx, &watcherList.Items[idx])).Should(Succeed()) - - // verify - Eventually(watcherCRState(client.ObjectKeyFromObject(&watcherList.Items[idx])), - Timeout, Interval).Should(Equal(v1alpha1.WatcherStateReady)) - verifyVsRoutes(&watcherList.Items[idx], customIstioClient, BeTrue()) - webhookCfg, err := deploy.GetDeployedWebhook(ctx, cfg) - Expect(err).NotTo(HaveOccurred()) - Expect(deploy.IsWebhookConfigured(&watcherList.Items[idx], webhookCfg)).To(BeTrue()) - } - } -} - -func oneCRDeleted() func(customIstioClient *custom.IstioClient) { - return func(customIstioClient *custom.IstioClient) { - // delete - watcherList := v1alpha1.WatcherList{} - Expect(controlPlaneClient.List(ctx, &watcherList)).To(Succeed()) - watcherCRCount := len(watcherList.Items) - Expect(watcherCRCount).To(Equal(len(centralComponents))) - watcherCR := watcherList.Items[watcherCRCount-1] - Expect(controlPlaneClient.Delete(ctx, &watcherCR)).To(Succeed()) - - Eventually(isCrDeletionFinished(client.ObjectKeyFromObject(&watcherCR)), Timeout, Interval).Should(BeTrue()) - verifyVsRoutes(&watcherCR, customIstioClient, BeFalse()) - webhookCfg, err := deploy.GetDeployedWebhook(ctx, cfg) - Expect(err).NotTo(HaveOccurred()) - Expect(deploy.IsWebhookConfigured(&watcherCR, webhookCfg)).To(BeFalse()) - } -} - -func allCRsDeleted() func(customIstioClient *custom.IstioClient) { - return func(customIstioClient *custom.IstioClient) { - // delete all - watcherList := v1alpha1.WatcherList{} - Expect(controlPlaneClient.List(ctx, &watcherList)).To(Succeed()) - watcherCRCount := len(watcherList.Items) - Expect(watcherCRCount).To(Equal(len(centralComponents))) - Expect(controlPlaneClient.DeleteAllOf(ctx, &v1alpha1.Watcher{}, - client.InNamespace(metav1.NamespaceDefault))).To(Succeed()) - - // verify - Eventually(isCrDeletionFinished(), Timeout, Interval).Should(BeTrue()) - verifyVsRoutes(nil, customIstioClient, BeTrue()) - Eventually(IsChartRemoved(ctx, controlPlaneClient), Timeout, Interval).Should(BeTrue()) - } -} - -var _ = Describe("Watcher CR scenarios", Ordered, func() { - var customIstioClient *custom.IstioClient - var err error - kymaSample := &v1alpha1.Kyma{} - var istioResources []*unstructured.Unstructured - BeforeAll(func() { - // create kyma resource - kymaName := "kyma-sample" - kymaSample = CreateKymaCR(kymaName) - - // create istio resources - customIstioClient, err = custom.NewVersionedIstioClient(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(controlPlaneClient.Create(ctx, kymaSample)).To(Succeed()) - istioResources, err = deserializeIstioResources() - Expect(err).NotTo(HaveOccurred()) - for _, istioResource := range istioResources { - Expect(controlPlaneClient.Create(ctx, istioResource)).To(Succeed()) - } - - Expect(CreateLoadBalancer(ctx, controlPlaneClient)).To(Succeed()) - }) - - AfterAll(func() { - // clean up kyma CR - Expect(controlPlaneClient.Delete(ctx, kymaSample)).To(Succeed()) - // clean up istio resources - for _, istioResource := range istioResources { - Expect(controlPlaneClient.Delete(ctx, istioResource)).To(Succeed()) - } - // clean rendered manifest - Expect(os.RemoveAll(filepath.Join(webhookChartPath, RenderedManifestDir))).ShouldNot(HaveOccurred()) - }) - - BeforeEach(func() { - // clean rendered manifest - Expect(os.RemoveAll(filepath.Join(webhookChartPath, RenderedManifestDir))).ShouldNot(HaveOccurred()) - // create WatcherCRs - for idx, component := range centralComponents { - watcherCR := createWatcherCR(component, isEven(idx)) - Expect(controlPlaneClient.Create(ctx, watcherCR)).To(Succeed()) - crObjectKey := client.ObjectKeyFromObject(watcherCR) - Eventually(watcherCRState(crObjectKey), Timeout, Interval).Should(Equal(v1alpha1.WatcherStateReady)) - - // verify - verifyVsRoutes(watcherCR, customIstioClient, BeTrue()) - webhookCfg, err := deploy.GetDeployedWebhook(ctx, cfg) - Expect(err).ShouldNot(HaveOccurred()) - Expect(deploy.IsWebhookConfigured(watcherCR, webhookCfg)).To(BeTrue()) - } - }) - - AfterEach(func() { - watcherList := v1alpha1.WatcherList{} - Expect(controlPlaneClient.List(ctx, &watcherList)).To(Succeed()) - for idx := range watcherList.Items { - // delete WatcherCR - Expect(controlPlaneClient.Delete(ctx, &watcherList.Items[idx])).To(Succeed()) - } - // verify deletion - Eventually(isCrDeletionFinished(), Timeout, Interval).Should(BeTrue()) - }) - - DescribeTable("given watcherCR reconcile loop", - func(testCase func(customIstioClient *custom.IstioClient)) { - testCase(customIstioClient) - }, - []TableEntry{ - Entry("when watcherCR specs are updated", cRSpecsUpdates()), - Entry("when one WatcherCR is deleted", oneCRDeleted()), - Entry("when all WatcherCRs are deleted", allCRsDeleted()), - }) -}) diff --git a/operator/controllers/withwatcher/kyma_controller_test.go b/operator/controllers/withwatcher/kyma_controller_test.go new file mode 100644 index 0000000000..a50546405c --- /dev/null +++ b/operator/controllers/withwatcher/kyma_controller_test.go @@ -0,0 +1,168 @@ +package withwatcher_test + +import ( + "context" + "fmt" + "reflect" + "strings" + + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" + + "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + admissionv1 "k8s.io/api/admissionregistration/v1" + appsv1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + webhookConfigNameTpl = "%s-webhook" + servicePathTpl = "/validate/%s" + specSubresources = "*" + statusSubresources = "*/status" + expectedWebhookNamePartsLength = 4 +) + +var _ = Describe("Kyma with multiple module CRs in remote sync mode", Ordered, func() { + kyma := NewTestKyma("kyma-remote-sync") + watcherCrForKyma := createWatcherCR("skr-webhook-manager", true) + + kyma.Spec.Sync = v1alpha1.Sync{ + Enabled: true, + Strategy: v1alpha1.SyncStrategyLocalClient, + Namespace: metav1.NamespaceDefault, + NoModuleCopy: true, + } + registerDefaultLifecycleForKymaWithWatcher(kyma, watcherCrForKyma) + + It("kyma reconciler installs watcher helm chart with correct webhook config", func() { + webhookConfig := &admissionv1.ValidatingWebhookConfiguration{} + Eventually(isWebhookDeployed(suiteCtx, runtimeClient, webhookConfig), Timeout, Interval). + Should(Succeed()) + Expect(isWebhookConfigured(watcherCrForKyma, webhookConfig)).To(BeTrue()) + Eventually(IsKymaInState(suiteCtx, controlPlaneClient, kyma.GetName(), v1alpha1.StateReady), + Timeout, Interval).Should(BeTrue()) + }) + + It("kyma reconciler installs watcher helm chart with correct webhook config when watcher specs are updated", + func() { + Skip("failing because of manifest caching invalidation") + latestWatcher := &v1alpha1.Watcher{} + Expect(controlPlaneClient.Get(suiteCtx, client.ObjectKeyFromObject(watcherCrForKyma), latestWatcher)). + To(Succeed()) + latestWatcher.Spec.LabelsToWatch["new-key"] = "new-value" + Expect(controlPlaneClient.Update(suiteCtx, latestWatcher)).To(Succeed()) + latestKyma := &v1alpha1.Kyma{} + Expect(controlPlaneClient.Get(suiteCtx, client.ObjectKeyFromObject(kyma), latestKyma)).To(Succeed()) + latestKyma.Spec.Channel = v1alpha1.ChannelFast + Expect(controlPlaneClient.Update(suiteCtx, latestKyma)).To(Succeed()) + webhookConfig := &admissionv1.ValidatingWebhookConfiguration{} + Eventually(isWebhookDeployed(suiteCtx, runtimeClient, webhookConfig), Timeout, Interval).Should(Succeed()) + Eventually(IsKymaInState(suiteCtx, controlPlaneClient, kyma.GetName(), v1alpha1.StateReady), + Timeout, Interval).Should(BeTrue()) + Expect(isWebhookConfigured(latestWatcher, webhookConfig)).To(BeTrue()) + }) + + It("webhook manager removes watcher helm chart from SKR cluster when kyma is deleted", func() { + latestKyma := &v1alpha1.Kyma{} + Expect(controlPlaneClient.Get(suiteCtx, client.ObjectKeyFromObject(kyma), latestKyma)).To(Succeed()) + Expect(controlPlaneClient.Delete(suiteCtx, latestKyma)).To(Succeed()) + Eventually(getSkrChartDeployment(suiteCtx, runtimeClient), Timeout, Interval).Should(Succeed()) + }) +}) + +func getSkrChartDeployment(ctx context.Context, skrClient client.Client) func() error { + return func() error { + return skrClient.Get(ctx, client.ObjectKey{ + Namespace: metav1.NamespaceDefault, + Name: deploy.ResolveSKRChartResourceName(deploy.DeploymentNameTpl), + }, &appsv1.Deployment{}) + } +} + +func isWebhookDeployed(ctx context.Context, skrClient client.Client, + webhookConfig *admissionv1.ValidatingWebhookConfiguration, +) func() error { + return func() error { + return skrClient.Get(ctx, client.ObjectKey{ + Namespace: metav1.NamespaceDefault, + Name: deploy.ResolveSKRChartResourceName(webhookConfigNameTpl), + }, webhookConfig) + } +} + +func isWebhookConfigured(watcher *v1alpha1.Watcher, webhookConfig *admissionv1.ValidatingWebhookConfiguration) bool { + if len(webhookConfig.Webhooks) < 1 { + return false + } + idx := lookupWebhookConfigForCR(webhookConfig.Webhooks, watcher) + if idx != -1 { + return verifyWebhookConfig(webhookConfig.Webhooks[idx], watcher) + } + return false +} + +func lookupWebhookConfigForCR(webhooks []admissionv1.ValidatingWebhook, watcher *v1alpha1.Watcher) int { + cfgIdx := -1 + for idx, webhook := range webhooks { + webhookNameParts := strings.Split(webhook.Name, ".") + if len(webhookNameParts) == 0 { + continue + } + moduleName := webhookNameParts[0] + objModuleName := watcher.GetModuleName() + if moduleName == objModuleName { + return idx + } + } + return cfgIdx +} + +func verifyWebhookConfig( + webhook admissionv1.ValidatingWebhook, + watcherCR *v1alpha1.Watcher, +) bool { + webhookNameParts := strings.Split(webhook.Name, ".") + Expect(len(webhookNameParts)).To(Equal(expectedWebhookNamePartsLength)) + + moduleName := webhookNameParts[0] + expectedModuleName, exists := watcherCR.Labels[v1alpha1.ManagedBylabel] + Expect(exists).To(BeTrue()) + Expect(moduleName).To(Equal(expectedModuleName)) + Expect(*webhook.ClientConfig.Service.Path).To(Equal(fmt.Sprintf(servicePathTpl, moduleName))) + Expect(reflect.DeepEqual(webhook.ObjectSelector.MatchLabels, watcherCR.Spec.LabelsToWatch)).To(BeTrue()) + + if watcherCR.Spec.Field == v1alpha1.StatusField { + Expect(webhook.Rules[0].Resources[0]).To(Equal(statusSubresources)) + } + + if watcherCR.Spec.Field == v1alpha1.SpecField { + Expect(webhook.Rules[0].Resources[0]).To(Equal(specSubresources)) + } + return true +} + +func registerDefaultLifecycleForKymaWithWatcher(kyma *v1alpha1.Kyma, watcher *v1alpha1.Watcher) { + BeforeAll(func() { + Expect(controlPlaneClient.Create(suiteCtx, watcher)).To(Succeed()) + Expect(controlPlaneClient.Create(suiteCtx, kyma)).Should(Succeed()) + DeployModuleTemplates(suiteCtx, controlPlaneClient, kyma) + }) + + AfterAll(func() { + Expect(controlPlaneClient.Delete(suiteCtx, watcher)).To(Succeed()) + DeleteModuleTemplates(suiteCtx, controlPlaneClient, kyma) + Expect(controlPlaneClient.Delete(suiteCtx, kyma)).Should(Succeed()) + }) + + BeforeEach(func() { + By("get latest kyma CR") + Expect(controlPlaneClient.Get(suiteCtx, client.ObjectKey{ + Name: kyma.Name, Namespace: metav1.NamespaceDefault, + }, kyma)).Should(Succeed()) + }) +} diff --git a/operator/controllers/withwatcher/suite_with_watcher_test.go b/operator/controllers/withwatcher/suite_with_watcher_test.go new file mode 100644 index 0000000000..6ede79976b --- /dev/null +++ b/operator/controllers/withwatcher/suite_with_watcher_test.go @@ -0,0 +1,284 @@ +/* +Copyright 2022. + +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 withwatcher_test + +import ( + "context" + "os" + "path/filepath" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/intstr" + + moduleManagerV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" + //nolint:gci + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + yaml2 "k8s.io/apimachinery/pkg/util/yaml" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/manager" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + operatorv1alpha1 "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" + "github.com/kyma-project/lifecycle-manager/operator/pkg/remote" + "github.com/kyma-project/lifecycle-manager/operator/pkg/signature" + + //+kubebuilder:scaffold:imports + "github.com/kyma-project/lifecycle-manager/operator/controllers" + "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +const listenerAddr = ":8082" + +var ( + controlPlaneClient client.Client //nolint:gochecknoglobals + runtimeClient client.Client //nolint:gochecknoglobals + k8sManager manager.Manager //nolint:gochecknoglobals + controlPlaneEnv *envtest.Environment //nolint:gochecknoglobals + runtimeEnv *envtest.Environment //nolint:gochecknoglobals + suiteCtx context.Context //nolint:gochecknoglobals + cancel context.CancelFunc //nolint:gochecknoglobals + cfg *rest.Config //nolint:gochecknoglobals + istioResources []*unstructured.Unstructured //nolint:gochecknoglobals + remoteClientCache *remote.ClientCache //nolint:gochecknoglobals +) + +const ( + webhookChartPath = "../../charts/skr-webhook" + istioResourcesFilePath = "../../internal/assets/istio-test-resources.yaml" + virtualServiceName = "kcp-events" + gatewayName = "lifecycle-manager-kyma-gateway" +) + +func TestAPIs(t *testing.T) { + t.Parallel() + RegisterFailHandler(Fail) + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + suiteCtx, cancel = context.WithCancel(context.TODO()) + logger := zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)) + logf.SetLogger(logger) + + By("bootstrapping test environment") + + // manifest CRD + // istio CRDs + remoteCrds, err := ParseRemoteCRDs([]string{ + "https://raw.githubusercontent.com/kyma-project/module-manager/main/operator/config/crd/bases/operator.kyma-project.io_manifests.yaml", //nolint:lll + "https://raw.githubusercontent.com/istio/istio/master/manifests/charts/base/crds/crd-all.gen.yaml", //nolint:lll + }) + Expect(err).NotTo(HaveOccurred()) + + // kcpModule CRD + controlplaneCrd := &v1.CustomResourceDefinition{} + modulePath := filepath.Join("..", "..", "config", "samples", "component-integration-installed", + "crd", "operator.kyma-project.io_kcpmodules.yaml") + moduleFile, err := os.ReadFile(modulePath) + Expect(err).To(BeNil()) + Expect(moduleFile).ToNot(BeEmpty()) + Expect(yaml2.Unmarshal(moduleFile, &controlplaneCrd)).To(Succeed()) + + controlPlaneEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + CRDs: append([]*v1.CustomResourceDefinition{controlplaneCrd}, remoteCrds...), + ErrorIfCRDPathMissing: true, + } + + cfg, err = controlPlaneEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + Expect(operatorv1alpha1.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) + Expect(v1.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) + Expect(moduleManagerV1alpha1.AddToScheme(scheme.Scheme)).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + controlPlaneClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(controlPlaneClient).NotTo(BeNil()) + + runtimeClient, runtimeEnv = NewSKRCluster() + + metricsBindAddress, found := os.LookupEnv("metrics-bind-address") + if !found { + metricsBindAddress = ":8081" + } + + k8sManager, err = ctrl.NewManager(cfg, ctrl.Options{ + MetricsBindAddress: metricsBindAddress, + Scheme: scheme.Scheme, + NewCache: controllers.NewCacheFunc(), + }) + Expect(err).ToNot(HaveOccurred()) + + intervals := controllers.RequeueIntervals{ + Success: 3 * time.Second, + } + + remoteClientCache = remote.NewClientCache() + skrChartCfg := &deploy.SkrChartConfig{ + WebhookChartPath: webhookChartPath, + SkrWebhookMemoryLimits: "200Mi", + SkrWebhookCPULimits: "1", + } + err = (&controllers.KymaReconciler{ + Client: k8sManager.GetClient(), + EventRecorder: k8sManager.GetEventRecorderFor(operatorv1alpha1.OperatorName), + RequeueIntervals: intervals, + SKRWebhookChartManager: deploy.NewEnabledSKRWebhookChartManager(skrChartCfg), + VerificationSettings: signature.VerificationSettings{ + EnableVerification: false, + }, + RemoteClientCache: remoteClientCache, + }).SetupWithManager(k8sManager, controller.Options{}, listenerAddr) + Expect(err).ToNot(HaveOccurred()) + + Expect(createLoadBalancer(suiteCtx, controlPlaneClient)).To(Succeed()) + istioResources, err = deserializeIstioResources() + Expect(err).NotTo(HaveOccurred()) + for _, istioResource := range istioResources { + Expect(controlPlaneClient.Create(suiteCtx, istioResource)).To(Succeed()) + } + + err = (&controllers.WatcherReconciler{ + Client: k8sManager.GetClient(), + RestConfig: k8sManager.GetConfig(), + Scheme: scheme.Scheme, + RequeueIntervals: intervals, + }).SetupWithManager(k8sManager, controller.Options{ + MaxConcurrentReconciles: 1, + }, virtualServiceName, gatewayName) + Expect(err).ToNot(HaveOccurred()) + + go func() { + defer GinkgoRecover() + err = k8sManager.Start(suiteCtx) + Expect(err).ToNot(HaveOccurred(), "failed to run manager") + }() +}) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + // clean up istio resources + for _, istioResource := range istioResources { + Expect(controlPlaneClient.Delete(suiteCtx, istioResource)).To(Succeed()) + } + // cancel environment context + cancel() + + err := controlPlaneEnv.Stop() + Expect(err).NotTo(HaveOccurred()) + err = runtimeEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) + +func NewSKRCluster() (client.Client, *envtest.Environment) { + skrEnv := &envtest.Environment{ + ErrorIfCRDPathMissing: true, + } + cfg, err := skrEnv.Start() + Expect(cfg).NotTo(BeNil()) + Expect(err).NotTo(HaveOccurred()) + + var authUser *envtest.AuthenticatedUser + authUser, err = skrEnv.AddUser(envtest.User{ + Name: "skr-admin-account", + Groups: []string{"system:masters"}, + }, cfg) + Expect(err).NotTo(HaveOccurred()) + + remote.LocalClient = func() *rest.Config { + return authUser.Config() + } + + skrClient, err := client.New(authUser.Config(), client.Options{Scheme: controlPlaneClient.Scheme()}) + Expect(err).NotTo(HaveOccurred()) + + return skrClient, skrEnv +} + +func createLoadBalancer(ctx context.Context, k8sClient client.Client) error { + istioNs := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: deploy.IstioSytemNs, + }, + } + if err := k8sClient.Create(ctx, istioNs); err != nil { + return err + } + loadBalancerService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: deploy.IngressServiceName, + Namespace: deploy.IstioSytemNs, + Labels: map[string]string{ + "app": deploy.IngressServiceName, + }, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + Ports: []corev1.ServicePort{ + { + Name: "http2", + Protocol: corev1.ProtocolTCP, + Port: 80, + TargetPort: intstr.FromInt(8080), + }, + }, + }, + } + + if err := k8sClient.Create(ctx, loadBalancerService); err != nil { + return err + } + loadBalancerService.Status = corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: "10.10.10.167", + }, + }, + }, + } + if err := k8sClient.Status().Update(ctx, loadBalancerService); err != nil { + return err + } + + return k8sClient.Get(ctx, client.ObjectKey{ + Name: deploy.IngressServiceName, + Namespace: deploy.IstioSytemNs, + }, loadBalancerService) +} diff --git a/operator/controllers/watcher_controller_helper_test.go b/operator/controllers/withwatcher/watcher_controller_helper_test.go similarity index 58% rename from operator/controllers/watcher_controller_helper_test.go rename to operator/controllers/withwatcher/watcher_controller_helper_test.go index 620d8d2fa8..18d2610895 100644 --- a/operator/controllers/watcher_controller_helper_test.go +++ b/operator/controllers/withwatcher/watcher_controller_helper_test.go @@ -1,26 +1,27 @@ -package controllers_test +package withwatcher_test import ( + "context" "errors" "fmt" "io" "os" - "github.com/onsi/gomega/types" + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" + "github.com/kyma-project/lifecycle-manager/operator/internal/custom" + . "github.com/onsi/gomega" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" - "sigs.k8s.io/controller-runtime/pkg/client" - . "github.com/onsi/gomega" - - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" - "github.com/kyma-project/lifecycle-manager/operator/internal/custom" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( defaultBufferSize = 2048 + crToDeleteIdx = 2 ) //nolint:gochecknoglobals @@ -48,71 +49,85 @@ func deserializeIstioResources() ([]*unstructured.Unstructured, error) { return istioResourcesList, nil } -func verifyVsRoutes(watcherCR *v1alpha1.Watcher, customIstioClient *custom.IstioClient, matcher types.GomegaMatcher) { - if watcherCR != nil { - routeReady, err := customIstioClient.IsListenerHTTPRouteConfigured(ctx, watcherCR) - Expect(err).ToNot(HaveOccurred()) - Expect(routeReady).To(matcher) - } else { - vsDeleted, err := customIstioClient.IsVsDeleted(ctx) - Expect(err).ToNot(HaveOccurred()) - Expect(vsDeleted).To(matcher) - } -} - func isEven(idx int) bool { return idx%2 == 0 } -func watcherCRState(watcherObjKey client.ObjectKey) func(g Gomega) v1alpha1.WatcherState { - return func(g Gomega) v1alpha1.WatcherState { - watcherCR := &v1alpha1.Watcher{} - err := controlPlaneClient.Get(ctx, watcherObjKey, watcherCR) - g.Expect(err).NotTo(HaveOccurred()) - return watcherCR.Status.State - } -} - -func createWatcherCR(moduleName string, statusOnly bool) *v1alpha1.Watcher { +func createWatcherCR(managerInstanceName string, statusOnly bool) *v1alpha1.Watcher { field := v1alpha1.SpecField if statusOnly { field = v1alpha1.StatusField } return &v1alpha1.Watcher{ + TypeMeta: metav1.TypeMeta{ + Kind: string(v1alpha1.WatcherKind), + APIVersion: v1alpha1.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-sample", moduleName), + Name: fmt.Sprintf("%s-sample", managerInstanceName), Namespace: metav1.NamespaceDefault, Labels: map[string]string{ - v1alpha1.ManagedBylabel: moduleName, + v1alpha1.ManagedBylabel: managerInstanceName, }, }, Spec: v1alpha1.WatcherSpec{ ServiceInfo: v1alpha1.Service{ Port: 8082, - Name: fmt.Sprintf("%s-svc", moduleName), + Name: fmt.Sprintf("%s-svc", managerInstanceName), Namespace: metav1.NamespaceDefault, }, LabelsToWatch: map[string]string{ - fmt.Sprintf("%s-watchable", moduleName): "true", + fmt.Sprintf("%s-watchable", managerInstanceName): "true", }, Field: field, }, } } +func listTestWatcherCrs(kcpClient client.Client) []*v1alpha1.Watcher { + watchers := make([]*v1alpha1.Watcher, 0) + for _, component := range centralComponents { + watcherCR := &v1alpha1.Watcher{} + err := kcpClient.Get(suiteCtx, client.ObjectKey{ + Name: fmt.Sprintf("%s-sample", component), + Namespace: metav1.NamespaceDefault, + }, watcherCR) + if err != nil { + continue + } + + watchers = append(watchers, watcherCR) + } + return watchers +} + func isCrDeletionFinished(watcherObjKeys ...client.ObjectKey) func(g Gomega) bool { if len(watcherObjKeys) > 1 { return nil } if len(watcherObjKeys) == 0 { return func(g Gomega) bool { - watchers := &v1alpha1.WatcherList{} - err := controlPlaneClient.List(ctx, watchers) - return err == nil && len(watchers.Items) == 0 + watchers := listTestWatcherCrs(controlPlaneClient) + return len(watchers) == 0 } } return func(g Gomega) bool { - err := controlPlaneClient.Get(ctx, watcherObjKeys[0], &v1alpha1.Watcher{}) + err := controlPlaneClient.Get(suiteCtx, watcherObjKeys[0], &v1alpha1.Watcher{}) return apierrors.IsNotFound(err) } } + +func isCrVsConfigured(ctx context.Context, customIstioClient *custom.IstioClient, obj *v1alpha1.Watcher, +) func(g Gomega) bool { + return func(g Gomega) bool { + routeReady, err := customIstioClient.IsListenerHTTPRouteConfigured(ctx, obj) + return err == nil && routeReady + } +} + +func isVsRemoved(ctx context.Context, customIstioClient *custom.IstioClient) func(g Gomega) bool { + return func(g Gomega) bool { + vsDeleted, err := customIstioClient.IsVsDeleted(ctx) + return err == nil && vsDeleted + } +} diff --git a/operator/controllers/withwatcher/watcher_controller_test.go b/operator/controllers/withwatcher/watcher_controller_test.go new file mode 100644 index 0000000000..ba9a1da708 --- /dev/null +++ b/operator/controllers/withwatcher/watcher_controller_test.go @@ -0,0 +1,91 @@ +package withwatcher_test + +import ( + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" + "github.com/kyma-project/lifecycle-manager/operator/internal/custom" + . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func cRSpecsUpdates() func(customIstioClient *custom.IstioClient) { + return func(customIstioClient *custom.IstioClient) { + watcherCrs := listTestWatcherCrs(controlPlaneClient) + Expect(watcherCrs).NotTo(BeEmpty()) + for _, watcherCR := range watcherCrs { + // update spec + watcherCR.Spec.ServiceInfo.Port = 9090 + watcherCR.Spec.Field = v1alpha1.StatusField + Expect(controlPlaneClient.Update(suiteCtx, watcherCR)).Should(Succeed()) + + // verify + Eventually(isCrVsConfigured(suiteCtx, customIstioClient, watcherCR)).Should(BeTrue()) + } + } +} + +func oneCRDeleted() func(customIstioClient *custom.IstioClient) { + return func(customIstioClient *custom.IstioClient) { + // delete + watcherCrs := listTestWatcherCrs(controlPlaneClient) + watcherCR := watcherCrs[crToDeleteIdx] + Expect(controlPlaneClient.Delete(suiteCtx, watcherCR)).To(Succeed()) + + Eventually(isCrDeletionFinished(client.ObjectKeyFromObject(watcherCR)), Timeout, Interval). + Should(BeTrue()) + Eventually(isCrVsConfigured(suiteCtx, customIstioClient, watcherCR)).Should(BeFalse()) + } +} + +func allCRsDeleted() func(customIstioClient *custom.IstioClient) { + return func(customIstioClient *custom.IstioClient) { + // delete all remaining CRs + watcherCrs := listTestWatcherCrs(controlPlaneClient) + watcherCRCount := len(watcherCrs) + Expect(watcherCRCount).To(Equal(len(centralComponents) - 1)) + for _, watcherCr := range watcherCrs { + Expect(controlPlaneClient.Delete(suiteCtx, watcherCr)).To(Succeed()) + } + // verify + Eventually(isCrDeletionFinished(), Timeout, Interval).Should(BeTrue()) + Eventually(isVsRemoved(suiteCtx, customIstioClient)).Should(BeTrue()) + } +} + +var _ = Describe("Watcher CR scenarios", Ordered, func() { + var customIstioClient *custom.IstioClient + var err error + kymaSample := &v1alpha1.Kyma{} + BeforeAll(func() { + // create kyma resource + kymaSample = NewTestKyma("kyma-sample") + + customIstioClient, err = custom.NewVersionedIstioClient(cfg, virtualServiceName, gatewayName) + Expect(err).ToNot(HaveOccurred()) + Expect(controlPlaneClient.Create(suiteCtx, kymaSample)).To(Succeed()) + // create WatcherCRs + for idx, component := range centralComponents { + watcherCR := createWatcherCR(component, isEven(idx)) + Expect(controlPlaneClient.Create(suiteCtx, watcherCR)).To(Succeed()) + + // verify + Eventually(isCrVsConfigured(suiteCtx, customIstioClient, watcherCR)).Should(BeTrue()) + } + }) + + AfterAll(func() { + // clean up kyma CR + Expect(controlPlaneClient.Delete(suiteCtx, kymaSample)).To(Succeed()) + }) + + DescribeTable("given watcherCR reconcile loop", + func(testCase func(customIstioClient *custom.IstioClient)) { + testCase(customIstioClient) + }, + []TableEntry{ + Entry("when watcherCR specs are updated", cRSpecsUpdates()), + Entry("when one WatcherCR is deleted", oneCRDeleted()), + Entry("when all WatcherCRs are deleted", allCRsDeleted()), + }) +}) diff --git a/operator/go.mod b/operator/go.mod index 462c39b6a1..cad1ed006a 100644 --- a/operator/go.mod +++ b/operator/go.mod @@ -6,6 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/gardener/component-spec/bindings-go v0.0.70 github.com/go-logr/logr v1.2.3 + github.com/go-logr/zapr v1.2.3 github.com/kyma-project/module-manager/operator v0.0.0-20221031152637-c1668e8dcd6c github.com/kyma-project/runtime-watcher/listener v0.0.0-20221006112208-0dd54057307c github.com/onsi/ginkgo/v2 v2.1.6 @@ -42,7 +43,6 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/containerd/containerd v1.6.6 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/cli v20.10.17+incompatible // indirect @@ -61,7 +61,6 @@ require ( github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-gorp/gorp/v3 v3.0.2 // indirect - github.com/go-logr/zapr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.22.3 // indirect @@ -74,7 +73,6 @@ require ( github.com/google/btree v1.1.2 // indirect github.com/google/gnostic v0.6.9 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-containerregistry v0.10.0 // 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 @@ -100,7 +98,6 @@ require ( github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/locker v1.0.1 // indirect @@ -127,7 +124,6 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cobra v1.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/vbatts/tar-split v0.11.2 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect diff --git a/operator/go.sum b/operator/go.sum index 515bac3b8c..215c9ee1f6 100644 --- a/operator/go.sum +++ b/operator/go.sum @@ -57,10 +57,8 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= @@ -80,7 +78,6 @@ github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -99,11 +96,8 @@ github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -123,8 +117,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= @@ -132,7 +124,6 @@ github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9D github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -142,7 +133,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= @@ -157,8 +147,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= @@ -179,8 +167,6 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0= github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= -github.com/containerd/stargz-snapshotter/estargz v0.12.0 h1:idtwRTLjk2erqiYhPWy2L844By8NRFYEwYHcXhoIWPM= -github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -193,7 +179,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -207,7 +192,6 @@ github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2 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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -232,9 +216,6 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 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= @@ -250,16 +231,12 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= @@ -267,10 +244,7 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -278,15 +252,12 @@ github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5 github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= -github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/gardener/component-spec/bindings-go v0.0.70 h1:zTESaetRZYKxuK+aMTN1BLOHsp3krhYRYaL31VgHM5I= github.com/gardener/component-spec/bindings-go v0.0.70/go.mod h1:qr7kADDXbXB0huul+ih/B43YkwyiMFYQepp/tqJ331c= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -302,13 +273,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -316,12 +284,9 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= 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-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= @@ -413,16 +378,13 @@ github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZ github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= 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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -439,10 +401,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/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/go-containerregistry v0.10.0 h1:qd/fv2nQajGZJenaNcdaghlwSPjQ0NphN9hzArr2WWg= -github.com/google/go-containerregistry v0.10.0/go.mod h1:C7uwbB1QUAtvnknyd3ethxJRd4gtEjU/9WLXzckfI1Y= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.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= @@ -477,7 +436,6 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= @@ -503,7 +461,6 @@ github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -555,7 +512,6 @@ github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= @@ -577,7 +533,6 @@ github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= 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/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= @@ -605,7 +560,6 @@ github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -625,10 +579,6 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/kyma-project/module-manager/operator v0.0.0-20221017152046-7690d9d91ca4 h1:NsL/mFmUNRGtsPXlg+PH89LuI4IgTp/79H3OZCsPQsE= -github.com/kyma-project/module-manager/operator v0.0.0-20221017152046-7690d9d91ca4/go.mod h1:BTORxQ8Piw7O24lTElpK5JrKcpGaCVcqb96LDT8Sti4= -github.com/kyma-project/module-manager/operator v0.0.0-20221026074920-7cb3b8f6f21b h1:WOT41TxUA6I0pinw3snhDZxZ1aYatpCgs7ShNcsi8bQ= -github.com/kyma-project/module-manager/operator v0.0.0-20221026074920-7cb3b8f6f21b/go.mod h1:N0kmS8pTNXq+7/Bdr6vfogmw03H+uYMCauTQ6U6+kA0= github.com/kyma-project/module-manager/operator v0.0.0-20221031152637-c1668e8dcd6c h1:lDNM+pZBfum9NWEz2dpy/VrvwZax+QgIB2gm2x1Lf+A= github.com/kyma-project/module-manager/operator v0.0.0-20221031152637-c1668e8dcd6c/go.mod h1:N0kmS8pTNXq+7/Bdr6vfogmw03H+uYMCauTQ6U6+kA0= github.com/kyma-project/runtime-watcher/listener v0.0.0-20221006112208-0dd54057307c h1:x6Kmcx9+TnhXKEhbtJR+/VO6A3a6PeENaYCwpQCHw2A= @@ -651,15 +601,12 @@ github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= @@ -691,7 +638,6 @@ github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mN github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -701,7 +647,6 @@ github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRU github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= @@ -719,11 +664,9 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -758,14 +701,12 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -778,18 +719,14 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -914,7 +851,6 @@ github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4l github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -924,12 +860,10 @@ github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -941,8 +875,7 @@ github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRk 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.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -973,14 +906,11 @@ github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lP github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= -github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= @@ -990,7 +920,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= @@ -1005,7 +934,6 @@ github.com/yuin/goldmark v1.1.32/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.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= @@ -1013,7 +941,6 @@ github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c h1:/RwRVN9EdXAVtdHxP7Ndn/tfmM9/goiwU0QTnLBgS4w= go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= @@ -1029,18 +956,7 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.starlark.net v0.0.0-20220714194419-4cadf0a12139 h1:zMemyQYZSyEdPaUFixYICrXf/0Rfnil7+jiQRf5IBZ0= go.starlark.net v0.0.0-20220714194419-4cadf0a12139/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1078,12 +994,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0= golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -1124,7 +1038,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1144,7 +1057,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL 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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1176,7 +1088,6 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1198,7 +1109,6 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= @@ -1241,7 +1151,6 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1263,7 +1172,6 @@ golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1298,10 +1206,8 @@ golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= @@ -1326,7 +1232,6 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb 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.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1388,7 +1293,6 @@ golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/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= @@ -1432,7 +1336,6 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= 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= @@ -1514,7 +1417,6 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D 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-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1625,9 +1527,6 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -helm.sh/helm/v3 v3.9.4 h1:TCI1QhJUeLVOdccfdw+vnSEO3Td6gNqibptB04QtExY= -helm.sh/helm/v3 v3.9.4/go.mod h1:3eaWAIqzvlRSD06gR9MMwmp2KBKwlu9av1/1BZpjeWY= helm.sh/helm/v3 v3.10.1 h1:uTnNlYx8QcTSNA4ZJ50Llwife4CSohUY4ehumyVf2QE= helm.sh/helm/v3 v3.10.1/go.mod h1:CXOcs02AYvrlPMWARNYNRgf2rNP7gLJQsi/Ubd4EDrI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1642,48 +1541,26 @@ istio.io/api v0.0.0-20220927144349-95d2a2fe2144 h1:8jXaJE++dfHmhx0j1lrz/J1oYHis5 istio.io/api v0.0.0-20220927144349-95d2a2fe2144/go.mod h1:hQkF0Q19MCmfOTre/Sg4KvrwwETq45oaFplnBm2p4j8= istio.io/client-go v1.15.1 h1:7OQQr1q+cw85LxlT951t1z5kzo469yMUg2xzv3W2qdw= istio.io/client-go v1.15.1/go.mod h1:y7N6Hi3uohxutNPWhilQ0sTVzuhWWA6JyRHNj3QyMxU= -k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= k8s.io/api v0.25.2 h1:v6G8RyFcwf0HR5jQGIAYlvtRNrxMJQG1xJzaSeVnIS8= k8s.io/api v0.25.2/go.mod h1:qP1Rn4sCVFwx/xIhe+we2cwBLTXNcheRyYXwajonhy0= k8s.io/apiextensions-apiserver v0.25.2 h1:8uOQX17RE7XL02ngtnh3TgifY7EhekpK+/piwzQNnBo= k8s.io/apiextensions-apiserver v0.25.2/go.mod h1:iRwwRDlWPfaHhuBfQ0WMa5skdQfrE18QXJaJvIDLvE8= -k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apimachinery v0.25.2 h1:WbxfAjCx+AeN8Ilp9joWnyJ6xu9OMeS/fsfjK/5zaQs= k8s.io/apimachinery v0.25.2/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA= k8s.io/apiserver v0.25.2 h1:YePimobk187IMIdnmsMxsfIbC5p4eX3WSOrS9x6FEYw= k8s.io/apiserver v0.25.2/go.mod h1:30r7xyQTREWCkG2uSjgjhQcKVvAAlqoD+YyrqR6Cn+I= -k8s.io/cli-runtime v0.24.3/go.mod h1:In84wauoMOqa7JDvDSXGbf8lTNlr70fOGpYlYfJtSqA= -k8s.io/cli-runtime v0.25.0 h1:XBnTc2Fi+w818jcJGzhiJKQuXl8479sZ4FhtV5hVJ1Q= -k8s.io/cli-runtime v0.25.0/go.mod h1:bHOI5ZZInRHhbq12OdUiYZQN8ml8aKZLwQgt9QlLINw= k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc= k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc= -k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= k8s.io/client-go v0.25.2 h1:SUPp9p5CwM0yXGQrwYurw9LWz+YtMwhWd0GqOsSiefo= k8s.io/client-go v0.25.2/go.mod h1:i7cNU7N+yGQmJkewcRD2+Vuj4iz7b30kI8OcL3horQ4= -k8s.io/code-generator v0.24.3/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.3/go.mod h1:bqom2IWN9Lj+vwAkPNOv2TflsP1PeVDIwIN0lRthxYY= k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY= k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60= -k8s.io/component-helpers v0.24.3/go.mod h1:/1WNW8TfBOijQ1ED2uCHb4wtXYWDVNMqUll8h36iNVo= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909 h1:q/70bz7C1/LGuQu/JBX7Fpi55CwcCts/wbvlehe0RRo= k8s.io/kube-openapi v0.0.0-20220928191237-829ce0c27909/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kubectl v0.24.3 h1:PqY8ho/S/KuE2/hCC3Iee7X+lOtARYo0LQsNzvV/edE= -k8s.io/kubectl v0.24.3/go.mod h1:PYLcvw96sC1NLbxZEDbdlOEd6/C76VIWjGmWV5QjSk0= k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA= k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg= -k8s.io/metrics v0.24.3/go.mod h1:p1M0lhMySWfhISkSd3HEj8xIgrVnJTK3PPhFq2rA3To= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220922133306-665eaaec4324 h1:i+xdFemcSNuJvIfBlaYuXgRondKxK4z4prVPKzEaelI= k8s.io/utils v0.0.0-20220922133306-665eaaec4324/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= @@ -1697,22 +1574,14 @@ 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.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= -sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= -sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= -sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= 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.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/operator/internal/assets/istio-test-resources.yaml b/operator/internal/assets/istio-test-resources.yaml index cdba1792b7..cabc9ae310 100644 --- a/operator/internal/assets/istio-test-resources.yaml +++ b/operator/internal/assets/istio-test-resources.yaml @@ -1,10 +1,3 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - kubernetes.io/metadata.name: istio-system - name: istio-system ---- apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: diff --git a/operator/internal/custom/istio_client.go b/operator/internal/custom/istio_client.go index 6e151bcf37..82842d8992 100644 --- a/operator/internal/custom/istio_client.go +++ b/operator/internal/custom/istio_client.go @@ -19,21 +19,23 @@ const ( firstElementIdx = 0 vsDeletionThreshold = 1 contractVersion = "v1" - virtualServiceName = "kcp-events" - gatewayName = "lifecycle-manager-kyma-gateway" ) type IstioClient struct { istioclient.Interface + virtualServiceName string + gatewayName string } -func NewVersionedIstioClient(cfg *rest.Config) (*IstioClient, error) { +func NewVersionedIstioClient(cfg *rest.Config, virtualServiceName, gatewayName string) (*IstioClient, error) { cs, err := istioclient.NewForConfig(cfg) if err != nil { return nil, err } return &IstioClient{ - Interface: cs, + Interface: cs, + virtualServiceName: virtualServiceName, + gatewayName: gatewayName, }, nil } @@ -45,7 +47,7 @@ type customClientErr struct { func (c *IstioClient) getVirtualService(ctx context.Context) (*istioclientapi.VirtualService, *customClientErr) { virtualService, err := c.NetworkingV1beta1(). VirtualServices(metav1.NamespaceDefault). - Get(ctx, virtualServiceName, metav1.GetOptions{}) + Get(ctx, c.virtualServiceName, metav1.GetOptions{}) if client.IgnoreNotFound(err) != nil { return nil, &customClientErr{ Err: fmt.Errorf("failed to fetch virtual service %w", err), @@ -61,21 +63,25 @@ func (c *IstioClient) getVirtualService(ctx context.Context) (*istioclientapi.Vi return virtualService, nil } -func (c *IstioClient) createVirtualService(ctx context.Context, obj *v1alpha1.Watcher, +func (c *IstioClient) createVirtualService(ctx context.Context, watcher *v1alpha1.Watcher, ) (*istioclientapi.VirtualService, error) { + if watcher == nil { + return &istioclientapi.VirtualService{}, nil + } _, err := c.NetworkingV1beta1(). Gateways(metav1.NamespaceDefault). - Get(ctx, gatewayName, metav1.GetOptions{}) + Get(ctx, c.gatewayName, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("error getting configured istio gateway: %w", err) } virtualSvc := &istioclientapi.VirtualService{} - virtualSvc.SetName(virtualServiceName) + virtualSvc.SetName(c.virtualServiceName) virtualSvc.SetNamespace(metav1.NamespaceDefault) - virtualSvc.Spec.Gateways = append(virtualSvc.Spec.Gateways, gatewayName) + virtualSvc.Spec.Gateways = append(virtualSvc.Spec.Gateways, c.gatewayName) virtualSvc.Spec.Hosts = append(virtualSvc.Spec.Hosts, "*") - istioHTTPRoute := prepareIstioHTTPRouteForCR(obj) - virtualSvc.Spec.Http = append(virtualSvc.Spec.Http, istioHTTPRoute) + virtualSvc.Spec.Http = []*istioapi.HTTPRoute{ + prepareIstioHTTPRouteForCR(watcher), + } return c.NetworkingV1beta1(). VirtualServices(metav1.NamespaceDefault). Create(ctx, virtualSvc, metav1.CreateOptions{}) @@ -99,7 +105,7 @@ func (c *IstioClient) IsListenerHTTPRouteConfigured(ctx context.Context, obj *v1 } for idx, route := range virtualService.Spec.Http { - if route.Name == obj.GetModuleName() { + if route.Name == client.ObjectKeyFromObject(obj).String() { istioHTTPRoute := prepareIstioHTTPRouteForCR(obj) return isRouteConfigEqual(virtualService.Spec.Http[idx], istioHTTPRoute), nil } @@ -111,43 +117,43 @@ func (c *IstioClient) IsListenerHTTPRouteConfigured(ctx context.Context, obj *v1 func (c *IstioClient) IsVsDeleted(ctx context.Context) (bool, error) { _, err := c.NetworkingV1beta1(). VirtualServices(metav1.NamespaceDefault). - Get(ctx, virtualServiceName, metav1.GetOptions{}) + Get(ctx, c.virtualServiceName, metav1.GetOptions{}) if apierrors.IsNotFound(err) { return true, nil } return false, err } -func (c *IstioClient) UpdateVirtualServiceConfig(ctx context.Context, obj *v1alpha1.Watcher, +func (c *IstioClient) UpdateVirtualServiceConfig(ctx context.Context, watcher *v1alpha1.Watcher, ) error { var err error var customErr *customClientErr var virtualService *istioclientapi.VirtualService virtualService, customErr = c.getVirtualService(ctx) if customErr != nil && customErr.IsNotFound { - _, err = c.createVirtualService(ctx, obj) + _, err = c.createVirtualService(ctx, watcher) if err != nil { return fmt.Errorf("failed to create virtual service %w", err) } return nil } // lookup cr config - routeIdx := lookupHTTPRouteByName(virtualService.Spec.Http, obj.GetModuleName()) + routeIdx := lookupHTTPRouteByObjectKey(virtualService.Spec.Http, client.ObjectKeyFromObject(watcher)) if routeIdx != -1 { - istioHTTPRoute := prepareIstioHTTPRouteForCR(obj) + istioHTTPRoute := prepareIstioHTTPRouteForCR(watcher) if isRouteConfigEqual(virtualService.Spec.Http[routeIdx], istioHTTPRoute) { return nil } - virtualService.Spec.Http[routeIdx] = prepareIstioHTTPRouteForCR(obj) + virtualService.Spec.Http[routeIdx] = prepareIstioHTTPRouteForCR(watcher) return c.updateVirtualService(ctx, virtualService) } // if route doesn't exist already append it to the route list - istioHTTPRoute := prepareIstioHTTPRouteForCR(obj) + istioHTTPRoute := prepareIstioHTTPRouteForCR(watcher) virtualService.Spec.Http = append(virtualService.Spec.Http, istioHTTPRoute) return c.updateVirtualService(ctx, virtualService) } -func (c *IstioClient) RemoveVirtualServiceConfigForCR(ctx context.Context, obj *v1alpha1.Watcher, +func (c *IstioClient) RemoveVirtualServiceConfigForCR(ctx context.Context, watcherObjKey client.ObjectKey, ) error { virtualService, customErr := c.getVirtualService(ctx) if customErr != nil { @@ -157,25 +163,26 @@ func (c *IstioClient) RemoveVirtualServiceConfigForCR(ctx context.Context, obj * // last http route is being deleted: remove the virtual service resource return c.NetworkingV1beta1(). VirtualServices(metav1.NamespaceDefault). - Delete(ctx, virtualServiceName, metav1.DeleteOptions{}) + Delete(ctx, c.virtualServiceName, metav1.DeleteOptions{}) } - routeIdx := lookupHTTPRouteByName(virtualService.Spec.Http, obj.GetModuleName()) - if routeIdx != -1 { - l := len(virtualService.Spec.Http) - copy(virtualService.Spec.Http[routeIdx:], virtualService.Spec.Http[routeIdx+1:]) - virtualService.Spec.Http[l-1] = nil - virtualService.Spec.Http = virtualService.Spec.Http[:l-1] + routeIdx := lookupHTTPRouteByObjectKey(virtualService.Spec.Http, watcherObjKey) + if routeIdx == -1 { + return nil } + l := len(virtualService.Spec.Http) + copy(virtualService.Spec.Http[routeIdx:], virtualService.Spec.Http[routeIdx+1:]) + virtualService.Spec.Http[l-1] = nil + virtualService.Spec.Http = virtualService.Spec.Http[:l-1] return c.updateVirtualService(ctx, virtualService) } -func lookupHTTPRouteByName(routes []*istioapi.HTTPRoute, name string) int { +func lookupHTTPRouteByObjectKey(routes []*istioapi.HTTPRoute, watcherObjKey client.ObjectKey) int { if len(routes) == 0 { return -1 } for idx, route := range routes { - if route.Name == name { + if route.Name == watcherObjKey.String() { return idx } } @@ -203,7 +210,7 @@ func isRouteConfigEqual(route1 *istioapi.HTTPRoute, route2 *istioapi.HTTPRoute) func prepareIstioHTTPRouteForCR(obj *v1alpha1.Watcher) *istioapi.HTTPRoute { return &istioapi.HTTPRoute{ - Name: obj.GetModuleName(), + Name: client.ObjectKeyFromObject(obj).String(), Match: []*istioapi.HTTPMatchRequest{ { Uri: &istioapi.StringMatch{ diff --git a/operator/internal/deploy/chart_manager.go b/operator/internal/deploy/chart_manager.go new file mode 100644 index 0000000000..2988ae4d30 --- /dev/null +++ b/operator/internal/deploy/chart_manager.go @@ -0,0 +1,221 @@ +package deploy + +import ( + "context" + "errors" + "fmt" + "net" + "strconv" + "time" + + "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" + "github.com/kyma-project/lifecycle-manager/operator/pkg/remote" + modulelib "github.com/kyma-project/module-manager/operator/pkg/manifest" + corev1 "k8s.io/api/core/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + k8syaml "sigs.k8s.io/yaml" +) + +var ErrExpectedExactlyOneSKRConfig = errors.New("expected exactly one SKR config") + +type SKRWebhookChartManager interface { + InstallWebhookChart(ctx context.Context, kyma *v1alpha1.Kyma, + remoteClientCache *remote.ClientCache, kcpClient client.Client) (bool, error) + RemoveWebhookChart(ctx context.Context, kyma *v1alpha1.Kyma, + syncCtx *remote.KymaSynchronizationContext) error +} + +type DisabledSKRWebhookChartManager struct{} + +//nolint:ireturn +func ResolveSKRWebhookChartManager(isWatcherEnabled bool, skrConfigs ...*SkrChartConfig, +) (SKRWebhookChartManager, error) { + if isWatcherEnabled && len(skrConfigs) != 1 { + return nil, ErrExpectedExactlyOneSKRConfig + } + if !isWatcherEnabled { + return &DisabledSKRWebhookChartManager{}, nil + } + + return NewEnabledSKRWebhookChartManager(skrConfigs[0]), nil +} + +func (m *DisabledSKRWebhookChartManager) InstallWebhookChart(_ context.Context, _ *v1alpha1.Kyma, + _ *remote.ClientCache, _ client.Client, +) (bool, error) { + return false, nil +} + +func (m *DisabledSKRWebhookChartManager) RemoveWebhookChart(_ context.Context, _ *v1alpha1.Kyma, + _ *remote.KymaSynchronizationContext, +) error { + return nil +} + +type EnabledSKRWebhookChartManager struct { + cache *SkrChartClientCache + config *SkrChartConfig + kcpAddr string +} + +type SkrChartConfig struct { + // WebhookChartPath represents the path of the webhook chart + // to be installed on SKR clusters upon reconciling kyma CRs. + WebhookChartPath string + SkrWebhookMemoryLimits string + SkrWebhookCPULimits string +} + +func NewEnabledSKRWebhookChartManager(config *SkrChartConfig) *EnabledSKRWebhookChartManager { + return &EnabledSKRWebhookChartManager{ + cache: NewSKRChartClientCache(), + config: config, + } +} + +func (m *EnabledSKRWebhookChartManager) InstallWebhookChart(ctx context.Context, kyma *v1alpha1.Kyma, + remoteClientCache *remote.ClientCache, kcpClient client.Client, +) (bool, error) { + skrClient, err := remote.NewRemoteClient(ctx, kcpClient, client.ObjectKeyFromObject(kyma), + kyma.Spec.Sync.Strategy, remoteClientCache) + if err != nil { + return true, err + } + skrCfg, err := remote.GetRemoteRestConfig(ctx, kcpClient, client.ObjectKeyFromObject(kyma), + kyma.Spec.Sync.Strategy) + if err != nil { + return true, err + } + argsVals, err := m.generateHelmChartArgs(ctx, kcpClient) + if err != nil { + return true, err + } + // TODO(khlifi411): make sure that validating-webhook-config resource is in sync with the secret configuration + skrWatcherInstallInfo := prepareInstallInfo(ctx, m.config.WebhookChartPath, ReleaseName, skrCfg, skrClient, argsVals) + err = m.installOrRemoveChartOnSKR(ctx, skrWatcherInstallInfo, ModeInstall) + if err != nil { + return true, err + } + kyma.UpdateCondition(v1alpha1.ConditionReasonSKRWebhookIsReady, metav1.ConditionTrue) + return false, nil +} + +func (m *EnabledSKRWebhookChartManager) RemoveWebhookChart(ctx context.Context, kyma *v1alpha1.Kyma, + syncCtx *remote.KymaSynchronizationContext, +) error { + skrCfg, err := remote.GetRemoteRestConfig(ctx, syncCtx.ControlPlaneClient, client.ObjectKeyFromObject(kyma), + kyma.Spec.Sync.Strategy) + if err != nil { + return err + } + argsVals, err := m.generateHelmChartArgs(ctx, syncCtx.ControlPlaneClient) + if err != nil { + return err + } + skrWatcherInstallInfo := prepareInstallInfo(ctx, m.config.WebhookChartPath, ReleaseName, skrCfg, + syncCtx.RuntimeClient, argsVals) + return m.installOrRemoveChartOnSKR(ctx, skrWatcherInstallInfo, ModeUninstall) +} + +func (m *EnabledSKRWebhookChartManager) generateHelmChartArgs(ctx context.Context, + kcpClient client.Client, +) (map[string]interface{}, error) { + watcherList := &v1alpha1.WatcherList{} + if err := kcpClient.List(ctx, watcherList, &client.ListOptions{}); err != nil { + return nil, fmt.Errorf("error listing watcher resources: %w", err) + } + if len(watcherList.Items) == 0 { + return nil, ErrFoundZeroWatchers + } + chartCfg := generateWatchableConfigs(watcherList) + bytes, err := k8syaml.Marshal(chartCfg) + if err != nil { + return nil, err + } + + kcpAddr, err := m.resolveKcpAddr(ctx, kcpClient) + if err != nil { + return nil, err + } + return map[string]interface{}{ + "triggerLabel": time.Now().Format(triggerLabelTimeFormat), + "kcpAddr": kcpAddr, + "resourcesLimitsMemory": m.config.SkrWebhookMemoryLimits, + "resourcesLimitsCPU": m.config.SkrWebhookCPULimits, + customConfigKey: string(bytes), + }, nil +} + +func (m *EnabledSKRWebhookChartManager) resolveKcpAddr(ctx context.Context, kcpClient client.Client) (string, error) { + if m.kcpAddr != "" { + return m.kcpAddr, nil + } + // Get external IP from the ISTIO load balancer external IP + loadBalancerService := &corev1.Service{} + if err := kcpClient.Get(ctx, client.ObjectKey{Name: IngressServiceName, Namespace: IstioSytemNs}, + loadBalancerService); err != nil { + return "", err + } + if len(loadBalancerService.Status.LoadBalancer.Ingress) == 0 { + return "", ErrLoadBalancerIPIsNotAssigned + } + externalIP := loadBalancerService.Status.LoadBalancer.Ingress[0].IP + var port int32 + for _, loadBalancerPort := range loadBalancerService.Spec.Ports { + if loadBalancerPort.Name == "http2" { + port = loadBalancerPort.Port + break + } + } + m.kcpAddr = net.JoinHostPort(externalIP, strconv.Itoa(int(port))) + return m.kcpAddr, nil +} + +func generateWatchableConfigs(watcherList *v1alpha1.WatcherList) map[string]WatchableConfig { + chartCfg := make(map[string]WatchableConfig, len(watcherList.Items)) + for _, watcher := range watcherList.Items { + statusOnly := watcher.Spec.Field == v1alpha1.StatusField + chartCfg[watcher.GetModuleName()] = WatchableConfig{ + Labels: watcher.Spec.LabelsToWatch, + StatusOnly: statusOnly, + } + } + return chartCfg +} + +func (m *EnabledSKRWebhookChartManager) installOrRemoveChartOnSKR(ctx context.Context, + deployInfo modulelib.InstallInfo, mode Mode, +) error { + logger := logf.FromContext(ctx) + if mode == ModeUninstall { + uninstalled, err := modulelib.UninstallChart(&logger, deployInfo, nil, nil) + if err != nil { + return fmt.Errorf("failed to uninstall webhook config: %w", err) + } + if !uninstalled { + return ErrSKRWebhookWasNotRemoved + } + + return nil + } + // TODO(khlifi411): verify webhook configuration with watchers' configuration before re-installing the chart + ready, err := modulelib.ConsistencyCheck(&logger, deployInfo, nil, nil) + if err != nil { + return fmt.Errorf("failed to verify webhook resources: %w", err) + } + if ready { + logger.V(1).Info("chart resources already installed, nothing to do!") + return nil + } + installed, err := modulelib.InstallChart(&logger, deployInfo, nil, nil) + if err != nil { + return fmt.Errorf("failed to install webhook config: %w", err) + } + if !installed { + return ErrSKRWebhookHasNotBeenInstalled + } + return nil +} diff --git a/operator/internal/deploy/deploy_suite_test.go b/operator/internal/deploy/deploy_suite_test.go deleted file mode 100644 index 4775bca976..0000000000 --- a/operator/internal/deploy/deploy_suite_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package deploy_test - -import ( - "context" - "net/http" - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - yaml "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - kyma "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" - //+kubebuilder:scaffold:imports -) - -func TestAPIs(t *testing.T) { - t.Parallel() - RegisterFailHandler(Fail) - - RunSpecs(t, "Webhook Deploy Suite") -} - -var ( - ctx context.Context //nolint:gochecknoglobals - testEnv *envtest.Environment //nolint:gochecknoglobals - k8sClient client.Client //nolint:gochecknoglobals -) - -var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) - ctx = context.Background() - - By("preparing required CRDs") - resp, err := http.Get("https://raw.githubusercontent.com/kyma-project/lifecycle-manager/" + - "main/operator/config/crd/bases/operator.kyma-project.io_kymas.yaml") - Expect(err).ToNot(HaveOccurred()) - Expect(resp.StatusCode).To(Equal(http.StatusOK)) - defer resp.Body.Close() - kymaCrd := &apiextv1.CustomResourceDefinition{} - err = yaml.NewYAMLOrJSONDecoder(resp.Body, 2048).Decode(kymaCrd) - Expect(err).ToNot(HaveOccurred()) - - By("bootstrapping test environment for webhook deployment tests") - testEnv = &envtest.Environment{ - CRDs: []*apiextv1.CustomResourceDefinition{kymaCrd}, - } - - cfg, err := testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) - - Expect(kyma.AddToScheme(scheme.Scheme)).To(Succeed()) - - //+kubebuilder:scaffold:scheme - - k8sClient, err = client.New(cfg, client.Options{}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - Expect(testEnv.Stop()).To(Succeed()) -}) diff --git a/operator/internal/deploy/helm_client_cache.go b/operator/internal/deploy/helm_client_cache.go new file mode 100644 index 0000000000..87520fe860 --- /dev/null +++ b/operator/internal/deploy/helm_client_cache.go @@ -0,0 +1,34 @@ +package deploy + +import ( + "sync" + + moduletypes "github.com/kyma-project/module-manager/operator/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type SkrChartClientCache struct { + cache *sync.Map +} + +func NewSKRChartClientCache() *SkrChartClientCache { + return &SkrChartClientCache{ + cache: &sync.Map{}, + } +} + +func (sc *SkrChartClientCache) Get(key client.ObjectKey) moduletypes.HelmClient { + value, ok := sc.cache.Load(key) + if !ok { + return nil + } + return value.(moduletypes.HelmClient) +} + +func (sc *SkrChartClientCache) Set(key client.ObjectKey, helmClient moduletypes.HelmClient) { + sc.cache.Store(key, helmClient) +} + +func (sc *SkrChartClientCache) Delete(key client.ObjectKey) { + sc.cache.Delete(key) +} diff --git a/operator/internal/deploy/webhook_chart.go b/operator/internal/deploy/webhook_chart.go index 039cf25a9b..a09613a9ee 100644 --- a/operator/internal/deploy/webhook_chart.go +++ b/operator/internal/deploy/webhook_chart.go @@ -4,16 +4,10 @@ import ( "context" "errors" "fmt" - "net" - "strconv" - v1 "k8s.io/api/core/v1" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" - k8syaml "sigs.k8s.io/yaml" - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" moduleLib "github.com/kyma-project/module-manager/operator/pkg/manifest" moduleLibTypes "github.com/kyma-project/module-manager/operator/pkg/types" ) @@ -21,57 +15,30 @@ import ( type Mode string const ( - ModeInstall = Mode("install") - ModeUninstall = Mode("uninstall") - customConfigKey = "modules" - kubeconfigKey = "config" - servicePathTpl = "/validate/%s" - webhookNameTpl = "%s.operator.kyma-project.io" - ReleaseName = "skr" - specSubresources = "*" - statusSubresources = "*/status" - configuredWebhooksDeletionThreshold = 1 - expectedWebhookNamePartsLength = 4 - IstioSytemNs = "istio-system" - IngressServiceName = "istio-ingressgateway" + ModeInstall = Mode("install") + ModeUninstall = Mode("uninstall") + customConfigKey = "modules" + ReleaseName = "skr" + IstioSytemNs = "istio-system" + IngressServiceName = "istio-ingressgateway" + DeploymentNameTpl = "%s-webhook" + triggerLabelTimeFormat = "200601021504050700" ) var ( - ErrSKRWebhookNotReady = errors.New("installed skr webhook resources are not ready") ErrSKRWebhookHasNotBeenInstalled = errors.New("skr webhook resources have not been installed") ErrSKRWebhookWasNotRemoved = errors.New("installed skr webhook resources were not removed") ErrLoadBalancerIPIsNotAssigned = errors.New("load balancer service external ip is not assigned") + ErrFoundZeroWatchers = errors.New("found 0 watcher resources, expected at least 1") ) -func installSKRWebhook(ctx context.Context, chartPath, releaseName string, obj *v1alpha1.Watcher, - restConfig *rest.Config, kcpClient client.Client, skrWebhookMemoryLimits, skrWebhookCPULimits string, -) error { - restClient, err := client.New(restConfig, client.Options{}) - if err != nil { - return err - } - argsVals, err := generateHelmChartArgsForCR(ctx, obj, kcpClient, skrWebhookMemoryLimits, skrWebhookCPULimits) - if err != nil { - return err - } - skrWatcherInstallInfo := prepareInstallInfo(ctx, chartPath, releaseName, restConfig, restClient, argsVals) - return installOrRemoveChartOnSKR(ctx, skrWatcherInstallInfo, ModeInstall) +type WatchableConfig struct { + Labels map[string]string `json:"labels"` + StatusOnly bool `json:"statusOnly"` } -func removeSKRWebhook(ctx context.Context, chartPath, releaseName string, - obj *v1alpha1.Watcher, restConfig *rest.Config, kcpClient client.Client, - skrWebhookMemoryLimits, skrWebhookCPULimits string, -) error { - restClient, err := client.New(restConfig, client.Options{}) - if err != nil { - return err - } - argsVals, err := generateHelmChartArgsForCR(ctx, obj, kcpClient, skrWebhookMemoryLimits, skrWebhookCPULimits) - if err != nil { - return err - } - skrWatcherInstallInfo := prepareInstallInfo(ctx, chartPath, releaseName, restConfig, restClient, argsVals) - return installOrRemoveChartOnSKR(ctx, skrWatcherInstallInfo, ModeUninstall) +func ResolveSKRChartResourceName(resourceNameTpl string) string { + return fmt.Sprintf(resourceNameTpl, ReleaseName) } func prepareInstallInfo(ctx context.Context, chartPath, releaseName string, restConfig *rest.Config, @@ -92,84 +59,3 @@ func prepareInstallInfo(ctx context.Context, chartPath, releaseName string, rest }, } } - -func generateHelmChartArgsForCR(ctx context.Context, obj *v1alpha1.Watcher, kcpClient client.Client, - skrWebhookMemoryLimits string, skrWebhookCPULimits string, -) (map[string]interface{}, error) { - resolvedKcpAddr, err := resolveKcpAddr(ctx, kcpClient) - if err != nil { - return nil, err - } - chartCfg := generateWatchableConfigForCR(obj) - bytes, err := k8syaml.Marshal(chartCfg) - if err != nil { - return nil, err - } - return map[string]interface{}{ - "kcpAddr": resolvedKcpAddr, - "resourcesLimitsMemory": skrWebhookMemoryLimits, - "resourcesLimitsCPU": skrWebhookCPULimits, - customConfigKey: string(bytes), - }, nil -} - -func generateWatchableConfigForCR(obj *v1alpha1.Watcher) map[string]WatchableConfig { - statusOnly := obj.Spec.Field == v1alpha1.StatusField - return map[string]WatchableConfig{ - obj.GetModuleName(): { - Labels: obj.Spec.LabelsToWatch, - StatusOnly: statusOnly, - }, - } -} - -func installOrRemoveChartOnSKR(ctx context.Context, deployInfo moduleLib.InstallInfo, mode Mode, -) error { - logger := logf.FromContext(ctx) - if mode == ModeUninstall { - uninstalled, err := moduleLib.UninstallChart(&logger, deployInfo, nil, nil) - if err != nil { - return fmt.Errorf("failed to uninstall webhook config: %w", err) - } - if !uninstalled { - return ErrSKRWebhookWasNotRemoved - } - return nil - } - installed, err := moduleLib.InstallChart(&logger, deployInfo, nil, nil) - if err != nil { - return fmt.Errorf("failed to install webhook config: %w", err) - } - if !installed { - return ErrSKRWebhookHasNotBeenInstalled - } - ready, err := moduleLib.ConsistencyCheck(&logger, deployInfo, nil, nil) - if err != nil { - return fmt.Errorf("failed to verify webhook resources: %w", err) - } - if !ready { - return ErrSKRWebhookNotReady - } - return nil -} - -func resolveKcpAddr(ctx context.Context, kcpClient client.Client) (string, error) { - // Get external IP from the ISTIO load balancer external IP - loadBalancerService := &v1.Service{} - if err := kcpClient.Get(ctx, client.ObjectKey{Name: IngressServiceName, Namespace: IstioSytemNs}, - loadBalancerService); err != nil { - return "", err - } - if len(loadBalancerService.Status.LoadBalancer.Ingress) == 0 { - return "", ErrLoadBalancerIPIsNotAssigned - } - externalIP := loadBalancerService.Status.LoadBalancer.Ingress[0].IP - var port int32 - for _, loadBalancerPort := range loadBalancerService.Spec.Ports { - if loadBalancerPort.Name == "http2" { - port = loadBalancerPort.Port - break - } - } - return net.JoinHostPort(externalIP, strconv.Itoa(int(port))), nil -} diff --git a/operator/internal/deploy/webhook_config.go b/operator/internal/deploy/webhook_config.go deleted file mode 100644 index 92f2e94282..0000000000 --- a/operator/internal/deploy/webhook_config.go +++ /dev/null @@ -1,277 +0,0 @@ -package deploy - -import ( - "context" - "fmt" - "reflect" - "strings" - - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/tools/clientcmd" - "sigs.k8s.io/controller-runtime/pkg/client" - - admissionv1 "k8s.io/api/admissionregistration/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/rest" - - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" -) - -const ( - WebhookConfigNameTpl = "%s-webhook" - ServiceAccountNameTpl = "%s-webhook-sa" - //nolint:gosec - SecretNameTpl = "%s-webhook-tls" - ServiceAndDeploymentNameTpl = "%s-webhook" - ClusterRoleName = "kyma-reader" - ClusterRoleBindingName = "read-kymas" -) - -type WatchableConfig struct { - Labels map[string]string `json:"labels"` - StatusOnly bool `json:"statusOnly"` -} - -func UpdateWebhookConfig(ctx context.Context, chartPath string, obj *v1alpha1.Watcher, inClusterCfg *rest.Config, - k8sClient client.Client, skrWebhookMemoryLimits string, skrWebhookCPULimits string, -) error { - restCfgs, err := getSKRRestConfigs(ctx, k8sClient, inClusterCfg) - if err != nil { - return err - } - for _, restCfg := range restCfgs { - err = updateWebhookConfigOrInstallSKRChart(ctx, chartPath, obj, restCfg, k8sClient, - skrWebhookMemoryLimits, skrWebhookCPULimits) - if err != nil { - continue - } - } - // return err so that if err!=nil for at least one SKR, reconciliation will be retriggered after requeue interval - return err -} - -func RemoveWebhookConfig(ctx context.Context, chartPath string, obj *v1alpha1.Watcher, inClusterCfg *rest.Config, - k8sClient client.Client, skrWebhookMemoryLimits string, skrWebhookCPULimits string, -) error { - restCfgs, err := getSKRRestConfigs(ctx, k8sClient, inClusterCfg) - if err != nil { - return err - } - for _, restCfg := range restCfgs { - err = removeWebhookConfigOrUninstallChart(ctx, chartPath, obj, restCfg, k8sClient, - skrWebhookMemoryLimits, skrWebhookCPULimits) - if err != nil { - continue - } - } - // return err so that if err!=nil for at least one SKR, reconciliation will be triggered after requeue interval - return err -} - -func IsWebhookConfigured(obj *v1alpha1.Watcher, webhookConfig *admissionv1.ValidatingWebhookConfiguration) bool { - if len(webhookConfig.Webhooks) < 1 { - return false - } - idx := lookupWebhookConfigForCR(webhookConfig.Webhooks, obj) - if idx != -1 { - // TODO: replace with deepequal? - return verifyWebhookConfig(webhookConfig.Webhooks[idx], obj) - } - return false -} - -func GetDeployedWebhook(ctx context.Context, restConfig *rest.Config, -) (*admissionv1.ValidatingWebhookConfiguration, error) { - remoteClient, err := client.New(restConfig, client.Options{}) - if err != nil { - return nil, err - } - webhookConfig := &admissionv1.ValidatingWebhookConfiguration{} - err = remoteClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: ResolveSKRChartResourceName(WebhookConfigNameTpl), - }, webhookConfig) - if err != nil { - return nil, err - } - return webhookConfig, nil -} - -func verifyWebhookConfig( - webhook admissionv1.ValidatingWebhook, - watcherCR *v1alpha1.Watcher, -) bool { - webhookNameParts := strings.Split(webhook.Name, ".") - if len(webhookNameParts) != expectedWebhookNamePartsLength { - return false - } - moduleName := webhookNameParts[0] - expectedModuleName, exists := watcherCR.Labels[v1alpha1.ManagedBylabel] - if !exists { - return false - } - if moduleName != expectedModuleName { - return false - } - if *webhook.ClientConfig.Service.Path != fmt.Sprintf(servicePathTpl, moduleName) { - return false - } - - if !reflect.DeepEqual(webhook.ObjectSelector.MatchLabels, watcherCR.Spec.LabelsToWatch) { - return false - } - if watcherCR.Spec.Field == v1alpha1.StatusField && webhook.Rules[0].Resources[0] != statusSubresources { - return false - } - if watcherCR.Spec.Field == v1alpha1.SpecField && webhook.Rules[0].Resources[0] != specSubresources { - return false - } - - return true -} - -func updateWebhookConfigOrInstallSKRChart(ctx context.Context, chartPath string, obj *v1alpha1.Watcher, - restConfig *rest.Config, kcpClient client.Client, skrWebhookMemoryLimits string, skrWebhookCPULimits string, -) error { - remoteClient, err := client.New(restConfig, client.Options{}) - if err != nil { - return err - } - - webhookConfig := &admissionv1.ValidatingWebhookConfiguration{} - err = remoteClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: ResolveSKRChartResourceName(WebhookConfigNameTpl), - }, webhookConfig) - if client.IgnoreNotFound(err) != nil { - return err - } - if apierrors.IsNotFound(err) { - // install chart - return installSKRWebhook(ctx, chartPath, ReleaseName, obj, restConfig, kcpClient, - skrWebhookMemoryLimits, skrWebhookCPULimits) - } - // generate webhook config from CR and update webhook config resource - if len(webhookConfig.Webhooks) < 1 { - //nolint:goerr113 - return fmt.Errorf("failed to get base webhook config") - } - idx := lookupWebhookConfigForCR(webhookConfig.Webhooks, obj) - if idx != -1 { - // update existing webhook - webhookConfig.Webhooks[idx] = generateWebhookConfigForCR(webhookConfig.Webhooks[idx], obj) - return remoteClient.Update(ctx, webhookConfig) - } - - webhookConfig.Webhooks = append(webhookConfig.Webhooks, generateWebhookConfigForCR(webhookConfig.Webhooks[0], obj)) - return remoteClient.Update(ctx, webhookConfig) -} - -func lookupWebhookConfigForCR(webhooks []admissionv1.ValidatingWebhook, obj *v1alpha1.Watcher) int { - cfgIdx := -1 - for idx, webhook := range webhooks { - webhookNameParts := strings.Split(webhook.Name, ".") - if len(webhookNameParts) == 0 { - continue - } - moduleName := webhookNameParts[0] - objModuleName := obj.GetModuleName() - if moduleName == objModuleName { - return idx - } - } - return cfgIdx -} - -func generateWebhookConfigForCR(baseCfg admissionv1.ValidatingWebhook, obj *v1alpha1.Watcher, -) admissionv1.ValidatingWebhook { - watcherCrWebhookCfg := baseCfg.DeepCopy() - moduleName := obj.GetModuleName() - watcherCrWebhookCfg.Name = fmt.Sprintf(webhookNameTpl, moduleName) - // fixme: if LabelsToWatch is nil: make sure that ObjectSelector is nil - if obj.Spec.LabelsToWatch != nil { - watcherCrWebhookCfg.ObjectSelector.MatchLabels = obj.Spec.LabelsToWatch - } - servicePath := fmt.Sprintf(servicePathTpl, moduleName) - watcherCrWebhookCfg.ClientConfig.Service.Path = &servicePath - if obj.Spec.Field == v1alpha1.StatusField { - watcherCrWebhookCfg.Rules[0].Resources[0] = statusSubresources - return *watcherCrWebhookCfg - } - watcherCrWebhookCfg.Rules[0].Resources[0] = specSubresources - return *watcherCrWebhookCfg -} - -func removeWebhookConfigOrUninstallChart(ctx context.Context, chartPath string, - obj *v1alpha1.Watcher, restConfig *rest.Config, kcpClient client.Client, - skrWebhookMemoryLimits, skrWebhookCPULimits string, -) error { - remoteClient, err := client.New(restConfig, client.Options{}) - if err != nil { - return err - } - webhookConfig := &admissionv1.ValidatingWebhookConfiguration{} - err = remoteClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: ResolveSKRChartResourceName(WebhookConfigNameTpl), - }, webhookConfig) - if client.IgnoreNotFound(err) != nil { - return err - } - if apierrors.IsNotFound(err) { - return nil - } - numberOfWebhooks := len(webhookConfig.Webhooks) - if numberOfWebhooks <= configuredWebhooksDeletionThreshold { - // this watcher CR is the latest CR configured on the SKR webhook - // uninstall the webhook chart - return removeSKRWebhook(ctx, chartPath, ReleaseName, obj, restConfig, kcpClient, - skrWebhookMemoryLimits, skrWebhookCPULimits) - } - cfgIdx := lookupWebhookConfigForCR(webhookConfig.Webhooks, obj) - if cfgIdx != -1 { - // remove corresponding config from webhook config resource - copy(webhookConfig.Webhooks[cfgIdx:], webhookConfig.Webhooks[cfgIdx+1:]) - webhookConfig.Webhooks[numberOfWebhooks-1] = admissionv1.ValidatingWebhook{} - webhookConfig.Webhooks = webhookConfig.Webhooks[:len(webhookConfig.Webhooks)-1] - return remoteClient.Update(ctx, webhookConfig) - } - return nil -} - -func getSKRRestConfigs(ctx context.Context, reader client.Reader, inClusterCfg *rest.Config, -) (map[string]*rest.Config, error) { - kymaCRs := &v1alpha1.KymaList{} - err := reader.List(ctx, kymaCRs) - if err != nil { - return nil, err - } - if len(kymaCRs.Items) == 0 { - //nolint:goerr113 - return nil, fmt.Errorf("no kymas found") - } - restCfgMap := make(map[string]*rest.Config, len(kymaCRs.Items)) - for _, kymaCr := range kymaCRs.Items { - if kymaCr.Spec.Sync.Strategy == v1alpha1.SyncStrategyLocalClient || !kymaCr.Spec.Sync.Enabled { - restCfgMap[kymaCr.Name] = inClusterCfg - continue - } - secret := &corev1.Secret{} - //nolint:gosec - err = reader.Get(ctx, client.ObjectKeyFromObject(&kymaCr), secret) - if err != nil { - return nil, err - } - restCfg, err := clientcmd.RESTConfigFromKubeConfig(secret.Data[kubeconfigKey]) - if err == nil { - restCfgMap[kymaCr.Name] = restCfg - } - } - - return restCfgMap, nil -} - -func ResolveSKRChartResourceName(resourceNameTpl string) string { - return fmt.Sprintf(resourceNameTpl, ReleaseName) -} diff --git a/operator/internal/deploy/webhook_config_test.go b/operator/internal/deploy/webhook_config_test.go deleted file mode 100644 index 9e4c977bd6..0000000000 --- a/operator/internal/deploy/webhook_config_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package deploy_test - -import ( - "context" - "fmt" - "os" - "path/filepath" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" - "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" - . "github.com/kyma-project/lifecycle-manager/operator/internal/testutils" -) - -const webhookChartPath = "../charts/skr-webhook" - -func createIstioNs() error { - istioNs := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: deploy.IstioSytemNs, - }, - } - if err := k8sClient.Create(ctx, istioNs); err != nil && !errors.IsAlreadyExists(err) { - return err - } - - return nil -} - -var _ = Describe("deploy watcher", Ordered, func() { - ctx := context.TODO() - moduleName := "lifecyle-manager" - watcherCR := &v1alpha1.Watcher{ - TypeMeta: metav1.TypeMeta{ - Kind: string(v1alpha1.WatcherKind), - APIVersion: v1alpha1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-sample", moduleName), - Namespace: metav1.NamespaceDefault, - Labels: map[string]string{ - v1alpha1.ManagedBylabel: moduleName, - }, - }, - Spec: v1alpha1.WatcherSpec{ - ServiceInfo: v1alpha1.Service{ - Port: 8082, - Name: fmt.Sprintf("%s-svc", moduleName), - Namespace: metav1.NamespaceDefault, - }, - LabelsToWatch: map[string]string{ - fmt.Sprintf("%s-watchable", moduleName): "true", - }, - Field: v1alpha1.StatusField, - }, - } - kymaSample := &v1alpha1.Kyma{} - BeforeAll(func() { - kymaName := "kyma-sample" - kymaSample = CreateKymaCR(kymaName) - Expect(createIstioNs()).To(Succeed()) - Expect(k8sClient.Create(ctx, kymaSample)).To(Succeed()) - Expect(CreateLoadBalancer(ctx, k8sClient)).To(Succeed()) - }) - - BeforeEach(func() { - // clean rendered manifest - Expect(os.RemoveAll(filepath.Join(webhookChartPath, RenderedManifestDir))).ShouldNot(HaveOccurred()) - }) - - AfterAll(func() { - // clean up kyma CR - Expect(k8sClient.Delete(ctx, kymaSample)).To(Succeed()) - // clean rendered manifest - Expect(os.RemoveAll(filepath.Join(webhookChartPath, RenderedManifestDir))).ShouldNot(HaveOccurred()) - }) - - It("deploys watcher helm chart with correct webhook config", func() { - err := deploy.UpdateWebhookConfig(ctx, webhookChartPath, watcherCR, testEnv.Config, k8sClient, "500Mi", "1") - Expect(err).ShouldNot(HaveOccurred()) - webhookCfg, err := deploy.GetDeployedWebhook(ctx, testEnv.Config) - Expect(err).NotTo(HaveOccurred()) - Expect(deploy.IsWebhookConfigured(watcherCR, webhookCfg)).To(BeTrue()) - }) - - It("updates webhook config when helm chart is already installed", func() { - watcherCR.Spec.Field = v1alpha1.SpecField - err := deploy.UpdateWebhookConfig(ctx, webhookChartPath, watcherCR, testEnv.Config, k8sClient, "500Mi", "1") - Expect(err).ShouldNot(HaveOccurred()) - webhookCfg, err := deploy.GetDeployedWebhook(ctx, testEnv.Config) - Expect(err).NotTo(HaveOccurred()) - Expect(deploy.IsWebhookConfigured(watcherCR, webhookCfg)).To(BeTrue()) - }) - - It("removes watcher helm chart from SKR cluster when last cr is deleted", func() { - err := deploy.RemoveWebhookConfig(ctx, webhookChartPath, watcherCR, testEnv.Config, k8sClient, "500Mi", "1") - Expect(err).ShouldNot(HaveOccurred()) - Eventually(IsChartRemoved(ctx, k8sClient), Timeout, Interval).Should(BeTrue()) - }) -}) diff --git a/operator/internal/testutils/utils.go b/operator/internal/testutils/utils.go index 49f697ce4e..c86ad6ee13 100644 --- a/operator/internal/testutils/utils.go +++ b/operator/internal/testutils/utils.go @@ -2,149 +2,139 @@ package testutils import ( "context" + "errors" + "fmt" + "io" + "math/rand" + "net/http" + "net/url" "time" - admissionv1 "k8s.io/api/admissionregistration/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" - "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + "github.com/kyma-project/lifecycle-manager/operator/pkg/test" + "github.com/onsi/gomega" + + v12 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( - RenderedManifestDir = "manifest" - Timeout = time.Second * 10 - Interval = time.Millisecond * 250 - defaultHTTPPort = 80 - servicePort = 8080 + randomStringLength = 8 + letterBytes = "abcdefghijklmnopqrstuvwxyz" + defaultBufferSize = 2048 + httpClientTimeout = 2 * time.Second + Timeout = time.Second * 10 + Interval = time.Millisecond * 250 ) -func IsChartRemoved(ctx context.Context, k8sClient client.Client) func() bool { - return func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ResolveSKRChartResourceName(deploy.WebhookConfigNameTpl), - }, &admissionv1.ValidatingWebhookConfiguration{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ResolveSKRChartResourceName(deploy.SecretNameTpl), - }, &corev1.Secret{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ResolveSKRChartResourceName(deploy.ServiceAndDeploymentNameTpl), - }, &appsv1.Deployment{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ResolveSKRChartResourceName(deploy.ServiceAndDeploymentNameTpl), - }, &corev1.Service{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ResolveSKRChartResourceName(deploy.ServiceAccountNameTpl), - }, &corev1.ServiceAccount{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ClusterRoleName, - }, &rbacv1.ClusterRole{}) - if !apierrors.IsNotFound(err) { - return false - } - err = k8sClient.Get(ctx, client.ObjectKey{ - Namespace: metav1.NamespaceDefault, - Name: deploy.ClusterRoleBindingName, - }, &rbacv1.ClusterRoleBinding{}) - return apierrors.IsNotFound(err) +func NewTestKyma(name string) *v1alpha1.Kyma { + return &v1alpha1.Kyma{ + TypeMeta: v1.TypeMeta{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: string(v1alpha1.KymaKind), + }, + ObjectMeta: v1.ObjectMeta{ + Name: name + RandString(randomStringLength), + Namespace: v1.NamespaceDefault, + }, + Spec: v1alpha1.KymaSpec{ + Modules: []v1alpha1.Module{}, + Channel: v1alpha1.DefaultChannel, + }, } } -func CreateLoadBalancer(ctx context.Context, controlPlaneClient client.Client) error { - loadBalancerService := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: deploy.IngressServiceName, - Namespace: deploy.IstioSytemNs, - Labels: map[string]string{ - "app": deploy.IngressServiceName, - }, - }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - Ports: []corev1.ServicePort{ - { - Name: "http2", - Protocol: corev1.ProtocolTCP, - Port: defaultHTTPPort, - TargetPort: intstr.FromInt(servicePort), - }, - }, - }, +func NewUniqModuleName() string { + return RandString(randomStringLength) +} + +func RandString(n int) string { + b := make([]byte, n) + for i := range b { + b[i] = letterBytes[rand.Intn(len(letterBytes))] //nolint:gosec } + return string(b) +} - if err := controlPlaneClient.Create(ctx, loadBalancerService); err != nil { - return err +func DeployModuleTemplates(ctx context.Context, kcpClient client.Client, kyma *v1alpha1.Kyma) { + for _, module := range kyma.Spec.Modules { + template, err := test.ModuleTemplateFactory(module, unstructured.Unstructured{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + gomega.Expect(kcpClient.Create(ctx, template)).To(gomega.Succeed()) } - loadBalancerService.Status = corev1.ServiceStatus{ - LoadBalancer: corev1.LoadBalancerStatus{ - Ingress: []corev1.LoadBalancerIngress{ - { - IP: "10.10.10.167", - }, - }, - }, +} + +func DeleteModuleTemplates(ctx context.Context, kcpClient client.Client, kyma *v1alpha1.Kyma) { + for _, module := range kyma.Spec.Modules { + template, err := test.ModuleTemplateFactory(module, unstructured.Unstructured{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + gomega.Expect(kcpClient.Delete(ctx, template)).To(gomega.Succeed()) } - if err := controlPlaneClient.Status().Update(ctx, loadBalancerService); err != nil { - return err +} + +func GetKyma(ctx context.Context, testClient client.Client, kymaName string) (*v1alpha1.Kyma, error) { + kymaInCluster := &v1alpha1.Kyma{} + err := testClient.Get(ctx, client.ObjectKey{ + Namespace: v1.NamespaceDefault, + Name: kymaName, + }, kymaInCluster) + if err != nil { + return nil, err } + return kymaInCluster, nil +} - return controlPlaneClient.Get(ctx, client.ObjectKey{ - Name: deploy.IngressServiceName, - Namespace: deploy.IstioSytemNs, - }, loadBalancerService) +func IsKymaInState(ctx context.Context, kcpClient client.Client, kymaName string, state v1alpha1.State) func() bool { + return func() bool { + kymaFromCluster, err := GetKyma(ctx, kcpClient, kymaName) + if err != nil || kymaFromCluster.Status.State != state { + return false + } + return true + } } -func CreateKymaCR(kymaName string) *v1alpha1.Kyma { - return &v1alpha1.Kyma{ - TypeMeta: metav1.TypeMeta{ - Kind: string(v1alpha1.KymaKind), - APIVersion: v1alpha1.GroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: kymaName, - Namespace: metav1.NamespaceDefault, - }, - Spec: v1alpha1.KymaSpec{ - Channel: v1alpha1.ChannelStable, - Modules: []v1alpha1.Module{ - { - Name: "sample-skr-module", - }, - { - Name: "sample-kcp-module", - }, - }, - Sync: v1alpha1.Sync{ - Enabled: false, - Strategy: v1alpha1.SyncStrategyLocalClient, - }, - }, +func ParseRemoteCRDs(testCrdURLs []string) ([]*v12.CustomResourceDefinition, error) { + var crds []*v12.CustomResourceDefinition + var httpResponse *http.Response + for _, testCrdURL := range testCrdURLs { + _, err := url.Parse(testCrdURL) + if err != nil { + return nil, err + } + request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, testCrdURL, nil) + if err != nil { + return nil, fmt.Errorf("failed pulling content for URL (%s) :%w", testCrdURL, err) + } + httpClient := &http.Client{Timeout: httpClientTimeout} + httpResponse, err = httpClient.Do(request) + if err != nil { + return nil, err + } + if httpResponse.StatusCode != http.StatusOK { + //nolint:goerr113 + return nil, fmt.Errorf("failed pulling content for URL (%s) with status code: %d", + testCrdURL, httpResponse.StatusCode) + } + + decoder := yaml.NewYAMLOrJSONDecoder(httpResponse.Body, defaultBufferSize) + for { + crd := &v12.CustomResourceDefinition{} + err = decoder.Decode(crd) + if err == nil { + crds = append(crds, crd) + } + if errors.Is(err, io.EOF) { + break + } + } } + defer func() { + _ = httpResponse.Body.Close() + }() + return crds, nil } diff --git a/operator/main.go b/operator/main.go index 0682253157..1ab3a5157a 100644 --- a/operator/main.go +++ b/operator/main.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "github.com/kyma-project/lifecycle-manager/operator/internal/deploy" + "github.com/kyma-project/lifecycle-manager/operator/pkg/remote" "github.com/kyma-project/lifecycle-manager/operator/pkg/signature" "go.uber.org/zap/zapcore" @@ -49,6 +51,7 @@ import ( operatorv1alpha1 "github.com/kyma-project/lifecycle-manager/operator/api/v1alpha1" "github.com/kyma-project/lifecycle-manager/operator/controllers" moduleManagerV1alpha1 "github.com/kyma-project/module-manager/operator/api/v1alpha1" + //+kubebuilder:scaffold:imports "github.com/go-logr/logr" "github.com/go-logr/zapr" @@ -97,6 +100,8 @@ type FlagVar struct { skrWatcherPath string skrWebhookMemoryLimits string skrWebhookCPULimits string + virtualServiceName string + gatewayName string pprof bool pprofAddr string pprofServerTimeout time.Duration @@ -183,7 +188,7 @@ func setupManager(flagVar *FlagVar, newCacheFunc cache.NewCacheFunc, scheme *run setupKymaReconciler(mgr, remoteClientCache, flagVar, intervals, options) if flagVar.enableKcpWatcher { - setupKcpWatcherReconciler(mgr, flagVar, intervals, options) + setupKcpWatcherReconciler(mgr, intervals, options, flagVar) } if flagVar.enableWebhooks { if err := (&operatorv1alpha1.ModuleTemplate{}). @@ -268,12 +273,16 @@ func defineFlagVar() *FlagVar { "Enabling Validation/Conversion Webhooks.") flag.BoolVar(&flagVar.enableKcpWatcher, "enable-kcp-watcher", false, "Enabling KCP Watcher to reconcile Watcher CRs created by KCP run operators") - flag.StringVar(&flagVar.skrWatcherPath, "skr-watcher-path", "skr-webhook", + flag.StringVar(&flagVar.skrWatcherPath, "skr-watcher-path", "charts/skr-webhook", "The path to the skr watcher chart.") flag.StringVar(&flagVar.skrWebhookMemoryLimits, "skr-webhook-memory-limits", "200Mi", "The resources.limits.memory for skr webhook.") flag.StringVar(&flagVar.skrWebhookCPULimits, "skr-webhook-cpu-limits", "0.1", "The resources.limits.cpu for skr webhook.") + flag.StringVar(&flagVar.virtualServiceName, "virtual-svc-name", "kcp-events", + "Name of the virtual service resource to be reconciled by the watcher control loop.") + flag.StringVar(&flagVar.virtualServiceName, "gateway-name", "lifecycle-manager-kyma-gateway", + "Name of the gateway resource that the virtual service will use.") flag.BoolVar(&flagVar.pprof, "pprof", false, "Whether to start up a pprof server.") flag.DurationVar(&flagVar.pprofServerTimeout, "pprof-server-timeout", defaultPprofServerTimeout, @@ -298,11 +307,28 @@ func setupKymaReconciler( intervals controllers.RequeueIntervals, options controller.Options, ) { + if flagVar.enableKcpWatcher { + watcherChartDirInfo, err := os.Stat(flagVar.skrWatcherPath) + if err != nil || !watcherChartDirInfo.IsDir() { + setupLog.Error(err, "failed to read local skr chart") + } + } + skrChartConfig := &deploy.SkrChartConfig{ + WebhookChartPath: flagVar.skrWatcherPath, + SkrWebhookMemoryLimits: flagVar.skrWebhookMemoryLimits, + SkrWebhookCPULimits: flagVar.skrWebhookCPULimits, + } + skrWebhookChartManager, err := deploy.ResolveSKRWebhookChartManager(flagVar.enableKcpWatcher, skrChartConfig) + if err != nil { + setupLog.Error(err, "failed to resolve SKR chart manager") + } if err := (&controllers.KymaReconciler{ - Client: mgr.GetClient(), - EventRecorder: mgr.GetEventRecorderFor(operatorv1alpha1.OperatorName), - RemoteClientCache: remoteClientCache, - RequeueIntervals: intervals, + Client: mgr.GetClient(), + EventRecorder: mgr.GetEventRecorderFor(operatorv1alpha1.OperatorName), + KcpRestConfig: mgr.GetConfig(), + RemoteClientCache: remoteClientCache, + SKRWebhookChartManager: skrWebhookChartManager, + RequeueIntervals: intervals, VerificationSettings: signature.VerificationSettings{ PublicKeyFilePath: flagVar.moduleVerificationKeyFilePath, ValidSignatureNames: strings.Split(flagVar.moduleVerificationSignatureNames, ":"), @@ -313,28 +339,21 @@ func setupKymaReconciler( } } -func setupKcpWatcherReconciler( - mgr ctrl.Manager, +func setupKcpWatcherReconciler(mgr ctrl.Manager, intervals controllers.RequeueIntervals, options controller.Options, flagVar *FlagVar, - intervals controllers.RequeueIntervals, - options controller.Options, ) { - fileInfo, err := os.Stat(flagVar.skrWatcherPath) - if err != nil || !fileInfo.IsDir() { - setupLog.Error(err, "failed to read local skr chart") - } - watcherConfig := &controllers.WatcherConfig{ - WebhookChartPath: flagVar.skrWatcherPath, - SkrWebhookMemoryLimits: flagVar.skrWebhookMemoryLimits, - SkrWebhookCPULimits: flagVar.skrWebhookCPULimits, - } + // Set MaxConcurrentReconciles to 1 to avoid concurrent writes on + // the Istio virtual service resource the WatcherReconciler is managing. + // In total, we probably only have 20 watcher CRs, one worker can sufficiently handle it, + // and we don't have to deal with concurrent write to virtual service. + // although eventually the write operation will succeed. + options.MaxConcurrentReconciles = 1 if err := (&controllers.WatcherReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), RestConfig: mgr.GetConfig(), RequeueIntervals: intervals, - Config: watcherConfig, - }).SetupWithManager(mgr, options); err != nil { + }).SetupWithManager(mgr, options, flagVar.virtualServiceName, flagVar.gatewayName); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Watcher") os.Exit(1) } diff --git a/operator/pkg/module/sync/runner_impl.go b/operator/pkg/module/sync/runner_impl.go index 3e4bf138ad..9c69933579 100644 --- a/operator/pkg/module/sync/runner_impl.go +++ b/operator/pkg/module/sync/runner_impl.go @@ -16,7 +16,8 @@ import ( "github.com/kyma-project/lifecycle-manager/operator/pkg/module/common" ) -func New(clnt client.Client) Runner { //nolint:ireturn +//nolint:ireturn +func New(clnt client.Client) Runner { return &runnerImpl{clnt} } diff --git a/operator/pkg/remote/kyma_synchronization_context.go b/operator/pkg/remote/kyma_synchronization_context.go index e36e13a7a6..947ea7913d 100644 --- a/operator/pkg/remote/kyma_synchronization_context.go +++ b/operator/pkg/remote/kyma_synchronization_context.go @@ -45,20 +45,34 @@ func NewRemoteClient(ctx context.Context, controlPlaneClient client.Client, key strategy v1alpha1.SyncStrategy, cache *ClientCache, ) (client.Client, error) { remoteClient := cache.Get(ClientCacheID(key)) - if remoteClient != nil { return remoteClient, nil } - clusterClient := ClusterClient{ - DefaultClient: controlPlaneClient, - Logger: log.FromContext(ctx), + restConfig, err := GetRemoteRestConfig(ctx, controlPlaneClient, key, strategy) + if err != nil { + return nil, err } - var restConfig *rest.Config + remoteClient, err = client.New(restConfig, client.Options{Scheme: controlPlaneClient.Scheme()}) + if err != nil { + return nil, err + } + cache.Set(ClientCacheID(key), remoteClient) + + return remoteClient, nil +} +func GetRemoteRestConfig(ctx context.Context, controlPlaneClient client.Client, key client.ObjectKey, + strategy v1alpha1.SyncStrategy, +) (*rest.Config, error) { var err error + var restConfig *rest.Config + clusterClient := ClusterClient{ + DefaultClient: controlPlaneClient, + Logger: log.FromContext(ctx), + } switch strategy { case v1alpha1.SyncStrategyLocalClient: if LocalClient != nil { @@ -75,14 +89,7 @@ func NewRemoteClient(ctx context.Context, controlPlaneClient client.Client, key if err != nil { return nil, err } - - remoteClient, err = client.New(restConfig, client.Options{Scheme: controlPlaneClient.Scheme()}) - if err != nil { - return nil, err - } - cache.Set(ClientCacheID(key), remoteClient) - - return remoteClient, nil + return restConfig, err } func GetRemotelySyncedKyma(ctx context.Context, runtimeClient client.Client,