From 9f4b709d8a0e80e7c38c2a14c88d8e79ea98c524 Mon Sep 17 00:00:00 2001 From: Ruturaj Mohite Date: Sun, 12 Jun 2022 17:23:03 +0530 Subject: [PATCH] Multi Context Refactor Signed-off-by: Ruturaj Mohite --- go.mod | 2 +- go.sum | 4 +- nginx/custom_operation.go | 4 +- nginx/error.go | 2 +- nginx/install.go | 94 ++++++++++++++++++++------ nginx/nginx.go | 65 ++++++++++++++++-- nginx/oam.go | 41 ++++++------ nginx/sample_apps.go | 136 ++++++++++++++++++++++++++++---------- 8 files changed, 260 insertions(+), 88 deletions(-) diff --git a/go.mod b/go.mod index 2b8836d..30eacc9 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ replace ( ) require ( - github.com/layer5io/meshery-adapter-library v0.5.4 + github.com/layer5io/meshery-adapter-library v0.5.6 github.com/layer5io/meshkit v0.5.20 github.com/layer5io/service-mesh-performance v0.3.4 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 7aedc5e..d03a575 100644 --- a/go.sum +++ b/go.sum @@ -882,8 +882,8 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6Fm github.com/layer5io/kuttl v0.4.1-0.20200723152044-916f10574334/go.mod h1:UmrVd7x+bNVKrpmKgTtfRiTKHZeNPcMjQproJ0vGwhE= github.com/layer5io/learn-layer5/smi-conformance v0.0.0-20210317075357-06b4f88b3e34 h1:QaViadDOBCMDUwYx78kfRvHMkzRVnh/GOhm3s2gxoP4= github.com/layer5io/learn-layer5/smi-conformance v0.0.0-20210317075357-06b4f88b3e34/go.mod h1:BQPLwdJt7v7y0fXIejI4whR9zMyX07Wjt5xrbgEmHLw= -github.com/layer5io/meshery-adapter-library v0.5.4 h1:QQ+nVGHd7KhV58KhY40V00kC+IEM4+AlOhQcSHSbOUE= -github.com/layer5io/meshery-adapter-library v0.5.4/go.mod h1:YmLV0w6ucBagrqUB0x9q8ZVXrhN1tJBP5j+Pu6LOY/M= +github.com/layer5io/meshery-adapter-library v0.5.6 h1:pbZTMkWNcGWPk314K7WhO4UGVxSnKvGLmwQXBWZ05GI= +github.com/layer5io/meshery-adapter-library v0.5.6/go.mod h1:YmLV0w6ucBagrqUB0x9q8ZVXrhN1tJBP5j+Pu6LOY/M= github.com/layer5io/meshkit v0.5.16/go.mod h1:tj5TAjty7T/WJ8YvlDfOZF94t4g3mhWuKBCc6MOUoNU= github.com/layer5io/meshkit v0.5.20 h1:QpN/SEepUZk+Jj2K4TBRZJCRr/pzuvHqDaUr30vWddI= github.com/layer5io/meshkit v0.5.20/go.mod h1:EUfXIcztap9Dh0Ao3Dmoxf3FMsm4h7zFHGwagj+5ra4= diff --git a/nginx/custom_operation.go b/nginx/custom_operation.go index 838d017..3bdff68 100644 --- a/nginx/custom_operation.go +++ b/nginx/custom_operation.go @@ -5,10 +5,10 @@ import ( "github.com/layer5io/meshery-adapter-library/status" ) -func (nginx *Nginx) applyCustomOperation(namespace string, manifest string, isDel bool) (string, error) { +func (nginx *Nginx) applyCustomOperation(namespace string, manifest string, isDel bool, kubeconfigs []string) (string, error) { st := status.Starting - err := nginx.applyManifest([]byte(manifest), isDel, namespace) + err := nginx.applyManifest([]byte(manifest), isDel, namespace, kubeconfigs) if err != nil { return st, ErrCustomOperation(err) } diff --git a/nginx/error.go b/nginx/error.go index 41c15fd..49d77c2 100644 --- a/nginx/error.go +++ b/nginx/error.go @@ -107,7 +107,7 @@ func ErrParseNginxCoreComponent(err error) error { } // ErrLoadNamespace is the occurend while applying namespace -func ErrLoadNamespace(err error, s string) error { +func ErrLoadNamespace(err error) error { return errors.New(ErrLoadNamespaceCode, errors.Alert, []string{"Error occured while applying namespace "}, []string{err.Error()}, []string{"Trying to access a namespace which is not available"}, []string{"Verify presence of namespace. Confirm Meshery ServiceAccount permissions"}) } diff --git a/nginx/install.go b/nginx/install.go index 87127d6..39f9123 100644 --- a/nginx/install.go +++ b/nginx/install.go @@ -3,6 +3,7 @@ package nginx import ( "fmt" "strings" + "sync" "github.com/layer5io/meshery-adapter-library/adapter" "github.com/layer5io/meshery-adapter-library/status" @@ -17,7 +18,7 @@ const ( // Installs NGINX service mesh using helm charts. // Unlike other adapters, doesn't keep CLI as a fallback method -func (nginx *Nginx) installNginx(del bool, version, namespace string) (string, error) { +func (nginx *Nginx) installNginx(del bool, version, namespace string, kubeconfigs []string) (string, error) { nginx.Log.Debug(fmt.Sprintf("Requested install of version: %s", version)) nginx.Log.Debug(fmt.Sprintf("Requested action is delete: %v", del)) nginx.Log.Debug(fmt.Sprintf("Requested action is in namespace: %s", namespace)) @@ -32,7 +33,7 @@ func (nginx *Nginx) installNginx(del bool, version, namespace string) (string, e return st, ErrMeshConfig(err) } - err = nginx.applyHelmChart(del, version, namespace) + err = nginx.applyHelmChart(del, version, namespace, kubeconfigs) if err != nil { nginx.Log.Error(ErrInstallNginx(err)) return st, ErrInstallNginx(err) @@ -44,12 +45,7 @@ func (nginx *Nginx) installNginx(del bool, version, namespace string) (string, e return status.Installed, nil } -func (nginx *Nginx) applyHelmChart(del bool, version, namespace string) error { - kClient := nginx.MesheryKubeclient - if kClient == nil { - return ErrNilClient - } - +func (nginx *Nginx) applyHelmChart(del bool, version, namespace string, kubeconfigs []string) error { chartVersion, err := mesherykube.HelmAppVersionToChartVersion(repo, chart, version) if err != nil { version = strings.TrimPrefix(version, "v") @@ -99,25 +95,79 @@ func (nginx *Nginx) applyHelmChart(del bool, version, namespace string) error { OverrideValues: overrideVal, } - // Install Helm chart. nginx.Log.Info(fmt.Sprintf("Installing NGINX Service Mesh %s using Helm chart: %+v\n", version, c)) - err = kClient.ApplyHelmChart(c) - if err != nil { - return ErrApplyHelmChart(err) + + var wg sync.WaitGroup + var errs []error + var errMx sync.Mutex + + for _, config := range kubeconfigs { + wg.Add(1) + go func(config string) { + defer wg.Done() + kClient, err := mesherykube.New([]byte(config)) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + // Install Helm chart. + err = kClient.ApplyHelmChart(c) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + }(config) + } + wg.Wait() + if len(errs) == 0 { + return nil } - return nil + mergedErrors := mergeErrors(errs) + return ErrApplyHelmChart(mergedErrors) } -func (nginx *Nginx) applyManifest(manifest []byte, isDel bool, namespace string) error { - err := nginx.MesheryKubeclient.ApplyManifest(manifest, mesherykube.ApplyOptions{ - Namespace: namespace, - Update: true, - Delete: isDel, - }) - if err != nil { - return err +func (nginx *Nginx) applyManifest(manifest []byte, isDel bool, namespace string, kubeconfigs []string) error { + var wg sync.WaitGroup + var errs []error + var errMx sync.Mutex + + for _, config := range kubeconfigs { + wg.Add(1) + go func(config string) { + defer wg.Done() + kClient, err := mesherykube.New([]byte(config)) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + err = kClient.ApplyManifest(manifest, mesherykube.ApplyOptions{ + Namespace: namespace, + Update: true, + Delete: isDel, + }) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + }(config) + } + + wg.Wait() + if len(errs) == 0 { + return nil } - return nil + return mergeErrors(errs) } diff --git a/nginx/nginx.go b/nginx/nginx.go index 20ab2e5..248e29d 100644 --- a/nginx/nginx.go +++ b/nginx/nginx.go @@ -10,6 +10,8 @@ import ( "github.com/layer5io/meshery-adapter-library/status" internalconfig "github.com/layer5io/meshery-nginx/internal/config" "github.com/layer5io/meshkit/logger" + "github.com/layer5io/meshkit/models" + "gopkg.in/yaml.v2" ) // Nginx defines a model for this adapter @@ -29,10 +31,16 @@ func New(c adapterconfig.Handler, l logger.Handler, kc adapterconfig.Handler) ad } // ApplyOperation applies the operation on nginx -func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationRequest) error { +func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationRequest, hchan *chan interface{}) error { + err := nginx.CreateKubeconfigs(opReq.K8sConfigs) + if err != nil { + return err + } + kubeConfigs := opReq.K8sConfigs + nginx.SetChannel(hchan); operations := make(adapter.Operations) - err := nginx.Config.GetObject(adapter.OperationsKey, &operations) + err = nginx.Config.GetObject(adapter.OperationsKey, &operations) if err != nil { return err } @@ -49,7 +57,7 @@ func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationR case internalconfig.NginxOperation: go func(hh *Nginx, ee *adapter.Event) { version := string(operations[opReq.OperationName].Versions[0]) - if stat, err = hh.installNginx(opReq.IsDeleteOperation, version, opReq.Namespace); err != nil { + if stat, err = hh.installNginx(opReq.IsDeleteOperation, version, opReq.Namespace, kubeConfigs); err != nil { e.Summary = fmt.Sprintf("Error while %s NGINX Service Mesh", stat) e.Details = err.Error() hh.StreamErr(e, err) @@ -61,7 +69,7 @@ func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationR }(nginx, e) case internalconfig.LabelNamespace: go func(hh *Nginx, ee *adapter.Event) { - err := hh.LoadNamespaceToMesh(opReq.Namespace, opReq.IsDeleteOperation) + err := hh.LoadNamespaceToMesh(opReq.Namespace, opReq.IsDeleteOperation, kubeConfigs) operation := "enabled" if opReq.IsDeleteOperation { operation = "removed" @@ -102,7 +110,7 @@ func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationR case common.BookInfoOperation, common.HTTPBinOperation, common.ImageHubOperation, common.EmojiVotoOperation: go func(hh *Nginx, ee *adapter.Event) { appName := operations[opReq.OperationName].AdditionalProperties[common.ServiceName] - stat, err := hh.installSampleApp(opReq.Namespace, opReq.IsDeleteOperation, operations[opReq.OperationName].Templates) + stat, err := hh.installSampleApp(opReq.Namespace, opReq.IsDeleteOperation, operations[opReq.OperationName].Templates, kubeConfigs) if err != nil { e.Summary = fmt.Sprintf("Error while %s %s application", stat, appName) e.Details = err.Error() @@ -115,7 +123,7 @@ func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationR }(nginx, e) case common.CustomOperation: go func(hh *Nginx, ee *adapter.Event) { - stat, err := hh.applyCustomOperation(opReq.Namespace, opReq.CustomBody, opReq.IsDeleteOperation) + stat, err := hh.applyCustomOperation(opReq.Namespace, opReq.CustomBody, opReq.IsDeleteOperation, kubeConfigs) if err != nil { e.Summary = fmt.Sprintf("Error while %s custom operation", stat) e.Details = err.Error() @@ -132,3 +140,48 @@ func (nginx *Nginx) ApplyOperation(ctx context.Context, opReq adapter.OperationR return nil } + +//CreateKubeconfigs creates and writes passed kubeconfig onto the filesystem +func (nginx *Nginx) CreateKubeconfigs(kubeconfigs []string) error { + var errs = make([]error, 0) + for _, kubeconfig := range kubeconfigs { + kconfig := models.Kubeconfig{} + err := yaml.Unmarshal([]byte(kubeconfig), &kconfig) + if err != nil { + errs = append(errs, err) + continue + } + + // To have control over what exactly to take in on kubeconfig + nginx.KubeconfigHandler.SetKey("kind", kconfig.Kind) + nginx.KubeconfigHandler.SetKey("apiVersion", kconfig.APIVersion) + nginx.KubeconfigHandler.SetKey("current-context", kconfig.CurrentContext) + err = nginx.KubeconfigHandler.SetObject("preferences", kconfig.Preferences) + if err != nil { + errs = append(errs, err) + continue + } + + err = nginx.KubeconfigHandler.SetObject("clusters", kconfig.Clusters) + if err != nil { + errs = append(errs, err) + continue + } + + err = nginx.KubeconfigHandler.SetObject("users", kconfig.Users) + if err != nil { + errs = append(errs, err) + continue + } + + err = nginx.KubeconfigHandler.SetObject("contexts", kconfig.Contexts) + if err != nil { + errs = append(errs, err) + continue + } + } + if len(errs) == 0 { + return nil + } + return mergeErrors(errs) +} diff --git a/nginx/oam.go b/nginx/oam.go index 1734f73..9b31035 100644 --- a/nginx/oam.go +++ b/nginx/oam.go @@ -8,12 +8,18 @@ import ( "github.com/layer5io/meshery-adapter-library/adapter" "github.com/layer5io/meshery-nginx/nginx/oam" "github.com/layer5io/meshkit/models/oam/core/v1alpha1" - mesherykube "github.com/layer5io/meshkit/utils/kubernetes" "gopkg.in/yaml.v2" ) // ProcessOAM will handles the grpc invocation for handling OAM objects -func (nginx *Nginx) ProcessOAM(ctx context.Context, oamReq adapter.OAMRequest) (string, error) { +func (nginx *Nginx) ProcessOAM(ctx context.Context, oamReq adapter.OAMRequest, hchan *chan interface{}) (string, error) { + nginx.SetChannel(hchan) + err := nginx.CreateKubeconfigs(oamReq.K8sConfigs) + if err != nil { + return "", err + } + kubeConfigs := oamReq.K8sConfigs + var comps []v1alpha1.Component for _, acomp := range oamReq.OamComps { comp, err := oam.ParseApplicationComponent(acomp) @@ -32,13 +38,13 @@ func (nginx *Nginx) ProcessOAM(ctx context.Context, oamReq adapter.OAMRequest) ( // If operation is delete then first HandleConfiguration and then handle the deployment if oamReq.DeleteOp { // Process configuration - msg2, err := nginx.HandleApplicationConfiguration(config, oamReq.DeleteOp) + msg2, err := nginx.HandleApplicationConfiguration(config, oamReq.DeleteOp, kubeConfigs) if err != nil { return msg2, ErrProcessOAM(err) } // Process components - msg1, err := nginx.HandleComponents(comps, oamReq.DeleteOp) + msg1, err := nginx.HandleComponents(comps, oamReq.DeleteOp, kubeConfigs) if err != nil { return msg1 + "\n" + msg2, ErrProcessOAM(err) } @@ -46,13 +52,13 @@ func (nginx *Nginx) ProcessOAM(ctx context.Context, oamReq adapter.OAMRequest) ( return msg1 + "\n" + msg2, nil } // Process components - msg1, err := nginx.HandleComponents(comps, oamReq.DeleteOp) + msg1, err := nginx.HandleComponents(comps, oamReq.DeleteOp, kubeConfigs) if err != nil { return msg1, ErrProcessOAM(err) } // Process configuration - msg2, err := nginx.HandleApplicationConfiguration(config, oamReq.DeleteOp) + msg2, err := nginx.HandleApplicationConfiguration(config, oamReq.DeleteOp, kubeConfigs) if err != nil { return msg1 + "\n" + msg2, ErrProcessOAM(err) } @@ -61,10 +67,10 @@ func (nginx *Nginx) ProcessOAM(ctx context.Context, oamReq adapter.OAMRequest) ( } // CompHandler is the type for functions which can handle OAM components -type CompHandler func(*Nginx, v1alpha1.Component, bool) (string, error) +type CompHandler func(*Nginx, v1alpha1.Component, bool, []string) (string, error) //HandleComponents handles the parsed oam components from pattern file -func (nginx *Nginx) HandleComponents(comps []v1alpha1.Component, isDel bool) (string, error) { +func (nginx *Nginx) HandleComponents(comps []v1alpha1.Component, isDel bool, kubeconfigs []string) (string, error) { var errs []error var msgs []string @@ -74,7 +80,7 @@ func (nginx *Nginx) HandleComponents(comps []v1alpha1.Component, isDel bool) (st for _, comp := range comps { fnc, ok := compFuncMap[comp.Spec.Type] if !ok { - msg, err := handleNginxCoreComponents(nginx, comp, isDel, "", "") + msg, err := handleNginxCoreComponents(nginx, comp, isDel, "", "", kubeconfigs) if err != nil { errs = append(errs, err) continue @@ -84,7 +90,7 @@ func (nginx *Nginx) HandleComponents(comps []v1alpha1.Component, isDel bool) (st continue } - msg, err := fnc(nginx, comp, isDel) + msg, err := fnc(nginx, comp, isDel, kubeconfigs) if err != nil { errs = append(errs, err) continue @@ -100,7 +106,7 @@ func (nginx *Nginx) HandleComponents(comps []v1alpha1.Component, isDel bool) (st } // HandleApplicationConfiguration handles the processing of OAM application configuration -func (nginx *Nginx) HandleApplicationConfiguration(config v1alpha1.Configuration, isDel bool) (string, error) { +func (nginx *Nginx) HandleApplicationConfiguration(config v1alpha1.Configuration, isDel bool, kubeconfigs []string) (string, error) { var errs []error var msgs []string for _, comp := range config.Spec.Components { @@ -119,13 +125,13 @@ func (nginx *Nginx) HandleApplicationConfiguration(config v1alpha1.Configuration return mergeMsgs(msgs), nil } -func handleComponentNginxMesh(c *Nginx, comp v1alpha1.Component, isDelete bool) (string, error) { +func handleComponentNginxMesh(c *Nginx, comp v1alpha1.Component, isDelete bool, kubeconfigs []string) (string, error) { // Get the Nginx version from the settings // we are sure that the version of Nginx would be present // because the configuration is already validated against the schema version := comp.Spec.Settings["version"].(string) - msg, err := c.installNginx(isDelete, version, comp.Namespace) + msg, err := c.installNginx(isDelete, version, comp.Namespace, kubeconfigs) if err != nil { return fmt.Sprintf("%s: %s", comp.Name, msg), err } @@ -138,7 +144,8 @@ func handleNginxCoreComponents( comp v1alpha1.Component, isDel bool, apiVersion, - kind string) (string, error) { + kind string, + kubeconfigs []string) (string, error) { if apiVersion == "" { apiVersion = getAPIVersionFromComponent(comp) if apiVersion == "" { @@ -176,11 +183,7 @@ func handleNginxCoreComponents( msg = fmt.Sprintf("deleted %s config \"%s\" in namespace \"%s\"", kind, comp.Name, comp.Namespace) } - return msg, c.MesheryKubeclient.ApplyManifest(yamlByt, mesherykube.ApplyOptions{ - Namespace: comp.Namespace, - Update: true, - Delete: isDel, - }) + return msg, c.applyManifest(yamlByt, isDel, comp.Namespace, kubeconfigs) } func getAPIVersionFromComponent(comp v1alpha1.Component) string { return comp.Annotations["pattern.meshery.io.mesh.workload.k8sAPIVersion"] diff --git a/nginx/sample_apps.go b/nginx/sample_apps.go index debcc9b..adfded2 100644 --- a/nginx/sample_apps.go +++ b/nginx/sample_apps.go @@ -5,14 +5,16 @@ import ( "fmt" "io/ioutil" "strings" + "sync" "github.com/layer5io/meshery-adapter-library/adapter" "github.com/layer5io/meshery-adapter-library/status" "github.com/layer5io/meshkit/utils" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + mesherykube "github.com/layer5io/meshkit/utils/kubernetes" ) -func (nginx *Nginx) installSampleApp(namespace string, del bool, templates []adapter.Template) (string, error) { +func (nginx *Nginx) installSampleApp(namespace string, del bool, templates []adapter.Template, kubeconfigs []string) (string, error) { st := status.Installing if del { @@ -25,7 +27,7 @@ func (nginx *Nginx) installSampleApp(namespace string, del bool, templates []ada return st, ErrSampleApp(err) } - err = nginx.applyManifest([]byte(contents), del, namespace) + err = nginx.applyManifest([]byte(contents), del, namespace, kubeconfigs) if err != nil { return st, ErrSampleApp(err) } @@ -69,48 +71,112 @@ func readLocalFile(location string) (string, error) { } // LoadToMesh is used to mark deployment for automatic sidecar injection (or not) -func (nginx *Nginx) LoadToMesh(namespace string, service string, remove bool) error { - deploy, err := nginx.KubeClient.AppsV1().Deployments(namespace).Get(context.TODO(), service, metav1.GetOptions{}) - if err != nil { - return err - } - - if deploy.ObjectMeta.Labels == nil { - deploy.ObjectMeta.Labels = map[string]string{} +func (nginx *Nginx) LoadToMesh(namespace string, service string, remove bool, kubeconfigs []string) error { + var wg sync.WaitGroup + var errs []error + var errMx sync.Mutex + + for _, config := range kubeconfigs { + wg.Add(1) + go func(config string) { + defer wg.Done() + kClient, err := mesherykube.New([]byte(config)) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + deploy, err := kClient.KubeClient.AppsV1().Deployments(namespace).Get(context.TODO(), service, metav1.GetOptions{}) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + if deploy.ObjectMeta.Labels == nil { + deploy.ObjectMeta.Labels = map[string]string{} + } + + deploy.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "true" + + if remove { + deploy.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "false" + } + + _, err = kClient.KubeClient.AppsV1().Deployments(namespace).Update(context.TODO(), deploy, metav1.UpdateOptions{}) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + }(config) } - deploy.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "true" - if remove { - deploy.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "false" - } - - _, err = nginx.KubeClient.AppsV1().Deployments(namespace).Update(context.TODO(), deploy, metav1.UpdateOptions{}) - if err != nil { - return err + wg.Wait() + if len(errs) == 0 { + return nil } - return nil + return mergeErrors(errs) } // LoadNamespaceToMesh is used to mark namespaces for automatic sidecar injection (or not) -func (nginx *Nginx) LoadNamespaceToMesh(namespace string, remove bool) error { - ns, err := nginx.KubeClient.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) - if err != nil { - return ErrLoadNamespace(err, namespace) - } - - if ns.ObjectMeta.Labels == nil { - ns.ObjectMeta.Labels = map[string]string{} +func (nginx *Nginx) LoadNamespaceToMesh(namespace string, remove bool, kubeconfigs []string) error { + var wg sync.WaitGroup + var errs []error + var errMx sync.Mutex + + for _, config := range kubeconfigs { + wg.Add(1) + go func(config string) { + defer wg.Done() + kClient, err := mesherykube.New([]byte(config)) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + ns, err := kClient.KubeClient.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + if ns.ObjectMeta.Labels == nil { + ns.ObjectMeta.Labels = map[string]string{} + } + //appmesh.k8s.aws/sidecarInjectorWebhook + ns.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "true" + + if remove { + ns.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "false" + } + + _, err = kClient.KubeClient.CoreV1().Namespaces().Update(context.TODO(), ns, metav1.UpdateOptions{}) + if err != nil { + errMx.Lock() + errs = append(errs, err) + errMx.Unlock() + return + } + + + }(config) } - ns.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "true" - if remove { - ns.ObjectMeta.Labels["injector.nsm.nginx.com/auto-inject"] = "false" + wg.Wait() + if len(errs) == 0 { + return nil } - _, err = nginx.KubeClient.CoreV1().Namespaces().Update(context.TODO(), ns, metav1.UpdateOptions{}) - if err != nil { - return err - } - return ErrLoadNamespace(err, namespace) + return ErrLoadNamespace(mergeErrors(errs)) }