diff options
Diffstat (limited to 'src/k8splugin/plugins')
-rw-r--r-- | src/k8splugin/plugins/generic/plugin.go | 68 | ||||
-rw-r--r-- | src/k8splugin/plugins/namespace/plugin.go | 60 | ||||
-rw-r--r-- | src/k8splugin/plugins/namespace/plugin_test.go | 106 | ||||
-rw-r--r-- | src/k8splugin/plugins/network/plugin.go | 39 | ||||
-rw-r--r-- | src/k8splugin/plugins/network/plugin_test.go | 33 | ||||
-rw-r--r-- | src/k8splugin/plugins/service/plugin.go | 58 | ||||
-rw-r--r-- | src/k8splugin/plugins/service/plugin_test.go | 141 |
7 files changed, 321 insertions, 184 deletions
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) |