aboutsummaryrefslogtreecommitdiffstats
path: root/src/k8splugin/internal/app
diff options
context:
space:
mode:
authorKiran Kamineni <kiran.k.kamineni@intel.com>2019-04-08 16:36:34 -0700
committerKiran Kamineni <kiran.k.kamineni@intel.com>2019-04-10 11:54:00 -0700
commitf940c42e563e67279cc28c7c129a340dc800fd30 (patch)
tree2fe49c08264378907a3c2a5da5b9af070fb04ac2 /src/k8splugin/internal/app
parent9d71e9114baba71266cded1f4f805cd46a378137 (diff)
Add support for generic plugin
Add support for generic kinds We are currently using a known map to find the group version resource for a kind. Issue-ID: MULTICLOUD-350 Change-Id: I5a64f73760b73cf92b9a3fab8c22ad54e0a5f84f Signed-off-by: Kiran Kamineni <kiran.k.kamineni@intel.com>
Diffstat (limited to 'src/k8splugin/internal/app')
-rw-r--r--src/k8splugin/internal/app/client.go132
1 files changed, 128 insertions, 4 deletions
diff --git a/src/k8splugin/internal/app/client.go b/src/k8splugin/internal/app/client.go
index cb6f0eca..cd1ec8a2 100644
--- a/src/k8splugin/internal/app/client.go
+++ b/src/k8splugin/internal/app/client.go
@@ -21,13 +21,26 @@ import (
utils "k8splugin/internal"
pkgerrors "github.com/pkg/errors"
+ "k8s.io/apimachinery/pkg/api/meta"
+ "k8s.io/client-go/discovery"
+ "k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/helm/pkg/tiller"
)
+// KubernetesResource is the interface that is implemented
+type KubernetesResource interface {
+ Create(yamlFilePath string, namespace string, client *KubernetesClient) (string, error)
+ Delete(kind string, name string, namespace string, client *KubernetesClient) error
+}
+
type KubernetesClient struct {
- clientSet *kubernetes.Clientset
+ clientSet *kubernetes.Clientset
+ dynamicClient dynamic.Interface
+ discoverClient *discovery.DiscoveryClient
+ restMapper meta.RESTMapper
}
// GetKubeClient loads the Kubernetes configuation values stored into the local configuration file
@@ -46,6 +59,16 @@ func (k *KubernetesClient) init(configPath string) error {
return err
}
+ k.dynamicClient, err = dynamic.NewForConfig(config)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Creating dynamic client")
+ }
+
+ k.discoverClient, err = discovery.NewDiscoveryClientForConfig(config)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Creating discovery client")
+ }
+
return nil
}
@@ -82,6 +105,50 @@ func (k *KubernetesClient) ensureNamespace(namespace string) error {
return nil
}
+func (k *KubernetesClient) createGeneric(kind string, files []string, namespace string) ([]string, error) {
+
+ log.Println("Processing items of Kind: " + kind)
+
+ //Check if have the mapper before loading the plugin
+ err := k.updateMapper()
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "Unable to create RESTMapper")
+ }
+
+ pluginObject, ok := utils.LoadedPlugins["generic"]
+ if !ok {
+ return nil, pkgerrors.New("No generic plugin found")
+ }
+
+ symbol, err := pluginObject.Lookup("ExportedVariable")
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "No ExportedVariable symbol found")
+ }
+
+ genericPlugin, ok := symbol.(KubernetesResource)
+ if !ok {
+ return nil, pkgerrors.New("ExportedVariable is not KubernetesResource type")
+ }
+
+ //Iterate over each file of a particular kind here
+ var resourcesCreated []string
+ for _, f := range files {
+ if _, err := os.Stat(f); os.IsNotExist(err) {
+ return nil, pkgerrors.New("File " + f + "does not exists")
+ }
+
+ log.Println("Processing file: " + f)
+
+ name, err := genericPlugin.Create(f, namespace, k)
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "Error in generic plugin")
+ }
+
+ resourcesCreated = append(resourcesCreated, name)
+ }
+ return resourcesCreated, nil
+}
+
func (k *KubernetesClient) createKind(kind string, files []string, namespace string) ([]string, error) {
log.Println("Processing items of Kind: " + kind)
@@ -103,7 +170,8 @@ func (k *KubernetesClient) createKind(kind string, files []string, namespace str
typePlugin, ok := utils.LoadedPlugins[strings.ToLower(kind)]
if !ok {
- return nil, pkgerrors.New("No plugin for kind " + kind + " found")
+ log.Println("No plugin for kind " + kind + " found. Using generic Plugin")
+ return k.createGeneric(kind, files, namespace)
}
symCreateResourceFunc, err := typePlugin.Lookup("Create")
@@ -163,17 +231,47 @@ func (k *KubernetesClient) createResources(resMap map[string][]string,
return createdResourceMap, nil
}
+func (k *KubernetesClient) deleteGeneric(kind string, resources []string, namespace string) error {
+ log.Println("Deleting items of Kind: " + kind)
+
+ pluginObject, ok := utils.LoadedPlugins["generic"]
+ if !ok {
+ return pkgerrors.New("No generic plugin found")
+ }
+
+ symbol, err := pluginObject.Lookup("ExportedVariable")
+ if err != nil {
+ return pkgerrors.Wrap(err, "No ExportedVariable symbol found")
+ }
+
+ //Assert that it implements the KubernetesResource
+ genericPlugin, ok := symbol.(KubernetesResource)
+ if !ok {
+ return pkgerrors.New("ExportedVariable is not KubernetesResource type")
+ }
+
+ for _, res := range resources {
+ err = genericPlugin.Delete(kind, res, namespace, k)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error in generic plugin")
+ }
+ }
+
+ return nil
+}
+
func (k *KubernetesClient) deleteKind(kind string, resources []string, namespace string) error {
log.Println("Deleting items of Kind: " + kind)
typePlugin, ok := utils.LoadedPlugins[strings.ToLower(kind)]
if !ok {
- return pkgerrors.New("No plugin for resource " + kind + " found")
+ log.Println("No plugin for kind " + kind + " found. Using generic Plugin")
+ return k.deleteGeneric(kind, resources, namespace)
}
symDeleteResourceFunc, err := typePlugin.Lookup("Delete")
if err != nil {
- return pkgerrors.Wrap(err, "Error fetching "+kind+" plugin")
+ return pkgerrors.Wrap(err, "Error findinf Delete symbol in plugin")
}
for _, res := range resources {
@@ -198,3 +296,29 @@ func (k *KubernetesClient) deleteResources(resMap map[string][]string, namespace
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
+}
+
+//GetDynamicClient returns the dynamic client that is needed for
+//unstructured REST calls to the apiserver
+func (k *KubernetesClient) GetDynamicClient() dynamic.Interface {
+ return k.dynamicClient
+}