aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBin Yang <bin.yang@windriver.com>2019-06-19 22:46:37 +0000
committerGerrit Code Review <gerrit@onap.org>2019-06-19 22:46:37 +0000
commit36bd529eefdf43e552f420ab0a1d52fd560b837f (patch)
tree9cc2974f1c6dc91c0e54300a96963aa11bce1780 /src
parentc1963d4331fce447d93131d731e1f261c175de87 (diff)
parentd780f1b30c98a27d269e3e05423e9e54e0e022f6 (diff)
Merge "Plugin code refactoring"
Diffstat (limited to 'src')
-rw-r--r--src/k8splugin/go.sum2
-rw-r--r--src/k8splugin/internal/app/client.go181
-rw-r--r--src/k8splugin/internal/app/client_test.go2
-rw-r--r--src/k8splugin/internal/plugin/helpers.go92
-rw-r--r--src/k8splugin/mock_files/mock_plugins/mockplugin.go31
-rw-r--r--src/k8splugin/plugins/generic/plugin.go68
-rw-r--r--src/k8splugin/plugins/namespace/plugin.go60
-rw-r--r--src/k8splugin/plugins/namespace/plugin_test.go106
-rw-r--r--src/k8splugin/plugins/network/plugin.go39
-rw-r--r--src/k8splugin/plugins/network/plugin_test.go33
-rw-r--r--src/k8splugin/plugins/service/plugin.go58
-rw-r--r--src/k8splugin/plugins/service/plugin_test.go141
12 files changed, 472 insertions, 341 deletions
diff --git a/src/k8splugin/go.sum b/src/k8splugin/go.sum
index cf605d2f..0047e332 100644
--- a/src/k8splugin/go.sum
+++ b/src/k8splugin/go.sum
@@ -129,6 +129,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
@@ -147,6 +148,7 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245 h1:DNVk+NIkGS0RbLkjQOLCJb/759yfCysThkMbl7EXxyY=
github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245/go.mod h1:O1c8HleITsZqzNZDjSNzirUGsMT0oGu9LhHKoJrqO+A=
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
+}
diff --git a/src/k8splugin/internal/app/client_test.go b/src/k8splugin/internal/app/client_test.go
index 4bfbcb18..e52aa7f8 100644
--- a/src/k8splugin/internal/app/client_test.go
+++ b/src/k8splugin/internal/app/client_test.go
@@ -42,7 +42,7 @@ func LoadMockPlugins(krdLoadedPlugins map[string]*plugin.Plugin) error {
}
krdLoadedPlugins["namespace"] = mockPlugin
- krdLoadedPlugins["deployment"] = mockPlugin
+ krdLoadedPlugins["generic"] = mockPlugin
krdLoadedPlugins["service"] = mockPlugin
return nil
diff --git a/src/k8splugin/internal/plugin/helpers.go b/src/k8splugin/internal/plugin/helpers.go
new file mode 100644
index 00000000..efcd18c1
--- /dev/null
+++ b/src/k8splugin/internal/plugin/helpers.go
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2019 Intel Corporation, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package plugin
+
+import (
+ "log"
+ "strings"
+
+ utils "k8splugin/internal"
+ "k8splugin/internal/helm"
+
+ pkgerrors "github.com/pkg/errors"
+ "k8s.io/apimachinery/pkg/api/meta"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/kubernetes"
+)
+
+// KubernetesConnector is an interface that is expected to be implemented
+// by any code that calls the plugin framework functions.
+// It implements methods that are needed by the plugins to get Kubernetes
+// clients and other information needed to interface with Kubernetes
+type KubernetesConnector interface {
+ //GetMapper returns the RESTMapper that was created for this client
+ GetMapper() meta.RESTMapper
+
+ //GetDynamicClient returns the dynamic client that is needed for
+ //unstructured REST calls to the apiserver
+ GetDynamicClient() dynamic.Interface
+
+ // GetStandardClient returns the standard client that can be used to handle
+ // standard kubernetes kinds
+ GetStandardClient() kubernetes.Interface
+}
+
+// Reference is the interface that is implemented
+type Reference interface {
+ //Create a kubernetes resource described by the yaml in yamlFilePath
+ Create(yamlFilePath string, namespace string, client KubernetesConnector) (string, error)
+
+ //Get a kubernetes resource based on the groupVersionKind and resourceName provided in resource
+ Get(resource helm.KubernetesResource, namespace string, client KubernetesConnector) (string, error)
+
+ //List all resources of the specified GroupVersionKind in the given namespace
+ //If gvk is empty, the plugin will return all supported objects in the namespace
+ List(gvk schema.GroupVersionKind, namespace string, client KubernetesConnector) ([]helm.KubernetesResource, error)
+
+ //Delete a kubernetes resource described in the provided namespace
+ Delete(resource helm.KubernetesResource, namespace string, client KubernetesConnector) error
+}
+
+// GetPluginByKind returns a plugin by the kind name
+// If plugin does not exist, it will return the generic plugin
+// TODO: Change this once we have a plugin registration mechanism
+func GetPluginByKind(kind string) (Reference, error) {
+
+ typePlugin, ok := utils.LoadedPlugins[strings.ToLower(kind)]
+ if !ok {
+ log.Println("No plugin for kind " + kind + " found. Using generic Plugin")
+ typePlugin, ok = utils.LoadedPlugins["generic"]
+ if !ok {
+ return nil, pkgerrors.New("No generic plugin found")
+ }
+ }
+
+ symbol, err := typePlugin.Lookup("ExportedVariable")
+ if err != nil {
+ return nil, pkgerrors.Wrap(err, "No ExportedVariable symbol found")
+ }
+
+ //Assert if it implements the PluginReference interface
+ pluginImpl, ok := symbol.(Reference)
+ if !ok {
+ return nil, pkgerrors.New("ExportedVariable does not implement plugins.Reference interface type")
+ }
+
+ return pluginImpl, nil
+}
diff --git a/src/k8splugin/mock_files/mock_plugins/mockplugin.go b/src/k8splugin/mock_files/mock_plugins/mockplugin.go
index bdc2130c..0c3d246d 100644
--- a/src/k8splugin/mock_files/mock_plugins/mockplugin.go
+++ b/src/k8splugin/mock_files/mock_plugins/mockplugin.go
@@ -14,30 +14,43 @@ limitations under the License.
package main
import (
- "k8s.io/client-go/kubernetes"
+ "k8splugin/internal/helm"
+ "k8splugin/internal/plugin"
- utils "k8splugin/internal"
+ "k8s.io/apimachinery/pkg/runtime/schema"
)
-func main() {}
+// ExportedVariable is what we will look for when calling the plugin
+var ExportedVariable mockPlugin
+
+type mockPlugin struct {
+}
// Create object in a specific Kubernetes resource
-func Create(data *utils.ResourceData, client kubernetes.Interface) (string, error) {
+func (p mockPlugin) Create(yamlFilePath string, namespace string, client plugin.KubernetesConnector) (string, error) {
return "resource-name", nil
}
// List of existing resources
-func List(namespace string, client kubernetes.Interface) ([]string, error) {
- returnVal := []string{"resource-name-1", "resource-name-2"}
+func (p mockPlugin) List(gvk schema.GroupVersionKind, namespace string,
+ client plugin.KubernetesConnector) ([]helm.KubernetesResource, error) {
+ returnVal := []helm.KubernetesResource{
+ {
+ Name: "resource-name-1",
+ },
+ {
+ Name: "resource-name-2",
+ },
+ }
return returnVal, nil
}
// Delete existing resources
-func Delete(name string, namespace string, client kubernetes.Interface) error {
+func (p mockPlugin) Delete(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) error {
return nil
}
// Get existing resource host
-func Get(name string, namespace string, client kubernetes.Interface) (string, error) {
- return name, nil
+func (p mockPlugin) Get(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) (string, error) {
+ return resource.Name, nil
}
diff --git a/src/k8splugin/plugins/generic/plugin.go b/src/k8splugin/plugins/generic/plugin.go
index 9ecaf68c..31c65d05 100644
--- a/src/k8splugin/plugins/generic/plugin.go
+++ b/src/k8splugin/plugins/generic/plugin.go
@@ -23,15 +23,18 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
utils "k8splugin/internal"
- "k8splugin/internal/app"
+ "k8splugin/internal/plugin"
"k8splugin/internal/helm"
)
+// ExportedVariable is what we will look for when calling the generic plugin
+var ExportedVariable genericPlugin
+
type genericPlugin struct {
}
// Create deployment object in a specific Kubernetes cluster
-func (g genericPlugin) Create(yamlFilePath string, namespace string, client *app.KubernetesClient) (string, error) {
+func (g genericPlugin) Create(yamlFilePath string, namespace string, client plugin.KubernetesConnector) (string, error) {
if namespace == "" {
namespace = "default"
}
@@ -72,15 +75,58 @@ func (g genericPlugin) Create(yamlFilePath string, namespace string, client *app
return createdObj.GetName(), nil
}
-// Delete an existing deployment hosted in a specific Kubernetes cluster
-func (g genericPlugin) Delete(resource helm.KubernetesResource, namespace string, client *app.KubernetesClient) error {
+// Get an existing resource hosted in a specific Kubernetes cluster
+func (g genericPlugin) Get(resource helm.KubernetesResource,
+ namespace string, client plugin.KubernetesConnector) (string, error) {
if namespace == "" {
namespace = "default"
}
- deletePolicy := metav1.DeletePropagationForeground
- opts := &metav1.DeleteOptions{
- PropagationPolicy: &deletePolicy,
+ dynClient := client.GetDynamicClient()
+ mapper := client.GetMapper()
+
+ mapping, err := mapper.RESTMapping(schema.GroupKind{
+ Group: resource.GVK.Group,
+ Kind: resource.GVK.Kind,
+ }, resource.GVK.Version)
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Mapping kind to resource error")
+ }
+
+ gvr := mapping.Resource
+ log.Printf("Using gvr: %s, %s, %s", gvr.Group, gvr.Version, gvr.Resource)
+
+ opts := metav1.GetOptions{}
+ var unstruct *unstructured.Unstructured
+ switch mapping.Scope.Name() {
+ case meta.RESTScopeNameNamespace:
+ unstruct, err = dynClient.Resource(gvr).Namespace(namespace).Get(resource.Name, opts)
+ case meta.RESTScopeNameRoot:
+ unstruct, err = dynClient.Resource(gvr).Get(resource.Name, opts)
+ default:
+ return "", pkgerrors.New("Got an unknown RESTSCopeName for mapping: " + resource.GVK.String())
+ }
+
+ if err != nil {
+ return "", pkgerrors.Wrap(err, "Delete object error")
+ }
+
+ return unstruct.GetName(), nil
+}
+
+// List all existing resources of the GroupVersionKind
+// TODO: Implement in seperate patch
+func (g genericPlugin) List(gvk schema.GroupVersionKind, namespace string,
+ client plugin.KubernetesConnector) ([]helm.KubernetesResource, error) {
+
+ var returnData []helm.KubernetesResource
+ return returnData, nil
+}
+
+// Delete an existing resource hosted in a specific Kubernetes cluster
+func (g genericPlugin) Delete(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) error {
+ if namespace == "" {
+ namespace = "default"
}
dynClient := client.GetDynamicClient()
@@ -97,6 +143,11 @@ func (g genericPlugin) Delete(resource helm.KubernetesResource, namespace string
gvr := mapping.Resource
log.Printf("Using gvr: %s, %s, %s", gvr.Group, gvr.Version, gvr.Resource)
+ deletePolicy := metav1.DeletePropagationForeground
+ opts := &metav1.DeleteOptions{
+ PropagationPolicy: &deletePolicy,
+ }
+
switch mapping.Scope.Name() {
case meta.RESTScopeNameNamespace:
err = dynClient.Resource(gvr).Namespace(namespace).Delete(resource.Name, opts)
@@ -111,6 +162,3 @@ func (g genericPlugin) Delete(resource helm.KubernetesResource, namespace string
}
return nil
}
-
-// ExportedVariable is what we will look for when calling the generic plugin
-var ExportedVariable genericPlugin
diff --git a/src/k8splugin/plugins/namespace/plugin.go b/src/k8splugin/plugins/namespace/plugin.go
index 6f823918..2d5d2ab8 100644
--- a/src/k8splugin/plugins/namespace/plugin.go
+++ b/src/k8splugin/plugins/namespace/plugin.go
@@ -16,39 +16,42 @@ package main
import (
"log"
- "k8s.io/client-go/kubernetes"
-
pkgerrors "github.com/pkg/errors"
-
coreV1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
utils "k8splugin/internal"
+ "k8splugin/internal/helm"
+ "k8splugin/internal/plugin"
)
+// ExportedVariable is what we will look for when calling the plugin
+var ExportedVariable namespacePlugin
+
+type namespacePlugin struct {
+}
+
// Create a namespace object in a specific Kubernetes cluster
-func Create(data *utils.ResourceData, client kubernetes.Interface) (string, error) {
- namespace := &coreV1.Namespace{
+func (p namespacePlugin) Create(yamlFilePath string, namespace string, client plugin.KubernetesConnector) (string, error) {
+ namespaceObj := &coreV1.Namespace{
ObjectMeta: metaV1.ObjectMeta{
- Name: data.Namespace,
+ Name: namespace,
},
}
- _, err := client.CoreV1().Namespaces().Create(namespace)
+ _, err := client.GetStandardClient().CoreV1().Namespaces().Create(namespaceObj)
if err != nil {
return "", pkgerrors.Wrap(err, "Create Namespace error")
}
- log.Printf("Namespace (%s) created", data.Namespace)
+ log.Printf("Namespace (%s) created", namespace)
- return data.Namespace, nil
+ return namespace, nil
}
// Get an existing namespace hosted in a specific Kubernetes cluster
-func Get(name string, namespace string, client kubernetes.Interface) (string, error) {
+func (p namespacePlugin) Get(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) (string, error) {
opts := metaV1.GetOptions{}
- opts.APIVersion = "apps/v1"
- opts.Kind = "Deployment"
-
- ns, err := client.CoreV1().Namespaces().Get(name, opts)
+ ns, err := client.GetStandardClient().CoreV1().Namespaces().Get(resource.Name, opts)
if err != nil {
return "", pkgerrors.Wrap(err, "Get Namespace error")
}
@@ -57,14 +60,14 @@ func Get(name string, namespace string, client kubernetes.Interface) (string, er
}
// Delete an existing namespace hosted in a specific Kubernetes cluster
-func Delete(name string, namespace string, client kubernetes.Interface) error {
+func (p namespacePlugin) Delete(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) error {
deletePolicy := metaV1.DeletePropagationForeground
opts := &metaV1.DeleteOptions{
PropagationPolicy: &deletePolicy,
}
- log.Println("Deleting namespace: " + name)
- if err := client.CoreV1().Namespaces().Delete(name, opts); err != nil {
+ log.Println("Deleting namespace: " + resource.Name)
+ if err := client.GetStandardClient().CoreV1().Namespaces().Delete(resource.Name, opts); err != nil {
return pkgerrors.Wrap(err, "Delete namespace error")
}
@@ -72,23 +75,30 @@ func Delete(name string, namespace string, client kubernetes.Interface) error {
}
// List of existing namespaces hosted in a specific Kubernetes cluster
-func List(namespace string, client kubernetes.Interface) ([]string, error) {
+// This plugin ignores both gvk and namespace arguments
+func (p namespacePlugin) List(gvk schema.GroupVersionKind, namespace string, client plugin.KubernetesConnector) ([]helm.KubernetesResource, error) {
opts := metaV1.ListOptions{
Limit: utils.ResourcesListLimit,
}
- opts.APIVersion = "apps/v1"
- opts.Kind = "Namespace"
- list, err := client.CoreV1().Namespaces().List(opts)
+ list, err := client.GetStandardClient().CoreV1().Namespaces().List(opts)
if err != nil {
return nil, pkgerrors.Wrap(err, "Get Namespace list error")
}
- result := make([]string, 0, utils.ResourcesListLimit)
+ result := make([]helm.KubernetesResource, 0, utils.ResourcesListLimit)
if list != nil {
- for _, deployment := range list.Items {
- log.Printf("%v", deployment.Name)
- result = append(result, deployment.Name)
+ for _, ns := range list.Items {
+ log.Printf("%v", ns.Name)
+ result = append(result,
+ helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{
+ Group: "",
+ Version: "v1",
+ Kind: "Namespace",
+ },
+ Name: ns.Name,
+ })
}
}
diff --git a/src/k8splugin/plugins/namespace/plugin_test.go b/src/k8splugin/plugins/namespace/plugin_test.go
index 0019df1c..9e57b971 100644
--- a/src/k8splugin/plugins/namespace/plugin_test.go
+++ b/src/k8splugin/plugins/namespace/plugin_test.go
@@ -18,36 +18,54 @@ import (
"strings"
"testing"
- utils "k8splugin/internal"
+ "k8splugin/internal/helm"
coreV1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/meta"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- testclient "k8s.io/client-go/kubernetes/fake"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/kubernetes/fake"
)
+type TestKubernetesConnector struct {
+ object runtime.Object
+}
+
+func (t TestKubernetesConnector) GetMapper() meta.RESTMapper {
+ return nil
+}
+
+func (t TestKubernetesConnector) GetDynamicClient() dynamic.Interface {
+ return nil
+}
+
+func (t TestKubernetesConnector) GetStandardClient() kubernetes.Interface {
+ return fake.NewSimpleClientset(t.object)
+}
+
func TestCreateNamespace(t *testing.T) {
- namespace := "test1"
testCases := []struct {
label string
- input *utils.ResourceData
- clientOutput *coreV1.Namespace
+ input string
+ object *coreV1.Namespace
expectedResult string
expectedError string
}{
{
- label: "Successfully create a namespace",
- input: &utils.ResourceData{
- Namespace: namespace,
- },
- clientOutput: &coreV1.Namespace{},
- expectedResult: namespace,
+ label: "Successfully create a namespace",
+ input: "test1",
+ object: &coreV1.Namespace{},
+ expectedResult: "test1",
},
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := Create(testCase.input, client)
+ result, err := namespacePlugin{}.Create("", testCase.input, client)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create method return an un-expected (%s)", err)
@@ -72,39 +90,47 @@ func TestCreateNamespace(t *testing.T) {
}
func TestListNamespace(t *testing.T) {
- namespace := "test1"
testCases := []struct {
label string
input string
- clientOutput *coreV1.NamespaceList
- expectedResult []string
+ object *coreV1.NamespaceList
+ expectedResult []helm.KubernetesResource
}{
{
label: "Sucessfully to display an empty namespace list",
- input: namespace,
- clientOutput: &coreV1.NamespaceList{},
- expectedResult: []string{},
+ input: "",
+ object: &coreV1.NamespaceList{},
+ expectedResult: []helm.KubernetesResource{},
},
{
label: "Sucessfully to display a list of existing namespaces",
- input: namespace,
- clientOutput: &coreV1.NamespaceList{
+ input: "test1",
+ object: &coreV1.NamespaceList{
Items: []coreV1.Namespace{
coreV1.Namespace{
ObjectMeta: metaV1.ObjectMeta{
- Name: namespace,
+ Name: "test1",
},
},
},
},
- expectedResult: []string{namespace},
+ expectedResult: []helm.KubernetesResource{
+ {
+ Name: "test1",
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"},
+ },
+ },
},
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := List(testCase.input, client)
+ result, err := namespacePlugin{}.List(schema.GroupVersionKind{
+ Group: "",
+ Version: "v1",
+ Kind: "Namespace",
+ }, testCase.input, client)
if err != nil {
t.Fatalf("List method returned an error (%s)", err)
} else {
@@ -113,7 +139,7 @@ func TestListNamespace(t *testing.T) {
}
if !reflect.DeepEqual(testCase.expectedResult, result) {
- t.Fatalf("List method returned: \n%v\n and it was expected: \n%v", result, testCase.expectedResult)
+ t.Fatalf("List method returned: \n%+v\n and it was expected: \n%+v", result, testCase.expectedResult)
}
}
})
@@ -122,14 +148,14 @@ func TestListNamespace(t *testing.T) {
func TestDeleteNamespace(t *testing.T) {
testCases := []struct {
- label string
- input map[string]string
- clientOutput *coreV1.Namespace
+ label string
+ input map[string]string
+ object *coreV1.Namespace
}{
{
label: "Sucessfully to delete an existing namespace",
input: map[string]string{"name": "test-name", "namespace": "test-namespace"},
- clientOutput: &coreV1.Namespace{
+ object: &coreV1.Namespace{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-name",
},
@@ -138,9 +164,12 @@ func TestDeleteNamespace(t *testing.T) {
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- err := Delete(testCase.input["name"], testCase.input["namespace"], client)
+ err := namespacePlugin{}.Delete(helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"},
+ Name: testCase.input["name"],
+ }, testCase.input["namespace"], client)
if err != nil {
t.Fatalf("Delete method returned an error (%s)", err)
}
@@ -152,14 +181,14 @@ func TestGetNamespace(t *testing.T) {
testCases := []struct {
label string
input map[string]string
- clientOutput *coreV1.Namespace
+ object *coreV1.Namespace
expectedResult string
expectedError string
}{
{
label: "Sucessfully to get an existing namespace",
input: map[string]string{"name": "test-name", "namespace": "test-namespace"},
- clientOutput: &coreV1.Namespace{
+ object: &coreV1.Namespace{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-name",
},
@@ -169,7 +198,7 @@ func TestGetNamespace(t *testing.T) {
{
label: "Fail to get an non-existing namespace",
input: map[string]string{"name": "test-name", "namespace": "test-namespace"},
- clientOutput: &coreV1.Namespace{
+ object: &coreV1.Namespace{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-name2",
},
@@ -179,9 +208,12 @@ func TestGetNamespace(t *testing.T) {
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := Get(testCase.input["name"], testCase.input["namespace"], client)
+ result, err := namespacePlugin{}.Get(helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"},
+ Name: testCase.input["name"],
+ }, testCase.input["namespace"], client)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Get method return an un-expected (%s)", err)
diff --git a/src/k8splugin/plugins/network/plugin.go b/src/k8splugin/plugins/network/plugin.go
index 74ac3473..5cc57e87 100644
--- a/src/k8splugin/plugins/network/plugin.go
+++ b/src/k8splugin/plugins/network/plugin.go
@@ -14,31 +14,38 @@ limitations under the License.
package main
import (
- "k8splugin/plugins/network/v1"
+ v1 "k8splugin/plugins/network/v1"
"regexp"
utils "k8splugin/internal"
+ "k8splugin/internal/app"
+ "k8splugin/internal/helm"
pkgerrors "github.com/pkg/errors"
- "k8s.io/client-go/kubernetes"
+ "k8s.io/apimachinery/pkg/runtime/schema"
)
-func extractData(data string) (vnfID, cniType, networkName string) {
+// ExportedVariable is what we will look for when calling the plugin
+var ExportedVariable networkPlugin
+
+type networkPlugin struct {
+}
+
+func extractData(data string) (cniType, networkName string) {
re := regexp.MustCompile("_")
split := re.Split(data, -1)
if len(split) != 3 {
return
}
- vnfID = split[0]
cniType = split[1]
networkName = split[2]
return
}
// Create an ONAP Network object
-func Create(data *utils.ResourceData, client kubernetes.Interface) (string, error) {
+func (p networkPlugin) Create(yamlFilePath string, namespace string, client *app.KubernetesClient) (string, error) {
network := &v1.OnapNetwork{}
- if _, err := utils.DecodeYAML(data.YamlFilePath, network); err != nil {
+ if _, err := utils.DecodeYAML(yamlFilePath, network); err != nil {
return "", pkgerrors.Wrap(err, "Decode network object error")
}
@@ -58,17 +65,24 @@ func Create(data *utils.ResourceData, client kubernetes.Interface) (string, erro
return "", pkgerrors.Wrap(err, "Error during the creation for "+cniType+" plugin")
}
- return data.VnfId + "_" + cniType + "_" + name, nil
+ return cniType + "_" + name, nil
+}
+
+// Get a Network
+func (p networkPlugin) Get(resource helm.KubernetesResource, namespace string, client *app.KubernetesClient) (string, error) {
+ return "", nil
}
// List of Networks
-func List(namespace string, kubeclient kubernetes.Interface) ([]string, error) {
+func (p networkPlugin) List(gvk schema.GroupVersionKind, namespace string,
+ client *app.KubernetesClient) ([]helm.KubernetesResource, error) {
+
return nil, nil
}
// Delete an existing Network
-func Delete(name string, namespace string, kubeclient kubernetes.Interface) error {
- _, cniType, networkName := extractData(name)
+func (p networkPlugin) Delete(resource helm.KubernetesResource, namespace string, client *app.KubernetesClient) error {
+ cniType, networkName := extractData(resource.Name)
typePlugin, ok := utils.LoadedPlugins[cniType+"-network"]
if !ok {
return pkgerrors.New("No plugin for resource " + cniType + " found")
@@ -85,8 +99,3 @@ func Delete(name string, namespace string, kubeclient kubernetes.Interface) erro
return nil
}
-
-// Get an existing Network
-func Get(name string, namespace string, kubeclient kubernetes.Interface) (string, error) {
- return "", nil
-}
diff --git a/src/k8splugin/plugins/network/plugin_test.go b/src/k8splugin/plugins/network/plugin_test.go
index e8e113b2..5a8ce4db 100644
--- a/src/k8splugin/plugins/network/plugin_test.go
+++ b/src/k8splugin/plugins/network/plugin_test.go
@@ -15,6 +15,7 @@ package main
import (
utils "k8splugin/internal"
+ "k8splugin/internal/helm"
"os"
"plugin"
"reflect"
@@ -22,6 +23,7 @@ import (
"testing"
pkgerrors "github.com/pkg/errors"
+ "k8s.io/apimachinery/pkg/runtime/schema"
)
func LoadMockNetworkPlugins(krdLoadedPlugins *map[string]*plugin.Plugin, networkName, errMsg string) error {
@@ -51,7 +53,6 @@ func LoadMockNetworkPlugins(krdLoadedPlugins *map[string]*plugin.Plugin, network
}
func TestCreateNetwork(t *testing.T) {
- internalVNFID := "1"
oldkrdPluginData := utils.LoadedPlugins
defer func() {
@@ -60,34 +61,27 @@ func TestCreateNetwork(t *testing.T) {
testCases := []struct {
label string
- input *utils.ResourceData
+ input string
mockError string
mockOutput string
expectedResult string
expectedError string
}{
{
- label: "Fail to decode a network object",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/service.yaml",
- },
+ label: "Fail to decode a network object",
+ input: "../../mock_files/mock_yamls/service.yaml",
expectedError: "No plugin for resource",
},
{
- label: "Fail to create a network",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/ovn4nfvk8s.yaml",
- },
+ label: "Fail to create a network",
+ input: "../../mock_files/mock_yamls/ovn4nfvk8s.yaml",
mockError: "Internal error",
expectedError: "Error during the creation for ovn4nfvk8s plugin: Internal error",
},
{
- label: "Successfully create a ovn4nfv network",
- input: &utils.ResourceData{
- VnfId: internalVNFID,
- YamlFilePath: "../../mock_files/mock_yamls/ovn4nfvk8s.yaml",
- },
- expectedResult: internalVNFID + "_ovn4nfvk8s_myNetwork",
+ label: "Successfully create a ovn4nfv network",
+ input: "../../mock_files/mock_yamls/ovn4nfvk8s.yaml",
+ expectedResult: "ovn4nfvk8s_myNetwork",
mockOutput: "myNetwork",
},
}
@@ -98,7 +92,7 @@ func TestCreateNetwork(t *testing.T) {
if err != nil {
t.Fatalf("TestCreateNetwork returned an error (%s)", err)
}
- result, err := Create(testCase.input, nil)
+ result, err := networkPlugin{}.Create(testCase.input, "", nil)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create method return an un-expected (%s)", err)
@@ -157,7 +151,10 @@ func TestDeleteNetwork(t *testing.T) {
if err != nil {
t.Fatalf("TestDeleteNetwork returned an error (%s)", err)
}
- err = Delete(testCase.input, "", nil)
+ err = networkPlugin{}.Delete(helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{Group: "", Version: "", Kind: "Network"},
+ Name: testCase.input,
+ }, "", nil)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create method return an un-expected (%s)", err)
diff --git a/src/k8splugin/plugins/service/plugin.go b/src/k8splugin/plugins/service/plugin.go
index ea5aecad..2957c441 100644
--- a/src/k8splugin/plugins/service/plugin.go
+++ b/src/k8splugin/plugins/service/plugin.go
@@ -16,23 +16,29 @@ package main
import (
"log"
- "k8s.io/client-go/kubernetes"
-
pkgerrors "github.com/pkg/errors"
-
coreV1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime/schema"
utils "k8splugin/internal"
+ "k8splugin/internal/helm"
+ "k8splugin/internal/plugin"
)
+// ExportedVariable is what we will look for when calling the plugin
+var ExportedVariable servicePlugin
+
+type servicePlugin struct {
+}
+
// Create a service object in a specific Kubernetes cluster
-func Create(data *utils.ResourceData, client kubernetes.Interface) (string, error) {
- namespace := data.Namespace
+func (p servicePlugin) Create(yamlFilePath string, namespace string, client plugin.KubernetesConnector) (string, error) {
if namespace == "" {
namespace = "default"
}
- obj, err := utils.DecodeYAML(data.YamlFilePath, nil)
+
+ obj, err := utils.DecodeYAML(yamlFilePath, nil)
if err != nil {
return "", pkgerrors.Wrap(err, "Decode service object error")
}
@@ -43,7 +49,7 @@ func Create(data *utils.ResourceData, client kubernetes.Interface) (string, erro
}
service.Namespace = namespace
- result, err := client.CoreV1().Services(namespace).Create(service)
+ result, err := client.GetStandardClient().CoreV1().Services(namespace).Create(service)
if err != nil {
return "", pkgerrors.Wrap(err, "Create Service error")
}
@@ -52,7 +58,8 @@ func Create(data *utils.ResourceData, client kubernetes.Interface) (string, erro
}
// List of existing services hosted in a specific Kubernetes cluster
-func List(namespace string, kubeclient kubernetes.Interface) ([]string, error) {
+// gvk parameter is not used as this plugin is specific to services only
+func (p servicePlugin) List(gvk schema.GroupVersionKind, namespace string, client plugin.KubernetesConnector) ([]helm.KubernetesResource, error) {
if namespace == "" {
namespace = "default"
}
@@ -60,19 +67,25 @@ func List(namespace string, kubeclient kubernetes.Interface) ([]string, error) {
opts := metaV1.ListOptions{
Limit: utils.ResourcesListLimit,
}
- opts.APIVersion = "apps/v1"
- opts.Kind = "Service"
- list, err := kubeclient.CoreV1().Services(namespace).List(opts)
+ list, err := client.GetStandardClient().CoreV1().Services(namespace).List(opts)
if err != nil {
return nil, pkgerrors.Wrap(err, "Get Service list error")
}
- result := make([]string, 0, utils.ResourcesListLimit)
+ result := make([]helm.KubernetesResource, 0, utils.ResourcesListLimit)
if list != nil {
- for _, deployment := range list.Items {
- log.Printf("%v", deployment.Name)
- result = append(result, deployment.Name)
+ for _, service := range list.Items {
+ log.Printf("%v", service.Name)
+ result = append(result,
+ helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{
+ Group: "",
+ Version: "v1",
+ Kind: "Service",
+ },
+ Name: service.GetName(),
+ })
}
}
@@ -80,7 +93,7 @@ func List(namespace string, kubeclient kubernetes.Interface) ([]string, error) {
}
// Delete an existing service hosted in a specific Kubernetes cluster
-func Delete(name string, namespace string, kubeclient kubernetes.Interface) error {
+func (p servicePlugin) Delete(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) error {
if namespace == "" {
namespace = "default"
}
@@ -90,8 +103,8 @@ func Delete(name string, namespace string, kubeclient kubernetes.Interface) erro
PropagationPolicy: &deletePolicy,
}
- log.Println("Deleting service: " + name)
- if err := kubeclient.CoreV1().Services(namespace).Delete(name, opts); err != nil {
+ log.Println("Deleting service: " + resource.Name)
+ if err := client.GetStandardClient().CoreV1().Services(namespace).Delete(resource.Name, opts); err != nil {
return pkgerrors.Wrap(err, "Delete service error")
}
@@ -99,18 +112,15 @@ func Delete(name string, namespace string, kubeclient kubernetes.Interface) erro
}
// Get an existing service hosted in a specific Kubernetes cluster
-func Get(name string, namespace string, kubeclient kubernetes.Interface) (string, error) {
+func (p servicePlugin) Get(resource helm.KubernetesResource, namespace string, client plugin.KubernetesConnector) (string, error) {
if namespace == "" {
namespace = "default"
}
opts := metaV1.GetOptions{}
- opts.APIVersion = "apps/v1"
- opts.Kind = "Service"
-
- service, err := kubeclient.CoreV1().Services(namespace).Get(name, opts)
+ service, err := client.GetStandardClient().CoreV1().Services(namespace).Get(resource.Name, opts)
if err != nil {
- return "", pkgerrors.Wrap(err, "Get Deployment error")
+ return "", pkgerrors.Wrap(err, "Get Service error")
}
return service.Name, nil
diff --git a/src/k8splugin/plugins/service/plugin_test.go b/src/k8splugin/plugins/service/plugin_test.go
index d3614860..66703089 100644
--- a/src/k8splugin/plugins/service/plugin_test.go
+++ b/src/k8splugin/plugins/service/plugin_test.go
@@ -14,54 +14,67 @@ limitations under the License.
package main
import (
+ "k8splugin/internal/helm"
"reflect"
"strings"
"testing"
- utils "k8splugin/internal"
-
coreV1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/meta"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- testclient "k8s.io/client-go/kubernetes/fake"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/client-go/dynamic"
+ "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/kubernetes/fake"
)
+type TestKubernetesConnector struct {
+ object runtime.Object
+}
+
+func (t TestKubernetesConnector) GetMapper() meta.RESTMapper {
+ return nil
+}
+
+func (t TestKubernetesConnector) GetDynamicClient() dynamic.Interface {
+ return nil
+}
+
+func (t TestKubernetesConnector) GetStandardClient() kubernetes.Interface {
+ return fake.NewSimpleClientset(t.object)
+}
+
func TestCreateService(t *testing.T) {
- namespace := "test1"
name := "mock-service"
testCases := []struct {
label string
- input *utils.ResourceData
- clientOutput *coreV1.Service
+ input string
+ namespace string
+ object *coreV1.Service
expectedResult string
expectedError string
}{
{
- label: "Fail to create a service with invalid type",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/deployment.yaml",
- },
- clientOutput: &coreV1.Service{},
+ label: "Fail to create a service with invalid type",
+ input: "../../mock_files/mock_yamls/deployment.yaml",
+ namespace: "test1",
+ object: &coreV1.Service{},
expectedError: "contains another resource different than Service",
},
{
- label: "Successfully create a service",
- input: &utils.ResourceData{
- YamlFilePath: "../../mock_files/mock_yamls/service.yaml",
- },
- clientOutput: &coreV1.Service{
- ObjectMeta: metaV1.ObjectMeta{
- Name: name,
- Namespace: namespace,
- },
- },
+ label: "Successfully create a service",
+ input: "../../mock_files/mock_yamls/service.yaml",
+ namespace: "test1",
+ object: &coreV1.Service{},
expectedResult: name,
},
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := Create(testCase.input, client)
+ result, err := servicePlugin{}.Create(testCase.input, testCase.namespace, client)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create method return an un-expected (%s)", err)
@@ -86,38 +99,42 @@ func TestCreateService(t *testing.T) {
}
func TestListService(t *testing.T) {
- namespace := "test1"
testCases := []struct {
label string
- input string
- clientOutput *coreV1.ServiceList
- expectedResult []string
+ namespace string
+ object *coreV1.ServiceList
+ expectedResult []helm.KubernetesResource
}{
{
label: "Sucessfully to display an empty service list",
- input: namespace,
- clientOutput: &coreV1.ServiceList{},
- expectedResult: []string{},
+ namespace: "test1",
+ object: &coreV1.ServiceList{},
+ expectedResult: []helm.KubernetesResource{},
},
{
- label: "Sucessfully to display a list of existing services",
- input: namespace,
- clientOutput: &coreV1.ServiceList{
+ label: "Sucessfully to display a list of existing services",
+ namespace: "test1",
+ object: &coreV1.ServiceList{
Items: []coreV1.Service{
coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test",
- Namespace: namespace,
+ Namespace: "test1",
},
},
},
},
- expectedResult: []string{"test"},
+ expectedResult: []helm.KubernetesResource{
+ {
+ Name: "test",
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"},
+ },
+ },
},
{
- label: "Sucessfully display a list of existing services in default namespace",
- input: "",
- clientOutput: &coreV1.ServiceList{
+ label: "Sucessfully display a list of existing services in default namespace",
+ namespace: "",
+ object: &coreV1.ServiceList{
Items: []coreV1.Service{
coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
@@ -128,19 +145,27 @@ func TestListService(t *testing.T) {
coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test2",
- Namespace: namespace,
+ Namespace: "test1",
},
},
},
},
- expectedResult: []string{"test"},
+ expectedResult: []helm.KubernetesResource{
+ {
+ Name: "test",
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"},
+ },
+ },
},
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := List(testCase.input, client)
+ result, err := servicePlugin{}.List(schema.GroupVersionKind{
+ Group: "",
+ Version: "v1",
+ Kind: "Service"}, testCase.namespace, client)
if err != nil {
t.Fatalf("List method returned an error (%s)", err)
} else {
@@ -158,14 +183,14 @@ func TestListService(t *testing.T) {
func TestDeleteService(t *testing.T) {
testCases := []struct {
- label string
- input map[string]string
- clientOutput *coreV1.Service
+ label string
+ input map[string]string
+ object *coreV1.Service
}{
{
label: "Sucessfully to delete an existing service",
input: map[string]string{"name": "test-service", "namespace": "test-namespace"},
- clientOutput: &coreV1.Service{
+ object: &coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
@@ -175,7 +200,7 @@ func TestDeleteService(t *testing.T) {
{
label: "Sucessfully delete an existing service in default namespace",
input: map[string]string{"name": "test-service", "namespace": ""},
- clientOutput: &coreV1.Service{
+ object: &coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service",
Namespace: "default",
@@ -185,9 +210,12 @@ func TestDeleteService(t *testing.T) {
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- err := Delete(testCase.input["name"], testCase.input["namespace"], client)
+ err := servicePlugin{}.Delete(helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"},
+ Name: testCase.input["name"],
+ }, testCase.input["namespace"], client)
if err != nil {
t.Fatalf("Delete method returned an error (%s)", err)
}
@@ -199,14 +227,14 @@ func TestGetService(t *testing.T) {
testCases := []struct {
label string
input map[string]string
- clientOutput *coreV1.Service
+ object *coreV1.Service
expectedResult string
expectedError string
}{
{
label: "Sucessfully to get an existing service",
input: map[string]string{"name": "test-service", "namespace": "test-namespace"},
- clientOutput: &coreV1.Service{
+ object: &coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
@@ -217,7 +245,7 @@ func TestGetService(t *testing.T) {
{
label: "Sucessfully get an existing service from default namespaces",
input: map[string]string{"name": "test-service", "namespace": ""},
- clientOutput: &coreV1.Service{
+ object: &coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service",
Namespace: "default",
@@ -228,7 +256,7 @@ func TestGetService(t *testing.T) {
{
label: "Fail to get an non-existing namespace",
input: map[string]string{"name": "test-name", "namespace": "test-namespace"},
- clientOutput: &coreV1.Service{
+ object: &coreV1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service",
Namespace: "default",
@@ -239,9 +267,12 @@ func TestGetService(t *testing.T) {
}
for _, testCase := range testCases {
- client := testclient.NewSimpleClientset(testCase.clientOutput)
+ client := TestKubernetesConnector{testCase.object}
t.Run(testCase.label, func(t *testing.T) {
- result, err := Get(testCase.input["name"], testCase.input["namespace"], client)
+ result, err := servicePlugin{}.Get(helm.KubernetesResource{
+ GVK: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Service"},
+ Name: testCase.input["name"],
+ }, testCase.input["namespace"], client)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Get method return an un-expected (%s)", err)