From 398b8c96f05a27e271ce5f4671b394f602004c70 Mon Sep 17 00:00:00 2001 From: dd di cesare Date: Mon, 19 Jun 2023 18:43:04 +0200 Subject: [PATCH] [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 })