aboutsummaryrefslogtreecommitdiffstats
path: root/src/k8splugin/plugins/service
diff options
context:
space:
mode:
authorKiran Kamineni <kiran.k.kamineni@intel.com>2019-05-30 14:43:06 -0700
committerKiran Kamineni <kiran.k.kamineni@intel.com>2019-06-06 17:32:41 -0700
commitd780f1b30c98a27d269e3e05423e9e54e0e022f6 (patch)
tree3d01a1fab1a846206ae714f94838de2f0a659e13 /src/k8splugin/plugins/service
parentf006c55c0793a0cacac5aa45ba7f13fd5c6ef5f4 (diff)
Plugin code refactoring
The plugin code has been refactored to implement a common interface. This will allow us to do plugin validation at loadtime of the plugin instead of at runtime. This also makes the code calling the plugins cleaner and easier to read. Issue-ID: MULTICLOUD-557 Change-Id: Ice2bcc9b850d7c0e1707dcc42132c63dd77472a7 Signed-off-by: Kiran Kamineni <kiran.k.kamineni@intel.com>
Diffstat (limited to 'src/k8splugin/plugins/service')
-rw-r--r--src/k8splugin/plugins/service/plugin.go58
-rw-r--r--src/k8splugin/plugins/service/plugin_test.go141
2 files changed, 120 insertions, 79 deletions
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)