From 342f7cc65e6c601ef59c87b2edce920276d51d52 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Tue, 23 May 2023 18:09:03 -0300 Subject: [PATCH 01/10] [istio] Updating registerIstioExternalAuthorizer * Reconciles also the Istio ConfigMap with the external authorizers * If the IstioOperator CR returns an error, it continues reconciling CM --- controllers/kuadrant_controller.go | 116 +++++++++++++++++++++++------ go.mod | 29 ++++++++ go.sum | 79 ++++++++++++++------ 3 files changed, 179 insertions(+), 45 deletions(-) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index d6e68e63e..6f4c059eb 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -21,6 +21,11 @@ import ( "encoding/json" "fmt" + "istio.io/istio/pkg/config/mesh" + "istio.io/istio/pkg/util/protomarshal" + + corev1 "k8s.io/api/core/v1" + "github.com/go-logr/logr" authorinov1beta1 "github.com/kuadrant/authorino-operator/api/v1beta1" maistrav1 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v1" @@ -297,37 +302,43 @@ func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kOb func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - iop := &iopv1alpha1.IstioOperator{} + var configsToUpdate []client.Object + iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} if err := r.Client().Get(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) - return err - } - - if iop.Spec == nil { - iop.Spec = &istioapiv1alpha1.IstioOperatorSpec{} + if apimeta.IsNoMatchError(err) { + // if it's a no match error (CRD not installed), return the error + // otherwise continue with the fetching of the configmap + return err + } + } else { + // if there is no error, add the iop to the list of configs to update + configsToUpdate = append(configsToUpdate, iop) } - meshConfig, err := meshConfigFromStruct(iop.Spec.MeshConfig) - if err != nil { + istioConfigMap := &corev1.ConfigMap{} + if err := r.Client().Get(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { + logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } - extensionProviders := extensionProvidersFromMeshConfig(meshConfig) + configsToUpdate = append(configsToUpdate, istioConfigMap) - if hasKuadrantAuthorizer(extensionProviders) { - return nil - } - - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObj.Namespace)) - meshConfigStruct, err := meshConfigToStruct(meshConfig) - if err != nil { - return err - } - iop.Spec.MeshConfig = meshConfigStruct - logger.Info("adding external authorizer to meshconfig") - if err := r.Client().Update(ctx, iop); err != nil { - return err + for _, config := range configsToUpdate { + meshConfig, err := getMeshConfig(config) + if err != nil { + logger.V(1).Info("failed to get mesh config", "err", err) + return err + } + if needsUpdate, err := updateMeshConfig(config, meshConfig, kObj.Namespace); err != nil { + return err + } else if needsUpdate { + logger.Info("adding external authorizer to meshconfig") + if err := r.Client().Update(ctx, config); err != nil { + return err + } + } } return nil @@ -606,6 +617,25 @@ func meshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshCo return meshConfig, nil } +// meshConfigFromString returns the Istio MeshConfig from a ConfigMap +func meshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { + meshConfig := mesh.DefaultMeshConfig() + err := protomarshal.ApplyYAML(config, meshConfig) + if err != nil { + return nil, err + } + return meshConfig, nil +} + +// meshConfigToString returns the Istio MeshConfig as a string +func meshConfigToString(config *istiomeshv1alpha1.MeshConfig) (string, error) { + configString, err := protomarshal.ToYAML(config) + if err != nil { + return "", err + } + return configString, nil +} + func meshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { configJSON, err := protojson.Marshal(config) if err != nil { @@ -627,6 +657,48 @@ func extensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (ext return } +func updateMeshConfig(configObject client.Object, meshConfig *istiomeshv1alpha1.MeshConfig, kObjNamespace string) (bool, error) { + extProviders := extensionProvidersFromMeshConfig(meshConfig) + if !hasKuadrantAuthorizer(extProviders) { + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObjNamespace)) + + switch config := configObject.(type) { + case *iopv1alpha1.IstioOperator: + meshConfigStruct, err := meshConfigToStruct(meshConfig) + if err != nil { + return false, err + } + config.Spec.MeshConfig = meshConfigStruct + return true, nil + case *corev1.ConfigMap: + var err error + config.Data["mesh"], err = meshConfigToString(meshConfig) + if err != nil { + return false, err + } + return true, nil + default: + return false, fmt.Errorf("unsupported configObject type: %T", config) + } + } + + return false, nil +} + +func getMeshConfig(configObject client.Object) (*istiomeshv1alpha1.MeshConfig, error) { + switch config := configObject.(type) { + case *iopv1alpha1.IstioOperator: + if config.Spec == nil { + config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} + } + return meshConfigFromStruct(config.Spec.MeshConfig) + case *corev1.ConfigMap: + return meshConfigFromString(config.Data["mesh"]) + default: + return nil, fmt.Errorf("unsupported configObject type: %T", config) + } +} + // SetupWithManager sets up the controller with the Manager. func (r *KuadrantReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/go.mod b/go.mod index a2631ead0..1bec7e07c 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,17 @@ require ( require ( cloud.google.com/go v0.102.1 // indirect cloud.google.com/go/compute v1.10.0 // indirect + cloud.google.com/go/logging v1.4.2 // indirect + github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/envoyproxy/go-control-plane v0.10.3-0.20220719090109-b024c36d9935 // indirect + github.com/envoyproxy/protoc-gen-validate v0.6.7 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -42,26 +49,46 @@ require ( github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.21.1 // indirect + github.com/goccy/go-json v0.9.7 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/cel-go v0.12.6 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect + github.com/googleapis/gax-go/v2 v2.4.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect + github.com/lestrrat-go/blackmagic v1.0.0 // indirect + github.com/lestrrat-go/httpcc v1.0.1 // indirect + github.com/lestrrat-go/iter v1.0.1 // indirect + github.com/lestrrat-go/jwx v1.2.25 // indirect + github.com/lestrrat-go/option v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/natefinch/lumberjack v2.0.0+incompatible // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect + github.com/spf13/cobra v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stoewer/go-strcase v1.2.0 // indirect + go.opencensus.io v0.23.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect + golang.org/x/crypto v0.1.0 // indirect golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect golang.org/x/sys v0.3.0 // indirect @@ -72,10 +99,12 @@ require ( google.golang.org/api v0.96.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 // indirect + google.golang.org/grpc v1.49.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + istio.io/pkg v0.0.0-20220907025138-198870de7239 // indirect k8s.io/component-base v0.26.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect diff --git a/go.sum b/go.sum index 3de3c614d..29bd59cc9 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,7 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/logging v1.4.2 h1:Mu2Q75VBDQlW1HlBMjTX4X84UFR73G1TiLlRYc/b7tA= +cloud.google.com/go/logging v1.4.2/go.mod h1:jco9QZSx8HiVVqLJReq7z7bVdj0P1Jb9PDFs63T+axo= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -75,6 +76,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= 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= @@ -84,6 +86,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -102,13 +105,18 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa h1:B/lvg4tQ5hfFZd4V2hcSfFVfUvAK6GSFKxIIzwnkv8g= +github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= 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/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= @@ -122,8 +130,10 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3-0.20220719090109-b024c36d9935 h1:1P6HktLf+VNpEwASft2E0KU7ddeuu73UMnFpawKuD58= +github.com/envoyproxy/go-control-plane v0.10.3-0.20220719090109-b024c36d9935/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7 h1:qcZcULcd/abmQg6dwigimCNEyi4gg31M/xaciQlDml8= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= 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= @@ -131,6 +141,7 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= @@ -164,10 +175,12 @@ github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/e github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -205,6 +218,7 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M= +github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -263,17 +277,23 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.5.0 h1:O293SZ2Eg+AAYijkVK3jR786Am1bhDEh2GHT0tIVE5E= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 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.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -292,6 +312,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -309,12 +330,19 @@ github.com/kuadrant/limitador-operator v0.4.0 h1:HgJi7LuOsenCUMs2ACCfKMKsKpfHcqm github.com/kuadrant/limitador-operator v0.4.0/go.mod h1:5fQo2XwxPr7bDObut9sK5sHCnK4hwAmTsTptaYvGfuc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= +github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4= +github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A= +github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0otA= +github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= +github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= 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.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -342,17 +370,16 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m 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/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -382,15 +409,15 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= @@ -403,11 +430,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -422,13 +445,13 @@ 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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= -go.starlark.net v0.0.0-20211013185944-b0039bd2cfe3 h1:oBcONsksxvpeodDrLjiMDaKHXKAVVfAydhe/792CE/o= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= @@ -439,9 +462,12 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -477,6 +503,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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/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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -515,6 +542,8 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/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= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -536,6 +565,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 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= @@ -575,6 +605,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -606,6 +637,7 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -614,6 +646,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -737,6 +770,7 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -807,7 +841,9 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -834,6 +870,7 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2 google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= @@ -874,12 +911,14 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -902,11 +941,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -921,9 +960,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -helm.sh/helm/v3 v3.9.4 h1:TCI1QhJUeLVOdccfdw+vnSEO3Td6gNqibptB04QtExY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -938,13 +975,13 @@ istio.io/client-go v1.15.1-0.20220907135338-7f6428013c07/go.mod h1:y7N6Hi3uohxut istio.io/istio v0.0.0-20220923214536-bf836f0be536 h1:fZZTZUPpzAJqGqKzijw7j5ss1kAZXYHO8YNfdhZmn48= istio.io/istio v0.0.0-20220923214536-bf836f0be536/go.mod h1:TLnweNm1q+jQT0mkQtKbJkz8GLEQm2d31oisK9vfENA= istio.io/pkg v0.0.0-20220907025138-198870de7239 h1:fT4mErRurULEFGqBYwrY/a9lq3BC6qgilzsUNFnnw6w= +istio.io/pkg v0.0.0-20220907025138-198870de7239/go.mod h1:kcBYN5TiyGFM2bs4b7K81j+YeDZ4JrINP+brV9ehZe0= k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= -k8s.io/cli-runtime v0.24.2 h1:KxY6tSgPGsahA6c1/dmR3uF5jOxXPx2QQY6C5ZrLmtE= k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= @@ -953,7 +990,6 @@ 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-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= @@ -965,9 +1001,6 @@ sigs.k8s.io/gateway-api v0.6.2 h1:583XHiX2M2bKEA0SAdkoxL1nY73W1+/M+IAm8LJvbEA= sigs.k8s.io/gateway-api v0.6.2/go.mod h1:EYJT+jlPWTeNskjV0JTki/03WX1cyAnBhwBJfYHpV/0= 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 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= -sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= -sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= From 69b1392ae15d9dcd623a6ba7ac4bf617d46bf63b Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Fri, 26 May 2023 20:49:45 -0300 Subject: [PATCH 02/10] [istio] Updating the unregisterExternalAuthorizerIstio * With the new functionality --- controllers/kuadrant_controller.go | 92 ++++++++++++++++++------------ 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index 6f4c059eb..415d9e334 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -186,44 +186,48 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context) e func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context) error { logger, _ := logr.FromContext(ctx) - iop := &iopv1alpha1.IstioOperator{} + var configsToUpdate []client.Object + iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} if err := r.Client().Get(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) - return err + if apimeta.IsNoMatchError(err) { + // return err only if there's no istiooperator CRD + return err + } + // otherwise, we assume that the control plane is istio but no installed by its operator + } else { + configsToUpdate = append(configsToUpdate, iop) } - meshConfig, err := meshConfigFromStruct(iop.Spec.MeshConfig) - if err != nil { + istioConfigMap := &corev1.ConfigMap{} + if err := r.Client().Get(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { + logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } - extensionProviders := extensionProvidersFromMeshConfig(meshConfig) - - if !hasKuadrantAuthorizer(extensionProviders) { - return nil - } + configsToUpdate = append(configsToUpdate, istioConfigMap) - for idx, extensionProvider := range extensionProviders { - name := extensionProvider.Name - if name == extAuthorizerName { - // deletes the element in the array - extensionProviders = append(extensionProviders[:idx], extensionProviders[idx+1:]...) - meshConfig.ExtensionProviders = extensionProviders - meshConfigStruct, err := meshConfigToStruct(meshConfig) - if err != nil { + for _, config := range configsToUpdate { + if needsUpdate, err := updateMeshConfig( + config, + func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + extProviders := extensionProvidersFromMeshConfig(meshConfig) + if hasKuadrantAuthorizer(extProviders) { + meshConfig.ExtensionProviders = removeKuadrantAuthorizerFromList(extProviders) + return true + } + return false + }, + ); err != nil { + return err + } else if needsUpdate { + logger.Info("remove external authorizer from meshconfig") + if err := r.Client().Update(ctx, config); err != nil { return err } - iop.Spec.MeshConfig = meshConfigStruct - break } } - - logger.Info("remove external authorizer from meshconfig") - if err := r.Client().Update(ctx, iop); err != nil { - return err - } - return nil } @@ -326,12 +330,17 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context configsToUpdate = append(configsToUpdate, istioConfigMap) for _, config := range configsToUpdate { - meshConfig, err := getMeshConfig(config) - if err != nil { - logger.V(1).Info("failed to get mesh config", "err", err) - return err - } - if needsUpdate, err := updateMeshConfig(config, meshConfig, kObj.Namespace); err != nil { + if needsUpdate, err := updateMeshConfig( + config, + func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + extProviders := extensionProvidersFromMeshConfig(meshConfig) + if !hasKuadrantAuthorizer(extProviders) { + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObj.Namespace)) + return true + } + return false + }, + ); err != nil { return err } else if needsUpdate { logger.Info("adding external authorizer to meshconfig") @@ -657,11 +666,12 @@ func extensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (ext return } -func updateMeshConfig(configObject client.Object, meshConfig *istiomeshv1alpha1.MeshConfig, kObjNamespace string) (bool, error) { - extProviders := extensionProvidersFromMeshConfig(meshConfig) - if !hasKuadrantAuthorizer(extProviders) { - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObjNamespace)) - +func updateMeshConfig(configObject client.Object, updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { + meshConfig, err := getMeshConfig(configObject) + if err != nil { + return false, err + } + if updateFunc(meshConfig) { switch config := configObject.(type) { case *iopv1alpha1.IstioOperator: meshConfigStruct, err := meshConfigToStruct(meshConfig) @@ -699,6 +709,16 @@ func getMeshConfig(configObject client.Object) (*istiomeshv1alpha1.MeshConfig, e } } +func removeKuadrantAuthorizerFromList(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) []*istiomeshv1alpha1.MeshConfig_ExtensionProvider { + for i, extProvider := range extensionProviders { + if extProvider.Name == extAuthorizerName { + extensionProviders = append(extensionProviders[:i], extensionProviders[i+1:]...) + break + } + } + return extensionProviders +} + // SetupWithManager sets up the controller with the Manager. func (r *KuadrantReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). From ca852c80fad7d0e4a8d5c1135c578a3c89613711 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Mon, 29 May 2023 12:57:29 -0300 Subject: [PATCH 03/10] [mesh config] Refactoring and testing mesh config functionality --- controllers/kuadrant_controller.go | 184 +++----------------------- pkg/common/mesh_config.go | 159 +++++++++++++++++++++++ pkg/common/mesh_config_test.go | 202 +++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+), 166 deletions(-) create mode 100644 pkg/common/mesh_config.go create mode 100644 pkg/common/mesh_config_test.go diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index 415d9e334..e4314aaa3 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -21,9 +21,6 @@ import ( "encoding/json" "fmt" - "istio.io/istio/pkg/config/mesh" - "istio.io/istio/pkg/util/protomarshal" - corev1 "k8s.io/api/core/v1" "github.com/go-logr/logr" @@ -32,10 +29,8 @@ import ( maistrav2 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v2" limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" "golang.org/x/sync/errgroup" - "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" - istioapiv1alpha1 "istio.io/api/operator/v1alpha1" iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" appsv1 "k8s.io/api/apps/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -55,7 +50,6 @@ import ( const ( kuadrantFinalizer = "kuadrant.io/finalizer" - extAuthorizerName = "kuadrant-authorization" ) // KuadrantReconciler reconciles a Kuadrant object @@ -209,12 +203,12 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte configsToUpdate = append(configsToUpdate, istioConfigMap) for _, config := range configsToUpdate { - if needsUpdate, err := updateMeshConfig( + if needsUpdate, err := common.UpdateMeshConfig( config, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - extProviders := extensionProvidersFromMeshConfig(meshConfig) - if hasKuadrantAuthorizer(extProviders) { - meshConfig.ExtensionProviders = removeKuadrantAuthorizerFromList(extProviders) + extProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) + if common.HasKuadrantAuthorizer(extProviders) { + meshConfig.ExtensionProviders = common.RemoveKuadrantAuthorizerFromList(extProviders) return true } return false @@ -255,23 +249,23 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Contex if err != nil { return err } - meshConfig, _ = meshConfigFromStruct(meshConfigStruct) + meshConfig, _ = common.MeshConfigFromStruct(meshConfigStruct) } else { meshConfig = &istiomeshv1alpha1.MeshConfig{} } - extensionProviders := extensionProvidersFromMeshConfig(meshConfig) + extensionProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) - if !hasKuadrantAuthorizer(extensionProviders) { + if !common.HasKuadrantAuthorizer(extensionProviders) { return nil } for idx, extensionProvider := range extensionProviders { name := extensionProvider.Name - if name == extAuthorizerName { + if name == common.ExtAuthorizerName { // deletes the element in the array extensionProviders = append(extensionProviders[:idx], extensionProviders[idx+1:]...) meshConfig.ExtensionProviders = extensionProviders - meshConfigStruct, err := meshConfigToStruct(meshConfig) + meshConfigStruct, err := common.MeshConfigToStruct(meshConfig) if err != nil { return err } @@ -330,12 +324,12 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context configsToUpdate = append(configsToUpdate, istioConfigMap) for _, config := range configsToUpdate { - if needsUpdate, err := updateMeshConfig( + if needsUpdate, err := common.UpdateMeshConfig( config, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - extProviders := extensionProvidersFromMeshConfig(meshConfig) - if !hasKuadrantAuthorizer(extProviders) { - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObj.Namespace)) + extProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) + if !common.HasKuadrantAuthorizer(extProviders) { + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, common.CreateKuadrantAuthorizer(kObj.Namespace)) return true } return false @@ -381,18 +375,18 @@ func (r *KuadrantReconciler) registerExternalAuthorizerOSSM(ctx context.Context, if err != nil { return err } - meshConfig, _ = meshConfigFromStruct(meshConfigStruct) + meshConfig, _ = common.MeshConfigFromStruct(meshConfigStruct) } else { meshConfig = &istiomeshv1alpha1.MeshConfig{} } - extensionProviders := extensionProvidersFromMeshConfig(meshConfig) + extensionProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) - if hasKuadrantAuthorizer(extensionProviders) { + if common.HasKuadrantAuthorizer(extensionProviders) { return nil } - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, createKuadrantAuthorizer(kObj.Namespace)) - meshConfigStruct, err := meshConfigToStruct(meshConfig) + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, common.CreateKuadrantAuthorizer(kObj.Namespace)) + meshConfigStruct, err := common.MeshConfigToStruct(meshConfig) if err != nil { return err } @@ -458,29 +452,6 @@ func buildServiceMeshMember(kObj *kuadrantv1beta1.Kuadrant) *maistrav1.ServiceMe } } -func hasKuadrantAuthorizer(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { - for _, extensionProvider := range extensionProviders { - if extensionProvider.Name == extAuthorizerName { - return true - } - } - - return false -} - -func createKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { - envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ - EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ - Port: 50051, - Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), - }, - } - return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ - Name: extAuthorizerName, - Provider: envoyExtAuthGRPC, - } -} - func (r *KuadrantReconciler) reconcileClusterGateways(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { // TODO: After the RFC defined, we might want to get the gw to label/annotate from Kuadrant.Spec or manual labeling/annotation gwList := &gatewayapiv1beta1.GatewayList{} @@ -600,125 +571,6 @@ func (r *KuadrantReconciler) reconcileAuthorino(ctx context.Context, kObj *kuadr return r.ReconcileResource(ctx, &authorinov1beta1.Authorino{}, authorino, reconcilers.CreateOnlyMutator) } -// Builds the Istio/OSSM MeshConfig from a compatible structure: -// -// meshConfig: -// extensionProviders: -// - envoyExtAuthzGrpc: -// port: -// service: -// name: kuadrant-authorization -func meshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { - if structure == nil { - return &istiomeshv1alpha1.MeshConfig{}, nil - } - - meshConfigJSON, err := structure.MarshalJSON() - if err != nil { - return nil, err - } - meshConfig := &istiomeshv1alpha1.MeshConfig{} - // istiomeshv1alpha1.MeshConfig doesn't implement JSON/Yaml marshalling, only protobuf - if err = protojson.Unmarshal(meshConfigJSON, meshConfig); err != nil { - return nil, err - } - - return meshConfig, nil -} - -// meshConfigFromString returns the Istio MeshConfig from a ConfigMap -func meshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { - meshConfig := mesh.DefaultMeshConfig() - err := protomarshal.ApplyYAML(config, meshConfig) - if err != nil { - return nil, err - } - return meshConfig, nil -} - -// meshConfigToString returns the Istio MeshConfig as a string -func meshConfigToString(config *istiomeshv1alpha1.MeshConfig) (string, error) { - configString, err := protomarshal.ToYAML(config) - if err != nil { - return "", err - } - return configString, nil -} - -func meshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { - configJSON, err := protojson.Marshal(config) - if err != nil { - return nil, err - } - configStruct := &structpb.Struct{} - - if err = configStruct.UnmarshalJSON(configJSON); err != nil { - return nil, err - } - return configStruct, nil -} - -func extensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { - extensionProviders = config.ExtensionProviders - if len(extensionProviders) == 0 { - extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) - } - return -} - -func updateMeshConfig(configObject client.Object, updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { - meshConfig, err := getMeshConfig(configObject) - if err != nil { - return false, err - } - if updateFunc(meshConfig) { - switch config := configObject.(type) { - case *iopv1alpha1.IstioOperator: - meshConfigStruct, err := meshConfigToStruct(meshConfig) - if err != nil { - return false, err - } - config.Spec.MeshConfig = meshConfigStruct - return true, nil - case *corev1.ConfigMap: - var err error - config.Data["mesh"], err = meshConfigToString(meshConfig) - if err != nil { - return false, err - } - return true, nil - default: - return false, fmt.Errorf("unsupported configObject type: %T", config) - } - } - - return false, nil -} - -func getMeshConfig(configObject client.Object) (*istiomeshv1alpha1.MeshConfig, error) { - switch config := configObject.(type) { - case *iopv1alpha1.IstioOperator: - if config.Spec == nil { - config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} - } - return meshConfigFromStruct(config.Spec.MeshConfig) - case *corev1.ConfigMap: - return meshConfigFromString(config.Data["mesh"]) - default: - return nil, fmt.Errorf("unsupported configObject type: %T", config) - } -} - -func removeKuadrantAuthorizerFromList(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) []*istiomeshv1alpha1.MeshConfig_ExtensionProvider { - for i, extProvider := range extensionProviders { - if extProvider.Name == extAuthorizerName { - extensionProviders = append(extensionProviders[:i], extensionProviders[i+1:]...) - break - } - } - return extensionProviders -} - // SetupWithManager sets up the controller with the Manager. func (r *KuadrantReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/pkg/common/mesh_config.go b/pkg/common/mesh_config.go new file mode 100644 index 000000000..3c3b5341a --- /dev/null +++ b/pkg/common/mesh_config.go @@ -0,0 +1,159 @@ +package common + +import ( + "fmt" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/structpb" + istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" + istioapiv1alpha1 "istio.io/api/operator/v1alpha1" + iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" + "istio.io/istio/pkg/util/protomarshal" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + ExtAuthorizerName = "kuadrant-authorization" +) + +// MeshConfigFromStruct Builds the Istio/OSSM MeshConfig from a compatible structure: +// +// meshConfig: +// extensionProviders: +// - envoyExtAuthzGrpc: +// port: +// service: +// name: kuadrant-authorization +func MeshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { + if structure == nil { + return &istiomeshv1alpha1.MeshConfig{}, nil + } + + meshConfigJSON, err := structure.MarshalJSON() + if err != nil { + return nil, err + } + meshConfig := &istiomeshv1alpha1.MeshConfig{} + // istiomeshv1alpha1.MeshConfig doesn't implement JSON/Yaml marshalling, only protobuf + if err = protojson.Unmarshal(meshConfigJSON, meshConfig); err != nil { + return nil, err + } + + return meshConfig, nil +} + +// MeshConfigFromString returns the Istio MeshConfig from a ConfigMap +func MeshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { + meshConfig := &istiomeshv1alpha1.MeshConfig{} + err := protomarshal.ApplyYAML(config, meshConfig) + if err != nil { + return nil, err + } + return meshConfig, nil +} + +// meshConfigToString returns the Istio MeshConfig as a string +func meshConfigToString(config *istiomeshv1alpha1.MeshConfig) (string, error) { + configString, err := protomarshal.ToYAML(config) + if err != nil { + return "", err + } + return configString, nil +} + +func MeshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { + configJSON, err := protojson.Marshal(config) + if err != nil { + return nil, err + } + configStruct := &structpb.Struct{} + + if err = configStruct.UnmarshalJSON(configJSON); err != nil { + return nil, err + } + return configStruct, nil +} + +func ExtensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { + extensionProviders = config.ExtensionProviders + if len(extensionProviders) == 0 { + extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + } + return +} + +func UpdateMeshConfig(configObject client.Object, updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { + meshConfig, err := getMeshConfig(configObject) + if err != nil { + return false, err + } + if updateFunc(meshConfig) { + switch config := configObject.(type) { + case *iopv1alpha1.IstioOperator: + meshConfigStruct, err := MeshConfigToStruct(meshConfig) + if err != nil { + return false, err + } + config.Spec.MeshConfig = meshConfigStruct + return true, nil + case *corev1.ConfigMap: + var err error + config.Data["mesh"], err = meshConfigToString(meshConfig) + if err != nil { + return false, err + } + return true, nil + default: + return false, fmt.Errorf("unsupported configObject type: %T", config) + } + } + return false, nil +} + +func getMeshConfig(configObject client.Object) (*istiomeshv1alpha1.MeshConfig, error) { + switch config := configObject.(type) { + case *iopv1alpha1.IstioOperator: + if config.Spec == nil { + config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} + } + return MeshConfigFromStruct(config.Spec.MeshConfig) + case *corev1.ConfigMap: + return MeshConfigFromString(config.Data["mesh"]) + default: + return nil, fmt.Errorf("unsupported configObject type: %T", config) + } +} + +func RemoveKuadrantAuthorizerFromList(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) []*istiomeshv1alpha1.MeshConfig_ExtensionProvider { + for i, extProvider := range extensionProviders { + if extProvider.Name == ExtAuthorizerName { + extensionProviders = append(extensionProviders[:i], extensionProviders[i+1:]...) + break + } + } + return extensionProviders +} + +func HasKuadrantAuthorizer(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { + for _, extensionProvider := range extensionProviders { + if extensionProvider.Name == ExtAuthorizerName { + return true + } + } + + return false +} + +func CreateKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { + envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ + EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ + Port: 50051, + Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), + }, + } + return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ + Name: ExtAuthorizerName, + Provider: envoyExtAuthGRPC, + } +} diff --git a/pkg/common/mesh_config_test.go b/pkg/common/mesh_config_test.go new file mode 100644 index 000000000..2747bdcb0 --- /dev/null +++ b/pkg/common/mesh_config_test.go @@ -0,0 +1,202 @@ +//go:build unit +// +build unit + +package common + +import ( + "testing" + + "google.golang.org/protobuf/types/known/structpb" + "gotest.tools/assert" + istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" + istioapiv1alpha1 "istio.io/api/operator/v1alpha1" + iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" + corev1 "k8s.io/api/core/v1" +) + +func getStubbedMeshConfig() *istiomeshv1alpha1.MeshConfig { + providers := make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + provider := &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ + Name: "custom-authorizer", + Provider: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ + EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ + Port: 50051, + Service: "custom-authorizer.default.svc.cluster.local", + }, + }, + } + providers = append(providers, provider) + return &istiomeshv1alpha1.MeshConfig{ + ExtensionProviders: providers, + } +} + +func TestMeshConfigFromStruct(t *testing.T) { + expectedConfig := getStubbedMeshConfig() + + config := &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "extensionProviders": { + Kind: &structpb.Value_ListValue{ + ListValue: &structpb.ListValue{ + Values: []*structpb.Value{ + { + Kind: &structpb.Value_StructValue{ + StructValue: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "name": { + Kind: &structpb.Value_StringValue{ + StringValue: "custom-authorizer", + }, + }, + "envoyExtAuthzGrpc": { + Kind: &structpb.Value_StructValue{ + StructValue: &structpb.Struct{ + Fields: map[string]*structpb.Value{ + "port": { + Kind: &structpb.Value_NumberValue{ + NumberValue: 50051, + }, + }, + "service": { + Kind: &structpb.Value_StringValue{ + StringValue: "custom-authorizer.default.svc.cluster.local", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + meshConfig, _ := MeshConfigFromStruct(config) + + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, expectedConfig.ExtensionProviders[0].Name) + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service) + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port) +} + +func TestMeshConfigFromString(t *testing.T) { + expectedConfig := getStubbedMeshConfig() + + config := ` +extensionProviders: +- name: "custom-authorizer" + envoyExtAuthzGrpc: + service: "custom-authorizer.default.svc.cluster.local" + port: "50051" +` + + meshConfig, _ := MeshConfigFromString(config) + + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, expectedConfig.ExtensionProviders[0].Name) + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service) + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port) + +} + +func TestMeshConfigToStruct(t *testing.T) { + config := getStubbedMeshConfig() + + meshConfig, _ := MeshConfigToStruct(config) + + assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["name"].GetStringValue(), "custom-authorizer") + assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["envoyExtAuthzGrpc"].GetStructValue().Fields["service"].GetStringValue(), "custom-authorizer.default.svc.cluster.local") + assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["envoyExtAuthzGrpc"].GetStructValue().Fields["port"].GetNumberValue(), float64(50051)) +} + +func TestExtensionProvidersFromMeshConfig(t *testing.T) { + config := getStubbedMeshConfig() + + extensionProviders := ExtensionProvidersFromMeshConfig(config) + + assert.Equal(t, extensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, extensionProviders[0].GetEnvoyExtAuthzGrpc().Service, "custom-authorizer.default.svc.cluster.local") + assert.Equal(t, extensionProviders[0].GetEnvoyExtAuthzGrpc().Port, uint32(50051)) +} + +func TestExtensionProvidersFromMeshConfigWithEmptyConfig(t *testing.T) { + config := &istiomeshv1alpha1.MeshConfig{} + + extensionProviders := ExtensionProvidersFromMeshConfig(config) + + assert.Equal(t, len(extensionProviders), 0) +} + +func TestHasKuadrantAuthorizer(t *testing.T) { + configWithNoKuadrantAuth := getStubbedMeshConfig().ExtensionProviders + + configWithKuadrantAuth := make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + kuadrantAuthProvider := CreateKuadrantAuthorizer("kuadrant-system") + configWithKuadrantAuth = append(configWithKuadrantAuth, kuadrantAuthProvider) + + assert.Equal(t, HasKuadrantAuthorizer(configWithNoKuadrantAuth), false) + assert.Equal(t, HasKuadrantAuthorizer(configWithKuadrantAuth), true) +} + +func TestCreateKuadrantAuthorizer(t *testing.T) { + authorizer := CreateKuadrantAuthorizer("kuadrant-system") + + assert.Equal(t, authorizer.Name, "kuadrant-authorization") + assert.Equal(t, authorizer.GetEnvoyExtAuthzGrpc().Service, "authorino-authorino-authorization.kuadrant-system.svc.cluster.local") + assert.Equal(t, authorizer.GetEnvoyExtAuthzGrpc().Port, uint32(50051)) +} + +func TestRemoveKuadrantAuthorizerFromList(t *testing.T) { + providers := getStubbedMeshConfig().ExtensionProviders + providers = append(providers, CreateKuadrantAuthorizer("kuadrant-system")) + providers = RemoveKuadrantAuthorizerFromList(providers) + + assert.Equal(t, len(providers), 1) + assert.Equal(t, providers[0].Name, "custom-authorizer") +} + +func TestUpdateMeshConfig(t *testing.T) { + t.Run("TestUpdateMeshConfigWithConfigMap", func(t *testing.T) { + configMap := &corev1.ConfigMap{ + Data: map[string]string{ + "mesh": ` +extensionProviders: +- name: "custom-authorizer" + envoyExtAuthzGrpc: + service: "custom-authorizer.default.svc.cluster.local" + port: "50051" +`, + }, + } + updated, err := UpdateMeshConfig(configMap, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) + return true + }) + + meshConfig, _ := MeshConfigFromString(configMap.Data["mesh"]) + assert.NilError(t, err) + assert.Equal(t, updated, true) + assert.Equal(t, len(meshConfig.ExtensionProviders), 2) + }) + t.Run("TestUpdateMeshConfigWithIstioOperator", func(t *testing.T) { + meshConfig, _ := MeshConfigToStruct(getStubbedMeshConfig()) + istioOperator := &iopv1alpha1.IstioOperator{ + Spec: &istioapiv1alpha1.IstioOperatorSpec{ + MeshConfig: meshConfig, + }, + } + updated, err := UpdateMeshConfig(istioOperator, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) + return true + }) + config := istioOperator.Spec.MeshConfig + assert.NilError(t, err) + assert.Equal(t, updated, true) + assert.Equal(t, len(config.Fields["extensionProviders"].GetListValue().Values), 2) + }) +} From b702ff95f1da0558924bc8345803d558ce643bcb Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Mon, 29 May 2023 18:49:11 -0300 Subject: [PATCH 04/10] [makefile] Splitting local deploy in different target --- Makefile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 5f43a33b5..5a1661d67 100644 --- a/Makefile +++ b/Makefile @@ -269,9 +269,8 @@ test-unit: clean-cov generate fmt vet ## Run Unit tests. namespace: ## Creates a namespace where to deploy Kuadrant Operator kubectl create namespace $(KUADRANT_NAMESPACE) -.PHONY: local-setup -local-setup: $(KIND) ## Deploy locally kuadrant operator from the current code - $(MAKE) local-env-setup +.PHONY: local-deploy +local-deploy: ## Deploy Kuadrant Operator in the cluster pointed by KUBECONFIG $(MAKE) docker-build IMG=$(IMAGE_TAG_BASE):dev $(KIND) load docker-image $(IMAGE_TAG_BASE):dev --name $(KIND_CLUSTER_NAME) $(MAKE) deploy IMG=$(IMAGE_TAG_BASE):dev @@ -284,6 +283,11 @@ local-setup: $(KIND) ## Deploy locally kuadrant operator from the current code @echo "curl -H \"Host: myhost.com\" localhost:9080" @echo +.PHONY: local-setup +local-setup: $(KIND) ## Deploy locally kuadrant operator from the current code + $(MAKE) local-env-setup + $(MAKE) local-deploy + .PHONY: local-cleanup local-cleanup: ## Delete local cluster $(MAKE) kind-delete-cluster From 3294708f6617554cb3ce7f43d812491b5a015b3b Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Mon, 19 Jun 2023 18:43:04 +0200 Subject: [PATCH 05/10] [istio] Refactoring using wrapper structs --- controllers/kuadrant_controller.go | 61 +++--- pkg/common/mesh_config.go | 159 --------------- pkg/istio/mesh_config.go | 223 ++++++++++++++++++++++ pkg/{common => istio}/mesh_config_test.go | 22 ++- 4 files changed, 259 insertions(+), 206 deletions(-) delete mode 100644 pkg/common/mesh_config.go create mode 100644 pkg/istio/mesh_config.go rename pkg/{common => istio}/mesh_config_test.go (90%) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index e4314aaa3..f2f7a97c4 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -44,6 +44,7 @@ import ( kuadrantv1beta1 "github.com/kuadrant/kuadrant-operator/api/v1beta1" "github.com/kuadrant/kuadrant-operator/pkg/common" + "github.com/kuadrant/kuadrant-operator/pkg/istio" "github.com/kuadrant/kuadrant-operator/pkg/log" "github.com/kuadrant/kuadrant-operator/pkg/reconcilers" ) @@ -180,7 +181,7 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context) e func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context) error { logger, _ := logr.FromContext(ctx) - var configsToUpdate []client.Object + var configsToUpdate []istio.ConfigWrapper iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} @@ -192,7 +193,7 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte } // otherwise, we assume that the control plane is istio but no installed by its operator } else { - configsToUpdate = append(configsToUpdate, iop) + configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) } istioConfigMap := &corev1.ConfigMap{} @@ -200,24 +201,16 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } - configsToUpdate = append(configsToUpdate, istioConfigMap) + configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) for _, config := range configsToUpdate { - if needsUpdate, err := common.UpdateMeshConfig( - config, - func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - extProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) - if common.HasKuadrantAuthorizer(extProviders) { - meshConfig.ExtensionProviders = common.RemoveKuadrantAuthorizerFromList(extProviders) - return true - } - return false - }, + if needsUpdate, err := config.UpdateConfig( + istio.RemoveKuadrantAuthorizerFromConfig, ); err != nil { return err } else if needsUpdate { logger.Info("remove external authorizer from meshconfig") - if err := r.Client().Update(ctx, config); err != nil { + if err := r.Client().Update(ctx, config.GetConfigObject()); err != nil { return err } } @@ -249,23 +242,23 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Contex if err != nil { return err } - meshConfig, _ = common.MeshConfigFromStruct(meshConfigStruct) + meshConfig, _ = istio.MeshConfigFromStruct(meshConfigStruct) } else { meshConfig = &istiomeshv1alpha1.MeshConfig{} } - extensionProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) + extensionProviders := istio.ExtensionProvidersFromMeshConfig(meshConfig) - if !common.HasKuadrantAuthorizer(extensionProviders) { + if !istio.HasKuadrantAuthorizer(extensionProviders) { return nil } for idx, extensionProvider := range extensionProviders { name := extensionProvider.Name - if name == common.ExtAuthorizerName { + if name == istio.ExtAuthorizerName { // deletes the element in the array extensionProviders = append(extensionProviders[:idx], extensionProviders[idx+1:]...) meshConfig.ExtensionProviders = extensionProviders - meshConfigStruct, err := common.MeshConfigToStruct(meshConfig) + meshConfigStruct, err := istio.MeshConfigToStruct(meshConfig) if err != nil { return err } @@ -300,7 +293,7 @@ func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kOb func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - var configsToUpdate []client.Object + var configsToUpdate []istio.ConfigWrapper iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} @@ -313,7 +306,7 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context } } else { // if there is no error, add the iop to the list of configs to update - configsToUpdate = append(configsToUpdate, iop) + configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) } istioConfigMap := &corev1.ConfigMap{} @@ -321,24 +314,16 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } - configsToUpdate = append(configsToUpdate, istioConfigMap) + configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) for _, config := range configsToUpdate { - if needsUpdate, err := common.UpdateMeshConfig( - config, - func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - extProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) - if !common.HasKuadrantAuthorizer(extProviders) { - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, common.CreateKuadrantAuthorizer(kObj.Namespace)) - return true - } - return false - }, + if needsUpdate, err := config.UpdateConfig( + istio.AddKuadrantAuthorizerToConfig(kObj.Namespace), ); err != nil { return err } else if needsUpdate { logger.Info("adding external authorizer to meshconfig") - if err := r.Client().Update(ctx, config); err != nil { + if err := r.Client().Update(ctx, config.GetConfigObject()); err != nil { return err } } @@ -375,18 +360,18 @@ func (r *KuadrantReconciler) registerExternalAuthorizerOSSM(ctx context.Context, if err != nil { return err } - meshConfig, _ = common.MeshConfigFromStruct(meshConfigStruct) + meshConfig, _ = istio.MeshConfigFromStruct(meshConfigStruct) } else { meshConfig = &istiomeshv1alpha1.MeshConfig{} } - extensionProviders := common.ExtensionProvidersFromMeshConfig(meshConfig) + extensionProviders := istio.ExtensionProvidersFromMeshConfig(meshConfig) - if common.HasKuadrantAuthorizer(extensionProviders) { + if istio.HasKuadrantAuthorizer(extensionProviders) { return nil } - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, common.CreateKuadrantAuthorizer(kObj.Namespace)) - meshConfigStruct, err := common.MeshConfigToStruct(meshConfig) + meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, istio.CreateKuadrantAuthorizer(kObj.Namespace)) + meshConfigStruct, err := istio.MeshConfigToStruct(meshConfig) if err != nil { return err } diff --git a/pkg/common/mesh_config.go b/pkg/common/mesh_config.go deleted file mode 100644 index 3c3b5341a..000000000 --- a/pkg/common/mesh_config.go +++ /dev/null @@ -1,159 +0,0 @@ -package common - -import ( - "fmt" - - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/types/known/structpb" - istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" - istioapiv1alpha1 "istio.io/api/operator/v1alpha1" - iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" - "istio.io/istio/pkg/util/protomarshal" - corev1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const ( - ExtAuthorizerName = "kuadrant-authorization" -) - -// MeshConfigFromStruct Builds the Istio/OSSM MeshConfig from a compatible structure: -// -// meshConfig: -// extensionProviders: -// - envoyExtAuthzGrpc: -// port: -// service: -// name: kuadrant-authorization -func MeshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { - if structure == nil { - return &istiomeshv1alpha1.MeshConfig{}, nil - } - - meshConfigJSON, err := structure.MarshalJSON() - if err != nil { - return nil, err - } - meshConfig := &istiomeshv1alpha1.MeshConfig{} - // istiomeshv1alpha1.MeshConfig doesn't implement JSON/Yaml marshalling, only protobuf - if err = protojson.Unmarshal(meshConfigJSON, meshConfig); err != nil { - return nil, err - } - - return meshConfig, nil -} - -// MeshConfigFromString returns the Istio MeshConfig from a ConfigMap -func MeshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { - meshConfig := &istiomeshv1alpha1.MeshConfig{} - err := protomarshal.ApplyYAML(config, meshConfig) - if err != nil { - return nil, err - } - return meshConfig, nil -} - -// meshConfigToString returns the Istio MeshConfig as a string -func meshConfigToString(config *istiomeshv1alpha1.MeshConfig) (string, error) { - configString, err := protomarshal.ToYAML(config) - if err != nil { - return "", err - } - return configString, nil -} - -func MeshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { - configJSON, err := protojson.Marshal(config) - if err != nil { - return nil, err - } - configStruct := &structpb.Struct{} - - if err = configStruct.UnmarshalJSON(configJSON); err != nil { - return nil, err - } - return configStruct, nil -} - -func ExtensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { - extensionProviders = config.ExtensionProviders - if len(extensionProviders) == 0 { - extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) - } - return -} - -func UpdateMeshConfig(configObject client.Object, updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { - meshConfig, err := getMeshConfig(configObject) - if err != nil { - return false, err - } - if updateFunc(meshConfig) { - switch config := configObject.(type) { - case *iopv1alpha1.IstioOperator: - meshConfigStruct, err := MeshConfigToStruct(meshConfig) - if err != nil { - return false, err - } - config.Spec.MeshConfig = meshConfigStruct - return true, nil - case *corev1.ConfigMap: - var err error - config.Data["mesh"], err = meshConfigToString(meshConfig) - if err != nil { - return false, err - } - return true, nil - default: - return false, fmt.Errorf("unsupported configObject type: %T", config) - } - } - return false, nil -} - -func getMeshConfig(configObject client.Object) (*istiomeshv1alpha1.MeshConfig, error) { - switch config := configObject.(type) { - case *iopv1alpha1.IstioOperator: - if config.Spec == nil { - config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} - } - return MeshConfigFromStruct(config.Spec.MeshConfig) - case *corev1.ConfigMap: - return MeshConfigFromString(config.Data["mesh"]) - default: - return nil, fmt.Errorf("unsupported configObject type: %T", config) - } -} - -func RemoveKuadrantAuthorizerFromList(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) []*istiomeshv1alpha1.MeshConfig_ExtensionProvider { - for i, extProvider := range extensionProviders { - if extProvider.Name == ExtAuthorizerName { - extensionProviders = append(extensionProviders[:i], extensionProviders[i+1:]...) - break - } - } - return extensionProviders -} - -func HasKuadrantAuthorizer(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { - for _, extensionProvider := range extensionProviders { - if extensionProvider.Name == ExtAuthorizerName { - return true - } - } - - return false -} - -func CreateKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { - envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ - EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ - Port: 50051, - Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), - }, - } - return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ - Name: ExtAuthorizerName, - Provider: envoyExtAuthGRPC, - } -} diff --git a/pkg/istio/mesh_config.go b/pkg/istio/mesh_config.go new file mode 100644 index 000000000..bc8800135 --- /dev/null +++ b/pkg/istio/mesh_config.go @@ -0,0 +1,223 @@ +package istio + +import ( + "fmt" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/structpb" + istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" + istioapiv1alpha1 "istio.io/api/operator/v1alpha1" + iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" + "istio.io/istio/pkg/util/protomarshal" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + ExtAuthorizerName = "kuadrant-authorization" +) + +// ConfigWrapper wraps the IstioOperator CRD or ConfigMap +type ConfigWrapper interface { + GetConfigObject() client.Object + GetConfig() (*istiomeshv1alpha1.MeshConfig, error) + UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) +} + +// OperatorWrapper wraps the IstioOperator CRD +type OperatorWrapper struct { + config *iopv1alpha1.IstioOperator +} + +// NewOperatorWrapper creates a new IstioOperatorWrapper +func NewOperatorWrapper(config *iopv1alpha1.IstioOperator) *OperatorWrapper { + return &OperatorWrapper{config: config} +} + +// GetConfigObject returns the IstioOperator CRD +func (w *OperatorWrapper) GetConfigObject() client.Object { + return w.config +} + +// GetConfig returns the IstioOperator MeshConfig +func (w *OperatorWrapper) GetConfig() (*istiomeshv1alpha1.MeshConfig, error) { + if w.config.Spec == nil { + w.config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} + } + return MeshConfigFromStruct(w.config.Spec.MeshConfig) +} + +// UpdateConfig updates the IstioOperator with the new MeshConfig and returns true if the MeshConfig was updated +func (w *OperatorWrapper) UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { + config, err := w.GetConfig() + if err != nil { + return false, err + } + if updateFunc(config) { + meshConfigStruct, err := MeshConfigToStruct(config) + if err != nil { + return false, err + } + w.config.Spec.MeshConfig = meshConfigStruct + return true, nil + } + return false, nil +} + +// ConfigMapWrapper wraps the ConfigMap holding the Istio MeshConfig +type ConfigMapWrapper struct { + config *corev1.ConfigMap +} + +// NewConfigMapWrapper creates a new ConfigMapWrapper +func NewConfigMapWrapper(config *corev1.ConfigMap) *ConfigMapWrapper { + return &ConfigMapWrapper{config: config} +} + +// GetConfigObject returns the ConfigMap +func (w *ConfigMapWrapper) GetConfigObject() client.Object { + return w.config +} + +// GetConfig returns the MeshConfig from the ConfigMap +func (w *ConfigMapWrapper) GetConfig() (*istiomeshv1alpha1.MeshConfig, error) { + meshConfigString, ok := w.config.Data["mesh"] + if !ok { + return nil, fmt.Errorf("mesh config not found in ConfigMap") + } + return MeshConfigFromString(meshConfigString) +} + +// UpdateConfig updates the ConfigMap with the new MeshConfig and returns true if the ConfigMap was updated +func (w *ConfigMapWrapper) UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { + config, err := w.GetConfig() + if err != nil { + return false, err + } + + if updateFunc(config) { + meshString, err := meshConfigToString(config) + if err != nil { + return false, err + } + w.config.Data["mesh"] = meshString + return true, nil + } + return false, nil +} + +// MeshConfigFromStruct Builds the Istio/OSSM MeshConfig from a compatible structure: +// +// meshConfig: +// extensionProviders: +// - envoyExtAuthzGrpc: +// port: +// service: +// name: kuadrant-authorization +func MeshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { + if structure == nil { + return &istiomeshv1alpha1.MeshConfig{}, nil + } + + meshConfigJSON, err := structure.MarshalJSON() + if err != nil { + return nil, err + } + meshConfig := &istiomeshv1alpha1.MeshConfig{} + // istiomeshv1alpha1.MeshConfig doesn't implement JSON/Yaml marshalling, only protobuf + if err = protojson.Unmarshal(meshConfigJSON, meshConfig); err != nil { + return nil, err + } + + return meshConfig, nil +} + +// MeshConfigFromString returns the Istio MeshConfig from a ConfigMap +func MeshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { + meshConfig := &istiomeshv1alpha1.MeshConfig{} + err := protomarshal.ApplyYAML(config, meshConfig) + if err != nil { + return nil, err + } + return meshConfig, nil +} + +// MeshConfigToStruct Marshals the Istio MeshConfig into a struct +func MeshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { + configJSON, err := protojson.Marshal(config) + if err != nil { + return nil, err + } + configStruct := &structpb.Struct{} + + if err = configStruct.UnmarshalJSON(configJSON); err != nil { + return nil, err + } + return configStruct, nil +} + +// ExtensionProvidersFromMeshConfig Returns the Istio MeshConfig ExtensionProviders +func ExtensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { + extensionProviders = config.ExtensionProviders + if len(extensionProviders) == 0 { + extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + } + return +} + +// HasKuadrantAuthorizer Checks if the Istio MeshConfig has the ExtensionProvider for Kuadrant +func HasKuadrantAuthorizer(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { + for _, extensionProvider := range extensionProviders { + if extensionProvider.Name == ExtAuthorizerName { + return true + } + } + + return false +} + +// RemoveKuadrantAuthorizerFromConfig Removes the Istio MeshConfig ExtensionProvider for Kuadrant +func RemoveKuadrantAuthorizerFromConfig(config *istiomeshv1alpha1.MeshConfig) bool { + for i, extProvider := range config.ExtensionProviders { + if extProvider.Name == ExtAuthorizerName { + fmt.Println("Removing Kuadrant Authorizer from MeshConfig", config.ExtensionProviders) + config.ExtensionProviders = append(config.ExtensionProviders[:i], config.ExtensionProviders[i+1:]...) + fmt.Println("Removing Kuadrant Authorizer from MeshConfig", config.ExtensionProviders) + return true + } + } + return false +} + +// AddKuadrantAuthorizerToConfig Adds the Istio MeshConfig ExtensionProvider for Kuadrant +func AddKuadrantAuthorizerToConfig(namespace string) func(config *istiomeshv1alpha1.MeshConfig) bool { + return func(config *istiomeshv1alpha1.MeshConfig) bool { + if HasKuadrantAuthorizer(config.ExtensionProviders) { + return false + } + config.ExtensionProviders = append(config.ExtensionProviders, CreateKuadrantAuthorizer(namespace)) + return true + } +} + +// CreateKuadrantAuthorizer Creates the Istio MeshConfig ExtensionProvider for Kuadrant +func CreateKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { + envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ + EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ + Port: 50051, + Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), + }, + } + return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ + Name: ExtAuthorizerName, + Provider: envoyExtAuthGRPC, + } +} + +// meshConfigToString returns the Istio MeshConfig as a string +func meshConfigToString(config *istiomeshv1alpha1.MeshConfig) (string, error) { + configString, err := protomarshal.ToYAML(config) + if err != nil { + return "", err + } + return configString, nil +} diff --git a/pkg/common/mesh_config_test.go b/pkg/istio/mesh_config_test.go similarity index 90% rename from pkg/common/mesh_config_test.go rename to pkg/istio/mesh_config_test.go index 2747bdcb0..485a1d770 100644 --- a/pkg/common/mesh_config_test.go +++ b/pkg/istio/mesh_config_test.go @@ -1,7 +1,7 @@ //go:build unit // +build unit -package common +package istio import ( "testing" @@ -151,13 +151,15 @@ func TestCreateKuadrantAuthorizer(t *testing.T) { assert.Equal(t, authorizer.GetEnvoyExtAuthzGrpc().Port, uint32(50051)) } -func TestRemoveKuadrantAuthorizerFromList(t *testing.T) { - providers := getStubbedMeshConfig().ExtensionProviders - providers = append(providers, CreateKuadrantAuthorizer("kuadrant-system")) - providers = RemoveKuadrantAuthorizerFromList(providers) +func TestRemoveKuadrantAuthorizerFromConfig(t *testing.T) { + config := getStubbedMeshConfig() + config.ExtensionProviders = append(config.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) + assert.Equal(t, len(config.ExtensionProviders), 2) + + RemoveKuadrantAuthorizerFromConfig(config) - assert.Equal(t, len(providers), 1) - assert.Equal(t, providers[0].Name, "custom-authorizer") + assert.Equal(t, len(config.ExtensionProviders), 1) + assert.Equal(t, config.ExtensionProviders[0].Name, "custom-authorizer") } func TestUpdateMeshConfig(t *testing.T) { @@ -173,7 +175,8 @@ extensionProviders: `, }, } - updated, err := UpdateMeshConfig(configMap, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + configWrapper := NewConfigMapWrapper(configMap) + updated, err := configWrapper.UpdateConfig(func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) return true }) @@ -190,7 +193,8 @@ extensionProviders: MeshConfig: meshConfig, }, } - updated, err := UpdateMeshConfig(istioOperator, func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { + istioOperatorWrapper := NewOperatorWrapper(istioOperator) + updated, err := istioOperatorWrapper.UpdateConfig(func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) return true }) From e7d3a9e039d402cc5d479641606ca5ed95671994 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Wed, 21 Jun 2023 15:44:37 +0200 Subject: [PATCH 06/10] [go] Fixing dependencies --- go.sum | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go.sum b/go.sum index 29bd59cc9..5461a530e 100644 --- a/go.sum +++ b/go.sum @@ -373,7 +373,9 @@ github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4 github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= +github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -960,6 +962,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From b6931dd4d64948f26dd2285a4fc9a5180f3cdb65 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Wed, 21 Jun 2023 15:45:18 +0200 Subject: [PATCH 07/10] [mesh config] Refactoring mesh config objects and fns --- controllers/kuadrant_controller.go | 148 +++++++++------------- pkg/common/mesh_config.go | 118 +++++++++++++++++ pkg/common/mesh_config_test.go | 96 ++++++++++++++ pkg/istio/mesh_config.go | 186 ++++++++++++--------------- pkg/istio/mesh_config_test.go | 196 ++++++++++++++--------------- 5 files changed, 443 insertions(+), 301 deletions(-) create mode 100644 pkg/common/mesh_config.go create mode 100644 pkg/common/mesh_config_test.go diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index f2f7a97c4..dce7456b8 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -19,7 +19,6 @@ package controllers import ( "context" "encoding/json" - "fmt" corev1 "k8s.io/api/core/v1" @@ -29,8 +28,6 @@ import ( maistrav2 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v2" limitadorv1alpha1 "github.com/kuadrant/limitador-operator/api/v1alpha1" "golang.org/x/sync/errgroup" - "google.golang.org/protobuf/types/known/structpb" - istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1" appsv1 "k8s.io/api/apps/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -105,7 +102,7 @@ func (r *KuadrantReconciler) Reconcile(eventCtx context.Context, req ctrl.Reques if kObj.GetDeletionTimestamp() != nil && controllerutil.ContainsFinalizer(kObj, kuadrantFinalizer) { logger.V(1).Info("Handling removal of kuadrant object") - if err := r.unregisterExternalAuthorizer(ctx); err != nil { + if err := r.unregisterExternalAuthorizer(ctx, kObj); err != nil { return ctrl.Result{}, err } @@ -163,13 +160,13 @@ func (r *KuadrantReconciler) Reconcile(eventCtx context.Context, req ctrl.Reques return ctrl.Result{}, nil } -func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context) error { +func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - err := r.unregisterExternalAuthorizerIstio(ctx) + err := r.unregisterExternalAuthorizerIstio(ctx, kObj) if err != nil && apimeta.IsNoMatchError(err) { - err = r.unregisterExternalAuthorizerOSSM(ctx) + err = r.unregisterExternalAuthorizerOSSM(ctx, kObj) } if err != nil { @@ -179,13 +176,13 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context) e return err } -func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context) error { +func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - var configsToUpdate []istio.ConfigWrapper + var configsToUpdate []common.ConfigWrapper iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} - if err := r.Client().Get(ctx, iopKey, iop); err != nil { + if err := r.GetResource(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) if apimeta.IsNoMatchError(err) { // return err only if there's no istiooperator CRD @@ -197,20 +194,25 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte } istioConfigMap := &corev1.ConfigMap{} - if err := r.Client().Get(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { + if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) + kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) for _, config := range configsToUpdate { - if needsUpdate, err := config.UpdateConfig( - istio.RemoveKuadrantAuthorizerFromConfig, - ); err != nil { + hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(config, *kuadrantAuthorizer) + if err != nil { return err - } else if needsUpdate { - logger.Info("remove external authorizer from meshconfig") - if err := r.Client().Update(ctx, config.GetConfigObject()); err != nil { + } + if hasKuadrantAuthorizer { + if err = common.UnregisterKuadrantAuthorizer(config, kuadrantAuthorizer); err != nil { + return err + } + + logger.Info("remove external authorizer from istio meshconfig") + if err := r.UpdateResource(ctx, config.GetConfigObject()); err != nil { return err } } @@ -218,7 +220,7 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte return nil } -func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Context) error { +func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) smcp := &maistrav2.ServiceMeshControlPlane{} @@ -229,49 +231,24 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Contex return err } - if smcp.Spec.TechPreview == nil { - smcp.Spec.TechPreview = maistrav1.NewHelmValues(nil) - } + smcpWrapper := istio.NewOSSMControlPlaneWrapper(smcp) + kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) - var meshConfig *istiomeshv1alpha1.MeshConfig - - if conf, found, err := smcp.Spec.TechPreview.GetMap("meshConfig"); err != nil { + hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(smcpWrapper, *kuadrantAuthorizer) + if err != nil { return err - } else if found { - meshConfigStruct, err := structpb.NewStruct(conf) + } + if hasKuadrantAuthorizer { + err = common.UnregisterKuadrantAuthorizer(smcpWrapper, kuadrantAuthorizer) if err != nil { return err } - meshConfig, _ = istio.MeshConfigFromStruct(meshConfigStruct) - } else { - meshConfig = &istiomeshv1alpha1.MeshConfig{} - } - extensionProviders := istio.ExtensionProvidersFromMeshConfig(meshConfig) - - if !istio.HasKuadrantAuthorizer(extensionProviders) { - return nil - } - - for idx, extensionProvider := range extensionProviders { - name := extensionProvider.Name - if name == istio.ExtAuthorizerName { - // deletes the element in the array - extensionProviders = append(extensionProviders[:idx], extensionProviders[idx+1:]...) - meshConfig.ExtensionProviders = extensionProviders - meshConfigStruct, err := istio.MeshConfigToStruct(meshConfig) - if err != nil { - return err - } - smcp.Spec.TechPreview.SetField("meshConfig", meshConfigStruct.AsMap()) - break + logger.Info("removing external authorizer from OSSM meshconfig") + if err := r.UpdateResource(ctx, smcpWrapper.GetConfigObject()); err != nil { + return err } } - logger.Info("remove external authorizer from meshconfig") - if err := r.Client().Update(ctx, smcp); err != nil { - return err - } - return nil } @@ -293,11 +270,11 @@ func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kOb func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - var configsToUpdate []istio.ConfigWrapper + var configsToUpdate []common.ConfigWrapper iop := &iopv1alpha1.IstioOperator{} iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} - if err := r.Client().Get(ctx, iopKey, iop); err != nil { + if err := r.GetResource(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) if apimeta.IsNoMatchError(err) { // if it's a no match error (CRD not installed), return the error @@ -310,20 +287,24 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context } istioConfigMap := &corev1.ConfigMap{} - if err := r.Client().Get(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { + if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) return err } configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) - + kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) for _, config := range configsToUpdate { - if needsUpdate, err := config.UpdateConfig( - istio.AddKuadrantAuthorizerToConfig(kObj.Namespace), - ); err != nil { + hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(config, *kuadrantAuthorizer) + if err != nil { return err - } else if needsUpdate { - logger.Info("adding external authorizer to meshconfig") - if err := r.Client().Update(ctx, config.GetConfigObject()); err != nil { + } + if !hasKuadrantAuthorizer { + err := common.RegisterKuadrantAuthorizer(config, kuadrantAuthorizer) + if err != nil { + return err + } + logger.Info("adding external authorizer to istio meshconfig") + if err := r.UpdateResource(ctx, config.GetConfigObject()); err != nil { return err } } @@ -342,43 +323,26 @@ func (r *KuadrantReconciler) registerExternalAuthorizerOSSM(ctx context.Context, smcp := &maistrav2.ServiceMeshControlPlane{} smcpKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} - if err := r.Client().Get(ctx, smcpKey, smcp); err != nil { + if err := r.GetResource(ctx, smcpKey, smcp); err != nil { logger.V(1).Info("failed to get servicemeshcontrolplane object", "key", smcp, "err", err) return err } + smcpWrapper := istio.NewOSSMControlPlaneWrapper(smcp) + kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) - if smcp.Spec.TechPreview == nil { - smcp.Spec.TechPreview = maistrav1.NewHelmValues(nil) - } - - var meshConfig *istiomeshv1alpha1.MeshConfig - - if conf, found, err := smcp.Spec.TechPreview.GetMap("meshConfig"); err != nil { + hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(smcpWrapper, *kuadrantAuthorizer) + if err != nil { return err - } else if found { - meshConfigStruct, err := structpb.NewStruct(conf) + } + if !hasKuadrantAuthorizer { + err = common.RegisterKuadrantAuthorizer(smcpWrapper, kuadrantAuthorizer) if err != nil { return err } - meshConfig, _ = istio.MeshConfigFromStruct(meshConfigStruct) - } else { - meshConfig = &istiomeshv1alpha1.MeshConfig{} - } - extensionProviders := istio.ExtensionProvidersFromMeshConfig(meshConfig) - - if istio.HasKuadrantAuthorizer(extensionProviders) { - return nil - } - - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, istio.CreateKuadrantAuthorizer(kObj.Namespace)) - meshConfigStruct, err := istio.MeshConfigToStruct(meshConfig) - if err != nil { - return err - } - smcp.Spec.TechPreview.SetField("meshConfig", meshConfigStruct.AsMap()) - logger.Info("adding external authorizer to meshconfig") - if err := r.Client().Update(ctx, smcp); err != nil { - return err + logger.Info("adding external authorizer to OSSM meshconfig") + if err := r.UpdateResource(ctx, smcpWrapper.GetConfigObject()); err != nil { + return err + } } return nil diff --git a/pkg/common/mesh_config.go b/pkg/common/mesh_config.go new file mode 100644 index 000000000..4eec3a4f8 --- /dev/null +++ b/pkg/common/mesh_config.go @@ -0,0 +1,118 @@ +package common + +import ( + "fmt" + + istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + ExtAuthorizerName = "kuadrant-authorization" +) + +type Authorizer interface { + GetExtensionProvider() *istiomeshv1alpha1.MeshConfig_ExtensionProvider +} + +type ConfigWrapper interface { + GetConfigObject() client.Object + GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) + SetMeshConfig(*istiomeshv1alpha1.MeshConfig) error +} + +type KuadrantAuthorizer struct { + extensionProvider *istiomeshv1alpha1.MeshConfig_ExtensionProvider +} + +// NewKuadrantAuthorizer Creates a new KuadrantAuthorizer +func NewKuadrantAuthorizer(namespace string) *KuadrantAuthorizer { + return &KuadrantAuthorizer{ + extensionProvider: createKuadrantAuthorizer(namespace), + } +} + +// GetExtensionProvider Returns the Istio MeshConfig ExtensionProvider for Kuadrant +func (k *KuadrantAuthorizer) GetExtensionProvider() *istiomeshv1alpha1.MeshConfig_ExtensionProvider { + return k.extensionProvider +} + +// createKuadrantAuthorizer Creates the Istio MeshConfig ExtensionProvider for Kuadrant +func createKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { + envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ + EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ + Port: 50051, + Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), + }, + } + return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ + Name: ExtAuthorizerName, + Provider: envoyExtAuthGRPC, + } +} + +// HasKuadrantAuthorizer returns true if the IstioOperator has the Kuadrant ExtensionProvider +func HasKuadrantAuthorizer(configWrapper ConfigWrapper, authorizer KuadrantAuthorizer) (bool, error) { + config, err := configWrapper.GetMeshConfig() + if err != nil { + return false, err + } + return hasExtensionProvider(authorizer.GetExtensionProvider(), extensionProvidersFromMeshConfig(config)), nil +} + +// RegisterKuadrantAuthorizer adds the Kuadrant ExtensionProvider to the IstioOperator +func RegisterKuadrantAuthorizer(configWrapper ConfigWrapper, authorizer Authorizer) error { + config, err := configWrapper.GetMeshConfig() + if err != nil { + return err + } + if !hasExtensionProvider(authorizer.GetExtensionProvider(), extensionProvidersFromMeshConfig(config)) { + config.ExtensionProviders = append(config.ExtensionProviders, authorizer.GetExtensionProvider()) + if err = configWrapper.SetMeshConfig(config); err != nil { + return err + } + } + return nil +} + +// UnregisterKuadrantAuthorizer removes the Kuadrant ExtensionProvider from the IstioOperator +func UnregisterKuadrantAuthorizer(configWrapper ConfigWrapper, authorizer Authorizer) error { + config, err := configWrapper.GetMeshConfig() + if err != nil { + return err + } + if hasExtensionProvider(authorizer.GetExtensionProvider(), extensionProvidersFromMeshConfig(config)) { + config.ExtensionProviders = removeExtensionProvider(authorizer.GetExtensionProvider(), extensionProvidersFromMeshConfig(config)) + if err = configWrapper.SetMeshConfig(config); err != nil { + return err + } + } + return nil +} + +func extensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { + extensionProviders = config.ExtensionProviders + if len(extensionProviders) == 0 { + extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + } + return +} + +// hasExtensionProvider returns true if the MeshConfig has an ExtensionProvider with the given name +func hasExtensionProvider(provider *istiomeshv1alpha1.MeshConfig_ExtensionProvider, extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { + for _, extensionProvider := range extensionProviders { + if extensionProvider.Name == provider.Name { + return true + } + } + return false +} + +func removeExtensionProvider(provider *istiomeshv1alpha1.MeshConfig_ExtensionProvider, providers []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) []*istiomeshv1alpha1.MeshConfig_ExtensionProvider { + for i, extensionProvider := range providers { + if extensionProvider.Name == provider.Name { + return append(providers[:i], providers[i+1:]...) + } + } + return providers +} diff --git a/pkg/common/mesh_config_test.go b/pkg/common/mesh_config_test.go new file mode 100644 index 000000000..d0e8a8962 --- /dev/null +++ b/pkg/common/mesh_config_test.go @@ -0,0 +1,96 @@ +//go:build unit +// +build unit + +package common + +import ( + "testing" + + "gotest.tools/assert" + istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func getStubbedMeshConfig() *istiomeshv1alpha1.MeshConfig { + providers := make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) + provider := &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ + Name: "custom-authorizer", + Provider: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ + EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ + Port: 50051, + Service: "custom-authorizer.default.svc.cluster.local", + }, + }, + } + providers = append(providers, provider) + return &istiomeshv1alpha1.MeshConfig{ + ExtensionProviders: providers, + } +} + +type stubbedConfigWrapper struct { + istioMeshConfig *istiomeshv1alpha1.MeshConfig +} + +func (c *stubbedConfigWrapper) SetMeshConfig(config *istiomeshv1alpha1.MeshConfig) error { + c.istioMeshConfig = config + return nil +} + +func (c *stubbedConfigWrapper) GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) { + return c.istioMeshConfig, nil +} + +func (c *stubbedConfigWrapper) GetConfigObject() client.Object { + return nil +} + +func TestKuadrantAuthorizer_GetExtensionProvider(t *testing.T) { + authorizer := NewKuadrantAuthorizer("default") + provider := authorizer.GetExtensionProvider() + + assert.Equal(t, provider.Name, ExtAuthorizerName) + assert.Equal(t, provider.GetEnvoyExtAuthzGrpc().Service, "authorino-authorino-authorization.default.svc.cluster.local") +} + +func TestHasKuadrantAuthorizer(t *testing.T) { + authorizer := NewKuadrantAuthorizer("default") + configWrapper := &stubbedConfigWrapper{getStubbedMeshConfig()} + + hasAuthorizer, err := HasKuadrantAuthorizer(configWrapper, *authorizer) + + assert.NilError(t, err) + assert.Equal(t, hasAuthorizer, false) + + configWrapper.istioMeshConfig.ExtensionProviders = append(configWrapper.istioMeshConfig.ExtensionProviders, authorizer.GetExtensionProvider()) + hasAuthorizer, err = HasKuadrantAuthorizer(configWrapper, *authorizer) + assert.NilError(t, err) + assert.Equal(t, hasAuthorizer, true) +} + +func TestRegisterKuadrantAuthorizer(t *testing.T) { + authorizer := NewKuadrantAuthorizer("default") + configWrapper := &stubbedConfigWrapper{getStubbedMeshConfig()} + + err := RegisterKuadrantAuthorizer(configWrapper, authorizer) + assert.NilError(t, err) + + meshConfig, _ := configWrapper.GetMeshConfig() + assert.Equal(t, meshConfig.ExtensionProviders[1].Name, "kuadrant-authorization") +} + +func TestUnregisterKuadrantAuthorizer(t *testing.T) { + authorizer := NewKuadrantAuthorizer("default") + configWrapper := &stubbedConfigWrapper{getStubbedMeshConfig()} + + err := RegisterKuadrantAuthorizer(configWrapper, authorizer) + assert.NilError(t, err) + assert.Equal(t, len(configWrapper.istioMeshConfig.ExtensionProviders), 2) + + err = UnregisterKuadrantAuthorizer(configWrapper, authorizer) + assert.NilError(t, err) + assert.Equal(t, len(configWrapper.istioMeshConfig.ExtensionProviders), 1) + + meshConfig, _ := configWrapper.GetMeshConfig() + assert.Equal(t, meshConfig.GetExtensionProviders()[0].Name, "custom-authorizer") +} diff --git a/pkg/istio/mesh_config.go b/pkg/istio/mesh_config.go index bc8800135..0cd23eb19 100644 --- a/pkg/istio/mesh_config.go +++ b/pkg/istio/mesh_config.go @@ -2,6 +2,8 @@ package istio import ( "fmt" + + maistrav2 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v2" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" @@ -12,16 +14,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const ( - ExtAuthorizerName = "kuadrant-authorization" -) - -// ConfigWrapper wraps the IstioOperator CRD or ConfigMap -type ConfigWrapper interface { - GetConfigObject() client.Object - GetConfig() (*istiomeshv1alpha1.MeshConfig, error) - UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) -} +// The structs below implement the interface defined in pkg/common/mesh_config.go `ConfigWrapper` +// type ConfigWrapper interface { +// GetConfigObject() client.Object +// GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) +// SetMeshConfig(*istiomeshv1alpha1.MeshConfig) error +// } // OperatorWrapper wraps the IstioOperator CRD type OperatorWrapper struct { @@ -38,29 +36,22 @@ func (w *OperatorWrapper) GetConfigObject() client.Object { return w.config } -// GetConfig returns the IstioOperator MeshConfig -func (w *OperatorWrapper) GetConfig() (*istiomeshv1alpha1.MeshConfig, error) { +// GetMeshConfig returns the IstioOperator MeshConfig +func (w *OperatorWrapper) GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) { if w.config.Spec == nil { w.config.Spec = &istioapiv1alpha1.IstioOperatorSpec{} } - return MeshConfigFromStruct(w.config.Spec.MeshConfig) + return meshConfigFromStruct(w.config.Spec.MeshConfig) } -// UpdateConfig updates the IstioOperator with the new MeshConfig and returns true if the MeshConfig was updated -func (w *OperatorWrapper) UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { - config, err := w.GetConfig() +// SetMeshConfig sets the IstioOperator MeshConfig +func (w *OperatorWrapper) SetMeshConfig(config *istiomeshv1alpha1.MeshConfig) error { + meshConfigStruct, err := meshConfigToStruct(config) if err != nil { - return false, err - } - if updateFunc(config) { - meshConfigStruct, err := MeshConfigToStruct(config) - if err != nil { - return false, err - } - w.config.Spec.MeshConfig = meshConfigStruct - return true, nil + return err } - return false, nil + w.config.Spec.MeshConfig = meshConfigStruct + return nil } // ConfigMapWrapper wraps the ConfigMap holding the Istio MeshConfig @@ -78,34 +69,71 @@ func (w *ConfigMapWrapper) GetConfigObject() client.Object { return w.config } -// GetConfig returns the MeshConfig from the ConfigMap -func (w *ConfigMapWrapper) GetConfig() (*istiomeshv1alpha1.MeshConfig, error) { +// GetMeshConfig returns the MeshConfig from the ConfigMap +func (w *ConfigMapWrapper) GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) { meshConfigString, ok := w.config.Data["mesh"] if !ok { return nil, fmt.Errorf("mesh config not found in ConfigMap") } - return MeshConfigFromString(meshConfigString) + return meshConfigFromString(meshConfigString) } -// UpdateConfig updates the ConfigMap with the new MeshConfig and returns true if the ConfigMap was updated -func (w *ConfigMapWrapper) UpdateConfig(updateFunc func(meshConfig *istiomeshv1alpha1.MeshConfig) bool) (bool, error) { - config, err := w.GetConfig() +// SetMeshConfig sets the MeshConfig in the ConfigMap +func (w *ConfigMapWrapper) SetMeshConfig(config *istiomeshv1alpha1.MeshConfig) error { + meshConfigString, err := meshConfigToString(config) if err != nil { - return false, err + return err } + w.config.Data["mesh"] = meshConfigString + return nil +} + +// OSSMControlPlaneWrapper wraps the OSSM ServiceMeshControlPlane +type OSSMControlPlaneWrapper struct { + config *maistrav2.ServiceMeshControlPlane +} - if updateFunc(config) { - meshString, err := meshConfigToString(config) +// NewOSSMControlPlaneWrapper creates a new OSSMControlPlaneWrapper +func NewOSSMControlPlaneWrapper(config *maistrav2.ServiceMeshControlPlane) *OSSMControlPlaneWrapper { + return &OSSMControlPlaneWrapper{config: config} +} + +// GetConfigObject returns the OSSM ServiceMeshControlPlane +func (w *OSSMControlPlaneWrapper) GetConfigObject() client.Object { + return w.config +} + +// GetMeshConfig returns the MeshConfig from the OSSM ServiceMeshControlPlane +func (w *OSSMControlPlaneWrapper) GetMeshConfig() (*istiomeshv1alpha1.MeshConfig, error) { + if config, found, err := w.config.Spec.TechPreview.GetMap("meshConfig"); err != nil { + return nil, err + } else if found { + meshConfigStruct, err := structpb.NewStruct(config) + if err != nil { + return nil, err + } + meshConfig, err := meshConfigFromStruct(meshConfigStruct) if err != nil { - return false, err + return nil, err } - w.config.Data["mesh"] = meshString - return true, nil + return meshConfig, nil } - return false, nil + return &istiomeshv1alpha1.MeshConfig{}, nil } -// MeshConfigFromStruct Builds the Istio/OSSM MeshConfig from a compatible structure: +// SetMeshConfig sets the MeshConfig in the OSSM ServiceMeshControlPlane +func (w *OSSMControlPlaneWrapper) SetMeshConfig(config *istiomeshv1alpha1.MeshConfig) error { + meshConfigStruct, err := meshConfigToStruct(config) + if err != nil { + return err + } + if err := w.config.Spec.TechPreview.SetField("meshConfig", meshConfigStruct.AsMap()); err != nil { + return err + } + return nil +} + +// meshConfigFromStruct Builds the Istio/OSSM MeshConfig from a compatible structure: // // meshConfig: // extensionProviders: @@ -113,7 +141,7 @@ func (w *ConfigMapWrapper) UpdateConfig(updateFunc func(meshConfig *istiomeshv1a // port: // service: // name: kuadrant-authorization -func MeshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { +func meshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshConfig, error) { if structure == nil { return &istiomeshv1alpha1.MeshConfig{}, nil } @@ -131,18 +159,8 @@ func MeshConfigFromStruct(structure *structpb.Struct) (*istiomeshv1alpha1.MeshCo return meshConfig, nil } -// MeshConfigFromString returns the Istio MeshConfig from a ConfigMap -func MeshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { - meshConfig := &istiomeshv1alpha1.MeshConfig{} - err := protomarshal.ApplyYAML(config, meshConfig) - if err != nil { - return nil, err - } - return meshConfig, nil -} - -// MeshConfigToStruct Marshals the Istio MeshConfig into a struct -func MeshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { +// meshConfigToStruct Marshals the Istio MeshConfig into a struct +func meshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, error) { configJSON, err := protojson.Marshal(config) if err != nil { return nil, err @@ -155,62 +173,14 @@ func MeshConfigToStruct(config *istiomeshv1alpha1.MeshConfig) (*structpb.Struct, return configStruct, nil } -// ExtensionProvidersFromMeshConfig Returns the Istio MeshConfig ExtensionProviders -func ExtensionProvidersFromMeshConfig(config *istiomeshv1alpha1.MeshConfig) (extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) { - extensionProviders = config.ExtensionProviders - if len(extensionProviders) == 0 { - extensionProviders = make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) - } - return -} - -// HasKuadrantAuthorizer Checks if the Istio MeshConfig has the ExtensionProvider for Kuadrant -func HasKuadrantAuthorizer(extensionProviders []*istiomeshv1alpha1.MeshConfig_ExtensionProvider) bool { - for _, extensionProvider := range extensionProviders { - if extensionProvider.Name == ExtAuthorizerName { - return true - } - } - - return false -} - -// RemoveKuadrantAuthorizerFromConfig Removes the Istio MeshConfig ExtensionProvider for Kuadrant -func RemoveKuadrantAuthorizerFromConfig(config *istiomeshv1alpha1.MeshConfig) bool { - for i, extProvider := range config.ExtensionProviders { - if extProvider.Name == ExtAuthorizerName { - fmt.Println("Removing Kuadrant Authorizer from MeshConfig", config.ExtensionProviders) - config.ExtensionProviders = append(config.ExtensionProviders[:i], config.ExtensionProviders[i+1:]...) - fmt.Println("Removing Kuadrant Authorizer from MeshConfig", config.ExtensionProviders) - return true - } - } - return false -} - -// AddKuadrantAuthorizerToConfig Adds the Istio MeshConfig ExtensionProvider for Kuadrant -func AddKuadrantAuthorizerToConfig(namespace string) func(config *istiomeshv1alpha1.MeshConfig) bool { - return func(config *istiomeshv1alpha1.MeshConfig) bool { - if HasKuadrantAuthorizer(config.ExtensionProviders) { - return false - } - config.ExtensionProviders = append(config.ExtensionProviders, CreateKuadrantAuthorizer(namespace)) - return true - } -} - -// CreateKuadrantAuthorizer Creates the Istio MeshConfig ExtensionProvider for Kuadrant -func CreateKuadrantAuthorizer(namespace string) *istiomeshv1alpha1.MeshConfig_ExtensionProvider { - envoyExtAuthGRPC := &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExtAuthzGrpc{ - EnvoyExtAuthzGrpc: &istiomeshv1alpha1.MeshConfig_ExtensionProvider_EnvoyExternalAuthorizationGrpcProvider{ - Port: 50051, - Service: fmt.Sprintf("authorino-authorino-authorization.%s.svc.cluster.local", namespace), - }, - } - return &istiomeshv1alpha1.MeshConfig_ExtensionProvider{ - Name: ExtAuthorizerName, - Provider: envoyExtAuthGRPC, +// meshConfigFromString returns the Istio MeshConfig from a ConfigMap +func meshConfigFromString(config string) (*istiomeshv1alpha1.MeshConfig, error) { + meshConfig := &istiomeshv1alpha1.MeshConfig{} + err := protomarshal.ApplyYAML(config, meshConfig) + if err != nil { + return nil, err } + return meshConfig, nil } // meshConfigToString returns the Istio MeshConfig as a string diff --git a/pkg/istio/mesh_config_test.go b/pkg/istio/mesh_config_test.go index 485a1d770..916c7397f 100644 --- a/pkg/istio/mesh_config_test.go +++ b/pkg/istio/mesh_config_test.go @@ -6,6 +6,8 @@ package istio import ( "testing" + maistrav1 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v1" + maistrav2 "github.com/kuadrant/kuadrant-operator/api/external/maistra/v2" "google.golang.org/protobuf/types/known/structpb" "gotest.tools/assert" istiomeshv1alpha1 "istio.io/api/mesh/v1alpha1" @@ -31,10 +33,8 @@ func getStubbedMeshConfig() *istiomeshv1alpha1.MeshConfig { } } -func TestMeshConfigFromStruct(t *testing.T) { - expectedConfig := getStubbedMeshConfig() - - config := &structpb.Struct{ +func getStubbedMeshConfigStruct() *structpb.Struct { + return &structpb.Struct{ Fields: map[string]*structpb.Value{ "extensionProviders": { Kind: &structpb.Value_ListValue{ @@ -77,130 +77,124 @@ func TestMeshConfigFromStruct(t *testing.T) { }, }, } - - meshConfig, _ := MeshConfigFromStruct(config) - - assert.Equal(t, meshConfig.ExtensionProviders[0].Name, expectedConfig.ExtensionProviders[0].Name) - assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service) - assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port) } -func TestMeshConfigFromString(t *testing.T) { - expectedConfig := getStubbedMeshConfig() +func TestOperatorWrapper_GetConfigObject(t *testing.T) { + config := &iopv1alpha1.IstioOperator{} + wrapper := NewOperatorWrapper(config) - config := ` -extensionProviders: -- name: "custom-authorizer" - envoyExtAuthzGrpc: - service: "custom-authorizer.default.svc.cluster.local" - port: "50051" -` + assert.Equal(t, wrapper.GetConfigObject(), config) +} - meshConfig, _ := MeshConfigFromString(config) +func TestOperatorWrapper_GetMeshConfig(t *testing.T) { + structConfig := getStubbedMeshConfigStruct() - assert.Equal(t, meshConfig.ExtensionProviders[0].Name, expectedConfig.ExtensionProviders[0].Name) - assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Service) - assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port, expectedConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().Port) + config := &iopv1alpha1.IstioOperator{ + Spec: &istioapiv1alpha1.IstioOperatorSpec{ + MeshConfig: structConfig, + }, + } + wrapper := NewOperatorWrapper(config) + meshConfig, err := wrapper.GetMeshConfig() + assert.NilError(t, err) + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) } -func TestMeshConfigToStruct(t *testing.T) { - config := getStubbedMeshConfig() +func TestOperatorWrapper_SetMeshConfig(t *testing.T) { + config := &iopv1alpha1.IstioOperator{ + Spec: &istioapiv1alpha1.IstioOperatorSpec{}, + } + wrapper := NewOperatorWrapper(config) - meshConfig, _ := MeshConfigToStruct(config) + stubbedMeshConfig := getStubbedMeshConfig() + err := wrapper.SetMeshConfig(stubbedMeshConfig) + assert.NilError(t, err) - assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["name"].GetStringValue(), "custom-authorizer") - assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["envoyExtAuthzGrpc"].GetStructValue().Fields["service"].GetStringValue(), "custom-authorizer.default.svc.cluster.local") - assert.Equal(t, meshConfig.Fields["extensionProviders"].GetListValue().Values[0].GetStructValue().Fields["envoyExtAuthzGrpc"].GetStructValue().Fields["port"].GetNumberValue(), float64(50051)) -} + meshConfig, _ := wrapper.GetMeshConfig() -func TestExtensionProvidersFromMeshConfig(t *testing.T) { - config := getStubbedMeshConfig() + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, stubbedMeshConfig.ExtensionProviders[0].Name) + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) +} - extensionProviders := ExtensionProvidersFromMeshConfig(config) +func TestConfigMapWrapper_GetConfigObject(t *testing.T) { + configMap := &corev1.ConfigMap{} + wrapper := NewConfigMapWrapper(configMap) - assert.Equal(t, extensionProviders[0].Name, "custom-authorizer") - assert.Equal(t, extensionProviders[0].GetEnvoyExtAuthzGrpc().Service, "custom-authorizer.default.svc.cluster.local") - assert.Equal(t, extensionProviders[0].GetEnvoyExtAuthzGrpc().Port, uint32(50051)) + assert.Equal(t, wrapper.GetConfigObject(), configMap) } -func TestExtensionProvidersFromMeshConfigWithEmptyConfig(t *testing.T) { - config := &istiomeshv1alpha1.MeshConfig{} - - extensionProviders := ExtensionProvidersFromMeshConfig(config) +func TestConfigMapWrapper_GetMeshConfig(t *testing.T) { + configMap := &corev1.ConfigMap{ + Data: map[string]string{ + "mesh": ` +extensionProviders: +- name: "custom-authorizer" + envoyExtAuthzGrpc: + service: "custom-authorizer.default.svc.cluster.local" + port: "50051" +`, + }, + } + wrapper := NewConfigMapWrapper(configMap) - assert.Equal(t, len(extensionProviders), 0) + meshConfig, _ := wrapper.GetMeshConfig() + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) } -func TestHasKuadrantAuthorizer(t *testing.T) { - configWithNoKuadrantAuth := getStubbedMeshConfig().ExtensionProviders +func TestConfigMapWrapper_SetMeshConfig(t *testing.T) { + configMap := &corev1.ConfigMap{ + Data: map[string]string{ + "mesh": "", + }, + } + wrapper := NewConfigMapWrapper(configMap) + + stubbedMeshConfig := getStubbedMeshConfig() + err := wrapper.SetMeshConfig(stubbedMeshConfig) + assert.NilError(t, err) - configWithKuadrantAuth := make([]*istiomeshv1alpha1.MeshConfig_ExtensionProvider, 0) - kuadrantAuthProvider := CreateKuadrantAuthorizer("kuadrant-system") - configWithKuadrantAuth = append(configWithKuadrantAuth, kuadrantAuthProvider) + meshConfig, _ := wrapper.GetMeshConfig() - assert.Equal(t, HasKuadrantAuthorizer(configWithNoKuadrantAuth), false) - assert.Equal(t, HasKuadrantAuthorizer(configWithKuadrantAuth), true) + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) } -func TestCreateKuadrantAuthorizer(t *testing.T) { - authorizer := CreateKuadrantAuthorizer("kuadrant-system") +func TestOSSMControlPlaneWrapper_GetConfigObject(t *testing.T) { + ossmControlPlane := &maistrav2.ServiceMeshControlPlane{} + wrapper := NewOSSMControlPlaneWrapper(ossmControlPlane) - assert.Equal(t, authorizer.Name, "kuadrant-authorization") - assert.Equal(t, authorizer.GetEnvoyExtAuthzGrpc().Service, "authorino-authorino-authorization.kuadrant-system.svc.cluster.local") - assert.Equal(t, authorizer.GetEnvoyExtAuthzGrpc().Port, uint32(50051)) + assert.Equal(t, wrapper.GetConfigObject(), ossmControlPlane) } -func TestRemoveKuadrantAuthorizerFromConfig(t *testing.T) { - config := getStubbedMeshConfig() - config.ExtensionProviders = append(config.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) - assert.Equal(t, len(config.ExtensionProviders), 2) +func TestOSSMControlPlaneWrapper_GetMeshConfig(t *testing.T) { + ossmControlPlane := &maistrav2.ServiceMeshControlPlane{} + ossmControlPlane.Spec.TechPreview = maistrav1.NewHelmValues(nil) + ossmControlPlane.Spec.TechPreview.SetField("meshConfig", getStubbedMeshConfigStruct().AsMap()) - RemoveKuadrantAuthorizerFromConfig(config) + wrapper := NewOSSMControlPlaneWrapper(ossmControlPlane) + meshConfig, _ := wrapper.GetMeshConfig() - assert.Equal(t, len(config.ExtensionProviders), 1) - assert.Equal(t, config.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) } -func TestUpdateMeshConfig(t *testing.T) { - t.Run("TestUpdateMeshConfigWithConfigMap", func(t *testing.T) { - configMap := &corev1.ConfigMap{ - Data: map[string]string{ - "mesh": ` -extensionProviders: -- name: "custom-authorizer" - envoyExtAuthzGrpc: - service: "custom-authorizer.default.svc.cluster.local" - port: "50051" -`, - }, - } - configWrapper := NewConfigMapWrapper(configMap) - updated, err := configWrapper.UpdateConfig(func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) - return true - }) - - meshConfig, _ := MeshConfigFromString(configMap.Data["mesh"]) - assert.NilError(t, err) - assert.Equal(t, updated, true) - assert.Equal(t, len(meshConfig.ExtensionProviders), 2) - }) - t.Run("TestUpdateMeshConfigWithIstioOperator", func(t *testing.T) { - meshConfig, _ := MeshConfigToStruct(getStubbedMeshConfig()) - istioOperator := &iopv1alpha1.IstioOperator{ - Spec: &istioapiv1alpha1.IstioOperatorSpec{ - MeshConfig: meshConfig, - }, - } - istioOperatorWrapper := NewOperatorWrapper(istioOperator) - updated, err := istioOperatorWrapper.UpdateConfig(func(meshConfig *istiomeshv1alpha1.MeshConfig) bool { - meshConfig.ExtensionProviders = append(meshConfig.ExtensionProviders, CreateKuadrantAuthorizer("kuadrant-system")) - return true - }) - config := istioOperator.Spec.MeshConfig - assert.NilError(t, err) - assert.Equal(t, updated, true) - assert.Equal(t, len(config.Fields["extensionProviders"].GetListValue().Values), 2) - }) +func TestOSSMControlPlaneWrapper_SetMeshConfig(t *testing.T) { + ossmControlPlane := &maistrav2.ServiceMeshControlPlane{} + ossmControlPlane.Spec.TechPreview = maistrav1.NewHelmValues(nil) + emptyConfig := &structpb.Struct{} + ossmControlPlane.Spec.TechPreview.SetField("meshConfig", emptyConfig.AsMap()) + + wrapper := NewOSSMControlPlaneWrapper(ossmControlPlane) + + stubbedMeshConfig := getStubbedMeshConfig() + err := wrapper.SetMeshConfig(stubbedMeshConfig) + assert.NilError(t, err) + + meshConfig, _ := wrapper.GetMeshConfig() + + assert.Equal(t, meshConfig.ExtensionProviders[0].Name, "custom-authorizer") + assert.Equal(t, meshConfig.ExtensionProviders[0].GetEnvoyExtAuthzGrpc().GetPort(), uint32(50051)) } From ffd9d156d8fc8128f5ad6eba28f92387957fd61a Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Thu, 22 Jun 2023 11:56:35 +0200 Subject: [PATCH 08/10] [controller] Fixing registering logic * Still relying on the istio CRD being installed. If not, means no istio * If it's 404, means it's installed other way than it's operator * If any other error happens, istio is installed, but an error occurred --- controllers/kuadrant_controller.go | 57 ++++++++++++++++-------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index dce7456b8..99e743442 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -19,6 +19,7 @@ package controllers import ( "context" "encoding/json" + "fmt" corev1 "k8s.io/api/core/v1" @@ -163,9 +164,9 @@ func (r *KuadrantReconciler) Reconcile(eventCtx context.Context, req ctrl.Reques func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - err := r.unregisterExternalAuthorizerIstio(ctx, kObj) + isIstioInstalled, err := r.unregisterExternalAuthorizerIstio(ctx, kObj) - if err != nil && apimeta.IsNoMatchError(err) { + if err == nil && !isIstioInstalled { err = r.unregisterExternalAuthorizerOSSM(ctx, kObj) } @@ -176,7 +177,7 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context, k return err } -func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { +func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) (bool, error) { logger, _ := logr.FromContext(ctx) var configsToUpdate []common.ConfigWrapper @@ -185,10 +186,12 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte if err := r.GetResource(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) if apimeta.IsNoMatchError(err) { - // return err only if there's no istiooperator CRD - return err + // return false and nil if there's no istiooperator CRD, means istio is not installed + return false, nil + } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { + // return true and err if there's an error other than not found (no istiooperator CR) + return true, err } - // otherwise, we assume that the control plane is istio but no installed by its operator } else { configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) } @@ -196,7 +199,7 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte istioConfigMap := &corev1.ConfigMap{} if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) - return err + return true, err } configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) @@ -204,20 +207,20 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Conte for _, config := range configsToUpdate { hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(config, *kuadrantAuthorizer) if err != nil { - return err + return true, err } if hasKuadrantAuthorizer { if err = common.UnregisterKuadrantAuthorizer(config, kuadrantAuthorizer); err != nil { - return err + return true, err } logger.Info("remove external authorizer from istio meshconfig") - if err := r.UpdateResource(ctx, config.GetConfigObject()); err != nil { - return err + if err = r.UpdateResource(ctx, config.GetConfigObject()); err != nil { + return true, err } } } - return nil + return true, nil } func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { @@ -255,9 +258,9 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizerOSSM(ctx context.Contex func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { logger, _ := logr.FromContext(ctx) - err := r.registerExternalAuthorizerIstio(ctx, kObj) + isIstioInstalled, err := r.registerExternalAuthorizerIstio(ctx, kObj) - if err != nil && apimeta.IsNoMatchError(err) { + if err == nil && !isIstioInstalled { err = r.registerExternalAuthorizerOSSM(ctx, kObj) } @@ -268,7 +271,7 @@ func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kOb return err } -func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { +func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) (bool, error) { logger, _ := logr.FromContext(ctx) var configsToUpdate []common.ConfigWrapper @@ -277,40 +280,42 @@ func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context if err := r.GetResource(ctx, iopKey, iop); err != nil { logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) if apimeta.IsNoMatchError(err) { - // if it's a no match error (CRD not installed), return the error - // otherwise continue with the fetching of the configmap - return err + logger.V(1).Info("there's no istiooperator CRD", "key", iopKey, "err", err) + // return false and nil if there's no istiooperator CRD, means istio is not installed + return false, nil + } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { + // return true and err if there's an error other than not found (no istiooperator CR) + return true, err } } else { - // if there is no error, add the iop to the list of configs to update configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) } istioConfigMap := &corev1.ConfigMap{} if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) - return err + return true, err } configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) for _, config := range configsToUpdate { hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(config, *kuadrantAuthorizer) if err != nil { - return err + return true, err } if !hasKuadrantAuthorizer { - err := common.RegisterKuadrantAuthorizer(config, kuadrantAuthorizer) + err = common.RegisterKuadrantAuthorizer(config, kuadrantAuthorizer) if err != nil { - return err + return true, err } logger.Info("adding external authorizer to istio meshconfig") - if err := r.UpdateResource(ctx, config.GetConfigObject()); err != nil { - return err + if err = r.UpdateResource(ctx, config.GetConfigObject()); err != nil { + return true, err } } } - return nil + return true, nil } func (r *KuadrantReconciler) registerExternalAuthorizerOSSM(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { From 7194a06bcb0fa83a1931fc2d845a1d4ce55ac58d Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Thu, 22 Jun 2023 12:45:39 +0200 Subject: [PATCH 09/10] =?UTF-8?q?[controller]=C2=A0Refactoring=20istio=20i?= =?UTF-8?q?nstallation=20process?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added ENV for CM name --- controllers/kuadrant_controller.go | 80 +++++++++++++++--------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index 99e743442..82a2a25a7 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -179,29 +179,13 @@ func (r *KuadrantReconciler) unregisterExternalAuthorizer(ctx context.Context, k func (r *KuadrantReconciler) unregisterExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) (bool, error) { logger, _ := logr.FromContext(ctx) - var configsToUpdate []common.ConfigWrapper + configsToUpdate, err := r.getIstioConfigObjects(ctx, logger) + isIstioInstalled := configsToUpdate != nil - iop := &iopv1alpha1.IstioOperator{} - iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} - if err := r.GetResource(ctx, iopKey, iop); err != nil { - logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) - if apimeta.IsNoMatchError(err) { - // return false and nil if there's no istiooperator CRD, means istio is not installed - return false, nil - } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { - // return true and err if there's an error other than not found (no istiooperator CR) - return true, err - } - } else { - configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) + if !isIstioInstalled || err != nil { + return isIstioInstalled, err } - istioConfigMap := &corev1.ConfigMap{} - if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { - logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) - return true, err - } - configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) for _, config := range configsToUpdate { @@ -273,30 +257,13 @@ func (r *KuadrantReconciler) registerExternalAuthorizer(ctx context.Context, kOb func (r *KuadrantReconciler) registerExternalAuthorizerIstio(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) (bool, error) { logger, _ := logr.FromContext(ctx) - var configsToUpdate []common.ConfigWrapper + configsToUpdate, err := r.getIstioConfigObjects(ctx, logger) + isIstioInstalled := configsToUpdate != nil - iop := &iopv1alpha1.IstioOperator{} - iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} - if err := r.GetResource(ctx, iopKey, iop); err != nil { - logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) - if apimeta.IsNoMatchError(err) { - logger.V(1).Info("there's no istiooperator CRD", "key", iopKey, "err", err) - // return false and nil if there's no istiooperator CRD, means istio is not installed - return false, nil - } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { - // return true and err if there's an error other than not found (no istiooperator CR) - return true, err - } - } else { - configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) + if !isIstioInstalled || err != nil { + return isIstioInstalled, err } - istioConfigMap := &corev1.ConfigMap{} - if err := r.GetResource(ctx, client.ObjectKey{Name: "istio", Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { - logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) - return true, err - } - configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) kuadrantAuthorizer := common.NewKuadrantAuthorizer(kObj.Namespace) for _, config := range configsToUpdate { hasKuadrantAuthorizer, err := common.HasKuadrantAuthorizer(config, *kuadrantAuthorizer) @@ -353,6 +320,33 @@ func (r *KuadrantReconciler) registerExternalAuthorizerOSSM(ctx context.Context, return nil } +func (r *KuadrantReconciler) getIstioConfigObjects(ctx context.Context, logger logr.Logger) ([]common.ConfigWrapper, error) { + var configsToUpdate []common.ConfigWrapper + + iop := &iopv1alpha1.IstioOperator{} + iopKey := client.ObjectKey{Name: controlPlaneProviderName(), Namespace: controlPlaneProviderNamespace()} + if err := r.GetResource(ctx, iopKey, iop); err != nil { + logger.V(1).Info("failed to get istiooperator object", "key", iopKey, "err", err) + if apimeta.IsNoMatchError(err) { + // return nil and nil if there's no istiooperator CRD, means istio is not installed + return nil, nil + } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { + // return nil and err if there's an error other than not found (no istiooperator CR) + return nil, err + } + } else { + configsToUpdate = append(configsToUpdate, istio.NewOperatorWrapper(iop)) + } + + istioConfigMap := &corev1.ConfigMap{} + if err := r.GetResource(ctx, client.ObjectKey{Name: controlPlaneConfigMapName(), Namespace: controlPlaneProviderNamespace()}, istioConfigMap); err != nil { + logger.V(1).Info("failed to get istio configMap", "key", iopKey, "err", err) + return configsToUpdate, err + } + configsToUpdate = append(configsToUpdate, istio.NewConfigMapWrapper(istioConfigMap)) + return configsToUpdate, nil +} + func (r *KuadrantReconciler) registerServiceMeshMember(ctx context.Context, kObj *kuadrantv1beta1.Kuadrant) error { member := buildServiceMeshMember(kObj) err := r.SetOwnerReference(kObj, member) @@ -383,6 +377,10 @@ func controlPlaneProviderName() string { return common.FetchEnv("ISTIOOPERATOR_NAME", "istiocontrolplane") } +func controlPlaneConfigMapName() string { + return common.FetchEnv("ISTIOCONFIGMAP_NAME", "istio") +} + func controlPlaneProviderNamespace() string { return common.FetchEnv("ISTIOOPERATOR_NAMESPACE", "istio-system") } From 80734361eb5f0888b680b39fe6bb89ff6e4bf04c Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Tue, 4 Jul 2023 15:40:39 +0200 Subject: [PATCH 10/10] [refactor] Using apierrors.IsNotFound instead of crafting the error msg --- controllers/kuadrant_controller.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controllers/kuadrant_controller.go b/controllers/kuadrant_controller.go index 82a2a25a7..43e313084 100644 --- a/controllers/kuadrant_controller.go +++ b/controllers/kuadrant_controller.go @@ -19,7 +19,6 @@ package controllers import ( "context" "encoding/json" - "fmt" corev1 "k8s.io/api/core/v1" @@ -330,7 +329,7 @@ func (r *KuadrantReconciler) getIstioConfigObjects(ctx context.Context, logger l if apimeta.IsNoMatchError(err) { // return nil and nil if there's no istiooperator CRD, means istio is not installed return nil, nil - } else if err.Error() != fmt.Sprintf("IstioOperator.install.istio.io \"%s\" not found", controlPlaneProviderName()) { + } else if !apierrors.IsNotFound(err) { // return nil and err if there's an error other than not found (no istiooperator CR) return nil, err }