diff options
Diffstat (limited to 'src/k8splugin/internal/app/client.go')
-rw-r--r-- | src/k8splugin/internal/app/client.go | 181 |
1 files changed, 34 insertions, 147 deletions
diff --git a/src/k8splugin/internal/app/client.go b/src/k8splugin/internal/app/client.go index 158d21de..9a5aa9e9 100644 --- a/src/k8splugin/internal/app/client.go +++ b/src/k8splugin/internal/app/client.go @@ -16,15 +16,16 @@ package app import ( "log" "os" - "strings" + "time" - utils "k8splugin/internal" "k8splugin/internal/config" "k8splugin/internal/connection" "k8splugin/internal/helm" + "k8splugin/internal/plugin" pkgerrors "github.com/pkg/errors" "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -32,16 +33,12 @@ import ( "k8s.io/client-go/tools/clientcmd" ) -// PluginReference is the interface that is implemented -type PluginReference interface { - Create(yamlFilePath string, namespace string, client *KubernetesClient) (string, error) - Delete(resource helm.KubernetesResource, namespace string, client *KubernetesClient) error -} - +// KubernetesClient encapsulates the different clients' interfaces +// we need when interacting with a Kubernetes cluster type KubernetesClient struct { - clientSet *kubernetes.Clientset + clientSet kubernetes.Interface dynamicClient dynamic.Interface - discoverClient *discovery.DiscoveryClient + discoverClient discovery.CachedDiscoveryInterface restMapper meta.RESTMapper } @@ -86,40 +83,35 @@ func (k *KubernetesClient) init(cloudregion string) error { return pkgerrors.Wrap(err, "Creating dynamic client") } - k.discoverClient, err = discovery.NewDiscoveryClientForConfig(config) + k.discoverClient, err = discovery.NewCachedDiscoveryClientForConfig(config, os.TempDir(), "", 10*time.Minute) if err != nil { return pkgerrors.Wrap(err, "Creating discovery client") } + k.restMapper = restmapper.NewDeferredDiscoveryRESTMapper(k.discoverClient) return nil } func (k *KubernetesClient) ensureNamespace(namespace string) error { - namespacePlugin, ok := utils.LoadedPlugins["namespace"] - if !ok { - return pkgerrors.New("No plugin for namespace resource found") - } - symGetNamespaceFunc, err := namespacePlugin.Lookup("Get") + pluginImpl, err := plugin.GetPluginByKind("Namespace") if err != nil { - return pkgerrors.Wrap(err, "Error fetching get namespace function") + return pkgerrors.Wrap(err, "Loading Namespace Plugin") } - ns, _ := symGetNamespaceFunc.(func(string, string, kubernetes.Interface) (string, error))( - namespace, namespace, k.clientSet) + ns, err := pluginImpl.Get(helm.KubernetesResource{ + Name: namespace, + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Namespace", + }, + }, namespace, k) if ns == "" { log.Println("Creating " + namespace + " namespace") - symGetNamespaceFunc, err := namespacePlugin.Lookup("Create") - if err != nil { - return pkgerrors.Wrap(err, "Error fetching create namespace plugin") - } - namespaceResource := &utils.ResourceData{ - Namespace: namespace, - } - _, err = symGetNamespaceFunc.(func(*utils.ResourceData, kubernetes.Interface) (string, error))( - namespaceResource, k.clientSet) + _, err = pluginImpl.Create("", namespace, k) if err != nil { return pkgerrors.Wrap(err, "Error creating "+namespace+" namespace") } @@ -127,50 +119,6 @@ func (k *KubernetesClient) ensureNamespace(namespace string) error { return nil } -func (k *KubernetesClient) createGeneric(resTempl helm.KubernetesResourceTemplate, - namespace string) (helm.KubernetesResource, error) { - - log.Println("Processing Kind: " + resTempl.GVK.Kind) - - //Check if have the mapper before loading the plugin - err := k.updateMapper() - if err != nil { - return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Unable to create RESTMapper") - } - - pluginObject, ok := utils.LoadedPlugins["generic"] - if !ok { - return helm.KubernetesResource{}, pkgerrors.New("No generic plugin found") - } - - symbol, err := pluginObject.Lookup("ExportedVariable") - if err != nil { - return helm.KubernetesResource{}, pkgerrors.Wrap(err, "No ExportedVariable symbol found") - } - - //Assert if it implements the PluginReference interface - genericPlugin, ok := symbol.(PluginReference) - if !ok { - return helm.KubernetesResource{}, pkgerrors.New("ExportedVariable is not PluginReference type") - } - - if _, err := os.Stat(resTempl.FilePath); os.IsNotExist(err) { - return helm.KubernetesResource{}, pkgerrors.New("File " + resTempl.FilePath + "does not exists") - } - - log.Println("Processing file: " + resTempl.FilePath) - - name, err := genericPlugin.Create(resTempl.FilePath, namespace, k) - if err != nil { - return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error in generic plugin") - } - - return helm.KubernetesResource{ - GVK: resTempl.GVK, - Name: name, - }, nil -} - func (k *KubernetesClient) createKind(resTempl helm.KubernetesResourceTemplate, namespace string) (helm.KubernetesResource, error) { @@ -182,28 +130,16 @@ func (k *KubernetesClient) createKind(resTempl helm.KubernetesResourceTemplate, log.Println("Processing file: " + resTempl.FilePath) - //Populate the namespace from profile instead of instance body - genericKubeData := &utils.ResourceData{ - YamlFilePath: resTempl.FilePath, - Namespace: namespace, - } - - typePlugin, ok := utils.LoadedPlugins[strings.ToLower(resTempl.GVK.Kind)] - if !ok { - log.Println("No plugin for kind " + resTempl.GVK.Kind + " found. Using generic Plugin") - return k.createGeneric(resTempl, namespace) - } - - symCreateResourceFunc, err := typePlugin.Lookup("Create") + pluginImpl, err := plugin.GetPluginByKind(resTempl.GVK.Kind) if err != nil { - return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error fetching "+resTempl.GVK.Kind+" plugin") + return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error loading plugin") } - createdResourceName, err := symCreateResourceFunc.(func(*utils.ResourceData, kubernetes.Interface) (string, error))( - genericKubeData, k.clientSet) + createdResourceName, err := pluginImpl.Create(resTempl.FilePath, namespace, k) if err != nil { return helm.KubernetesResource{}, pkgerrors.Wrap(err, "Error in plugin "+resTempl.GVK.Kind+" plugin") } + log.Print(createdResourceName + " created") return helm.KubernetesResource{ GVK: resTempl.GVK, @@ -231,58 +167,18 @@ func (k *KubernetesClient) createResources(sortedTemplates []helm.KubernetesReso return createdResources, nil } -func (k *KubernetesClient) deleteGeneric(resource helm.KubernetesResource, namespace string) error { - log.Println("Deleting Kind: " + resource.GVK.Kind) - - pluginObject, ok := utils.LoadedPlugins["generic"] - if !ok { - return pkgerrors.New("No generic plugin found") - } - - //Check if have the mapper before loading the plugin - err := k.updateMapper() - if err != nil { - return pkgerrors.Wrap(err, "Unable to create RESTMapper") - } - - symbol, err := pluginObject.Lookup("ExportedVariable") - if err != nil { - return pkgerrors.Wrap(err, "No ExportedVariable symbol found") - } - - //Assert that it implements the PluginReference interface - genericPlugin, ok := symbol.(PluginReference) - if !ok { - return pkgerrors.New("ExportedVariable is not PluginReference type") - } - - err = genericPlugin.Delete(resource, namespace, k) - if err != nil { - return pkgerrors.Wrap(err, "Error in generic plugin") - } - - return nil -} - func (k *KubernetesClient) deleteKind(resource helm.KubernetesResource, namespace string) error { log.Println("Deleting Kind: " + resource.GVK.Kind) - typePlugin, ok := utils.LoadedPlugins[strings.ToLower(resource.GVK.Kind)] - if !ok { - log.Println("No plugin for kind " + resource.GVK.Kind + " found. Using generic Plugin") - return k.deleteGeneric(resource, namespace) - } - - symDeleteResourceFunc, err := typePlugin.Lookup("Delete") + pluginImpl, err := plugin.GetPluginByKind(resource.GVK.Kind) if err != nil { - return pkgerrors.Wrap(err, "Error finding Delete symbol in plugin") + return pkgerrors.Wrap(err, "Error loading plugin") } log.Println("Deleting resource: " + resource.Name) - err = symDeleteResourceFunc.(func(string, string, kubernetes.Interface) error)( - resource.Name, namespace, k.clientSet) + err = pluginImpl.Delete(resource, namespace, k) if err != nil { - return pkgerrors.Wrap(err, "Error destroying "+resource.Name) + return pkgerrors.Wrap(err, "Error deleting "+resource.Name) } return nil @@ -300,21 +196,6 @@ func (k *KubernetesClient) deleteResources(resources []helm.KubernetesResource, return nil } -func (k *KubernetesClient) updateMapper() error { - //Create restMapper if not already done - if k.restMapper != nil { - return nil - } - - groupResources, err := restmapper.GetAPIGroupResources(k.discoverClient) - if err != nil { - return pkgerrors.Wrap(err, "Get GroupResources") - } - - k.restMapper = restmapper.NewDiscoveryRESTMapper(groupResources) - return nil -} - //GetMapper returns the RESTMapper that was created for this client func (k *KubernetesClient) GetMapper() meta.RESTMapper { return k.restMapper @@ -325,3 +206,9 @@ func (k *KubernetesClient) GetMapper() meta.RESTMapper { func (k *KubernetesClient) GetDynamicClient() dynamic.Interface { return k.dynamicClient } + +// GetStandardClient returns the standard client that can be used to handle +// standard kubernetes kinds +func (k *KubernetesClient) GetStandardClient() kubernetes.Interface { + return k.clientSet +} |