diff options
Diffstat (limited to 'src/k8splugin')
-rw-r--r-- | src/k8splugin/api/api.go | 13 | ||||
-rw-r--r-- | src/k8splugin/api/brokerhandler_test.go | 6 | ||||
-rw-r--r-- | src/k8splugin/api/confighandler.go | 15 | ||||
-rw-r--r-- | src/k8splugin/internal/app/config.go (renamed from src/k8splugin/internal/rb/config.go) | 8 | ||||
-rw-r--r-- | src/k8splugin/internal/app/config_backend.go (renamed from src/k8splugin/internal/rb/config_backend.go) | 52 | ||||
-rw-r--r-- | src/k8splugin/internal/app/config_test.go (renamed from src/k8splugin/internal/rb/config_test.go) | 2 | ||||
-rw-r--r-- | src/k8splugin/internal/app/instance.go | 43 | ||||
-rw-r--r-- | src/k8splugin/internal/app/instance_test.go | 390 | ||||
-rw-r--r-- | src/k8splugin/mock_files/mock_yamls/ovn4nfvk8s.yaml | 16 | ||||
-rw-r--r-- | src/k8splugin/plugins/network/plugin.go | 7 | ||||
-rw-r--r-- | src/k8splugin/plugins/network/plugin_test.go | 2 | ||||
-rw-r--r-- | src/k8splugin/plugins/network/v1/types.go | 23 | ||||
-rw-r--r-- | src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go | 34 | ||||
-rw-r--r-- | src/k8splugin/plugins/ovn4nfvk8s-network/plugin_test.go | 6 |
14 files changed, 530 insertions, 87 deletions
diff --git a/src/k8splugin/api/api.go b/src/k8splugin/api/api.go index 5fed28a0..58e50a16 100644 --- a/src/k8splugin/api/api.go +++ b/src/k8splugin/api/api.go @@ -25,7 +25,7 @@ import ( func NewRouter(defClient rb.DefinitionManager, profileClient rb.ProfileManager, instClient app.InstanceManager, - configClient rb.ConfigManager, + configClient app.ConfigManager, templateClient rb.ConfigTemplateManager) *mux.Router { router := mux.NewRouter() @@ -43,12 +43,11 @@ func NewRouter(defClient rb.DefinitionManager, // instRouter.HandleFunc("/{vnfInstanceId}", UpdateHandler).Methods("PUT") //Setup the broker handler here + //Use the base router without any path prefixes brokerHandler := brokerInstanceHandler{client: instClient} - instRouter.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload", brokerHandler.createHandler).Methods("POST") - instRouter.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", - brokerHandler.getHandler).Methods("GET") - instRouter.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", - brokerHandler.deleteHandler).Methods("DELETE") + router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload", brokerHandler.createHandler).Methods("POST") + router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", brokerHandler.getHandler).Methods("GET") + router.HandleFunc("/{cloud-owner}/{cloud-region}/infra_workload/{instID}", brokerHandler.deleteHandler).Methods("DELETE") //Setup the connectivity api handler here connectionClient := connection.NewConnectionClient() @@ -91,7 +90,7 @@ func NewRouter(defClient rb.DefinitionManager, // Config value if configClient == nil { - configClient = rb.NewConfigClient() + configClient = app.NewConfigClient() } configHandler := rbConfigHandler{client: configClient} resRouter.HandleFunc("/definition/{rbname}/{rbversion}/profile/{prname}/config", configHandler.createHandler).Methods("POST") diff --git a/src/k8splugin/api/brokerhandler_test.go b/src/k8splugin/api/brokerhandler_test.go index d9991e68..16046634 100644 --- a/src/k8splugin/api/brokerhandler_test.go +++ b/src/k8splugin/api/brokerhandler_test.go @@ -122,7 +122,7 @@ func TestBrokerCreateHandler(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.label, func(t *testing.T) { - request := httptest.NewRequest("POST", "/v1/cloudowner/cloudregion/infra_workload", testCase.input) + request := httptest.NewRequest("POST", "/cloudowner/cloudregion/infra_workload", testCase.input) resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil)) if testCase.expectedCode != resp.StatusCode { @@ -204,7 +204,7 @@ func TestBrokerGetHandler(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.label, func(t *testing.T) { - request := httptest.NewRequest("GET", "/v1/cloudowner/cloudregion/infra_workload/"+testCase.input, nil) + request := httptest.NewRequest("GET", "/cloudowner/cloudregion/infra_workload/"+testCase.input, nil) resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil)) if testCase.expectedCode != resp.StatusCode { @@ -251,7 +251,7 @@ func TestBrokerDeleteHandler(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.label, func(t *testing.T) { - request := httptest.NewRequest("DELETE", "/v1/cloudowner/cloudregion/infra_workload/"+testCase.input, nil) + request := httptest.NewRequest("DELETE", "/cloudowner/cloudregion/infra_workload/"+testCase.input, nil) resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil)) if testCase.expectedCode != resp.StatusCode { diff --git a/src/k8splugin/api/confighandler.go b/src/k8splugin/api/confighandler.go index 93098d61..9bd9db83 100644 --- a/src/k8splugin/api/confighandler.go +++ b/src/k8splugin/api/confighandler.go @@ -18,9 +18,10 @@ package api import ( "encoding/json" - "k8splugin/internal/rb" "net/http" + "k8splugin/internal/app" + "github.com/gorilla/mux" ) @@ -29,12 +30,12 @@ import ( type rbConfigHandler struct { // Interface that implements bundle Definition operations // We will set this variable with a mock interface for testing - client rb.ConfigManager + client app.ConfigManager } // createHandler handles creation of the definition entry in the database func (h rbConfigHandler) createHandler(w http.ResponseWriter, r *http.Request) { - var p rb.Config + var p app.Config vars := mux.Vars(r) rbName := vars["rbname"] rbVersion := vars["rbversion"] @@ -73,7 +74,7 @@ func (h rbConfigHandler) createHandler(w http.ResponseWriter, r *http.Request) { } // getHandler handles GET operations on a particular config -// Returns a rb.Definition +// Returns a app.Definition func (h rbConfigHandler) getHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) rbName := vars["rbname"] @@ -128,7 +129,7 @@ func (h rbConfigHandler) updateHandler(w http.ResponseWriter, r *http.Request) { prName := vars["prname"] cfgName := vars["cfgname"] - var p rb.Config + var p app.Config if r.Body == nil { http.Error(w, "Empty body", http.StatusBadRequest) @@ -168,7 +169,7 @@ func (h rbConfigHandler) rollbackHandler(w http.ResponseWriter, r *http.Request) return } - var p rb.ConfigRollback + var p app.ConfigRollback err := json.NewDecoder(r.Body).Decode(&p) if err != nil { http.Error(w, err.Error(), http.StatusUnprocessableEntity) @@ -194,7 +195,7 @@ func (h rbConfigHandler) tagitHandler(w http.ResponseWriter, r *http.Request) { return } - var p rb.ConfigTagit + var p app.ConfigTagit err := json.NewDecoder(r.Body).Decode(&p) if err != nil { http.Error(w, err.Error(), http.StatusUnprocessableEntity) diff --git a/src/k8splugin/internal/rb/config.go b/src/k8splugin/internal/app/config.go index 3bd8347b..f7e81358 100644 --- a/src/k8splugin/internal/rb/config.go +++ b/src/k8splugin/internal/app/config.go @@ -14,13 +14,15 @@ * limitations under the License. */ -package rb +package app import ( - pkgerrors "github.com/pkg/errors" - "k8splugin/internal/db" "strconv" "strings" + + "k8splugin/internal/db" + + pkgerrors "github.com/pkg/errors" ) // Config contains the parameters needed for configuration diff --git a/src/k8splugin/internal/rb/config_backend.go b/src/k8splugin/internal/app/config_backend.go index e2fa5b3c..763aed0d 100644 --- a/src/k8splugin/internal/rb/config_backend.go +++ b/src/k8splugin/internal/app/config_backend.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package rb +package app import ( "bytes" @@ -25,9 +25,11 @@ import ( "strconv" "strings" "sync" + "time" "k8splugin/internal/db" "k8splugin/internal/helm" + "k8splugin/internal/rb" "github.com/ghodss/yaml" pkgerrors "github.com/pkg/errors" @@ -57,7 +59,8 @@ type ConfigVersionStore struct { type configResourceList struct { resourceTemplates []helm.KubernetesResourceTemplate - profile Profile + createdResources []helm.KubernetesResource + profile rb.Profile action string } @@ -339,17 +342,50 @@ func scheduleResources(c chan configResourceList) { for { data := <-c //TODO: ADD Check to see if Application running + ic := NewInstanceClient() + resp, err := ic.Find(data.profile.RBName, data.profile.RBVersion, data.profile.ProfileName) + if err != nil || len(resp) == 0 { + log.Println("Error finding a running instance. Retrying later...") + time.Sleep(time.Second * 10) + continue + } switch { case data.action == "POST": log.Printf("[scheduleResources]: POST %v %v", data.profile, data.resourceTemplates) + for _, inst := range resp { + k8sClient := KubernetesClient{} + err = k8sClient.init(inst.CloudRegion) + if err != nil { + log.Printf("Getting CloudRegion Information: %s", err.Error()) + //Move onto the next cloud region + continue + } + data.createdResources, err = k8sClient.createResources(data.resourceTemplates, inst.Namespace) + if err != nil { + log.Printf("Error Creating resources: %s", err.Error()) + continue + } + } //TODO: Needs to add code to call Kubectl create case data.action == "PUT": log.Printf("[scheduleResources]: PUT %v %v", data.profile, data.resourceTemplates) //TODO: Needs to add code to call Kubectl apply case data.action == "DELETE": log.Printf("[scheduleResources]: DELETE %v %v", data.profile, data.resourceTemplates) - //TODO: Needs to add code to call Kubectl delete - + for _, inst := range resp { + k8sClient := KubernetesClient{} + err = k8sClient.init(inst.CloudRegion) + if err != nil { + log.Printf("Getting CloudRegion Information: %s", err.Error()) + //Move onto the next cloud region + continue + } + err = k8sClient.deleteResources(data.createdResources, inst.Namespace) + if err != nil { + log.Printf("Error Deleting resources: %s", err.Error()) + continue + } + } } } } @@ -360,12 +396,12 @@ var resolve = func(rbName, rbVersion, profileName string, p Config) (configResou var resTemplates []helm.KubernetesResourceTemplate - profile, err := NewProfileClient().Get(rbName, rbVersion, profileName) + profile, err := rb.NewProfileClient().Get(rbName, rbVersion, profileName) if err != nil { return configResourceList{}, pkgerrors.Wrap(err, "Reading Profile Data") } - t, err := NewConfigTemplateClient().Get(rbName, rbVersion, p.TemplateName) + t, err := rb.NewConfigTemplateClient().Get(rbName, rbVersion, p.TemplateName) if err != nil { return configResourceList{}, pkgerrors.Wrap(err, "Getting Template") } @@ -373,7 +409,7 @@ var resolve = func(rbName, rbVersion, profileName string, p Config) (configResou return configResourceList{}, pkgerrors.New("Invalid template no Chart.yaml file found") } - def, err := NewConfigTemplateClient().Download(rbName, rbVersion, p.TemplateName) + def, err := rb.NewConfigTemplateClient().Download(rbName, rbVersion, p.TemplateName) if err != nil { return configResourceList{}, pkgerrors.Wrap(err, "Downloading Template") } @@ -398,7 +434,7 @@ var resolve = func(rbName, rbVersion, profileName string, p Config) (configResou } defer outputfile.Close() - chartBasePath, err := ExtractTarBall(bytes.NewBuffer(def)) + chartBasePath, err := rb.ExtractTarBall(bytes.NewBuffer(def)) if err != nil { return configResourceList{}, pkgerrors.Wrap(err, "Extracting Template") } diff --git a/src/k8splugin/internal/rb/config_test.go b/src/k8splugin/internal/app/config_test.go index 9bf97a51..11a300ff 100644 --- a/src/k8splugin/internal/rb/config_test.go +++ b/src/k8splugin/internal/app/config_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package rb +package app import ( "k8splugin/internal/db" diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go index 6d0910d0..41eca211 100644 --- a/src/k8splugin/internal/app/instance.go +++ b/src/k8splugin/internal/app/instance.go @@ -53,6 +53,7 @@ type InstanceResponse struct { type InstanceManager interface { Create(i InstanceRequest) (InstanceResponse, error) Get(id string) (InstanceResponse, error) + Find(rbName string, ver string, profile string) ([]InstanceResponse, error) Delete(id string) error } @@ -176,6 +177,48 @@ func (v *InstanceClient) Get(id string) (InstanceResponse, error) { return InstanceResponse{}, pkgerrors.New("Error getting Instance") } +// Find returns the instances that match the given criteria +// If version is empty, it will return all instances for a given rbName +// If profile is empty, it will return all instances for a given rbName+version +func (v *InstanceClient) Find(rbName string, version string, profile string) ([]InstanceResponse, error) { + if rbName == "" { + return []InstanceResponse{}, pkgerrors.New("rbName is required and cannot be empty") + } + + values, err := db.DBconn.ReadAll(v.storeName, v.tagInst) + if err != nil || len(values) == 0 { + return []InstanceResponse{}, pkgerrors.Wrap(err, "Find Instance") + } + + response := []InstanceResponse{} + //values is a map[string][]byte + for _, value := range values { + resp := InstanceResponse{} + db.DBconn.Unmarshal(value, &resp) + if err != nil { + return []InstanceResponse{}, pkgerrors.Wrap(err, "Unmarshaling Instance Value") + } + + if resp.RBName == rbName { + + //Check if a version is provided and if it matches + if version != "" { + if resp.RBVersion == version { + //Check if a profilename matches or if it is not provided + if profile == "" || resp.ProfileName == profile { + response = append(response, resp) + } + } + } else { + //Append all versions as version is not provided + response = append(response, resp) + } + } + } + + return response, nil +} + // Delete the Instance from database func (v *InstanceClient) Delete(id string) error { inst, err := v.Get(id) diff --git a/src/k8splugin/internal/app/instance_test.go b/src/k8splugin/internal/app/instance_test.go index 6ab14a34..2fa2115b 100644 --- a/src/k8splugin/internal/app/instance_test.go +++ b/src/k8splugin/internal/app/instance_test.go @@ -18,6 +18,7 @@ import ( "io/ioutil" "log" "reflect" + "sort" "testing" utils "k8splugin/internal" @@ -312,6 +313,395 @@ func TestInstanceGet(t *testing.T) { }) } +func TestInstanceFind(t *testing.T) { + oldkrdPluginData := utils.LoadedPlugins + + defer func() { + utils.LoadedPlugins = oldkrdPluginData + }() + + err := LoadMockPlugins(utils.LoadedPlugins) + if err != nil { + t.Fatalf("LoadMockPlugins returned an error (%s)", err) + } + + items := map[string]map[string][]byte{ + InstanceKey{ID: "HaKpys8e"}.String(): { + "instance": []byte( + `{ + "profile-name":"profile1", + "id":"HaKpys8e", + "namespace":"testnamespace", + "rb-name":"test-rbdef", + "rb-version":"v1", + "cloud-region":"region1", + "resources": [ + { + "GVK": { + "Group":"apps", + "Version":"v1", + "Kind":"Deployment" + }, + "Name": "deployment-1" + }, + { + "GVK": { + "Group":"", + "Version":"v1", + "Kind":"Service" + }, + "Name": "service-1" + } + ] + }`), + }, + InstanceKey{ID: "HaKpys8f"}.String(): { + "instance": []byte( + `{ + "profile-name":"profile2", + "id":"HaKpys8f", + "namespace":"testnamespace", + "rb-name":"test-rbdef", + "rb-version":"v1", + "cloud-region":"region1", + "resources": [ + { + "GVK": { + "Group":"apps", + "Version":"v1", + "Kind":"Deployment" + }, + "Name": "deployment-1" + }, + { + "GVK": { + "Group":"", + "Version":"v1", + "Kind":"Service" + }, + "Name": "service-1" + } + ] + }`), + }, + InstanceKey{ID: "HaKpys8g"}.String(): { + "instance": []byte( + `{ + "profile-name":"profile1", + "id":"HaKpys8g", + "namespace":"testnamespace", + "rb-name":"test-rbdef", + "rb-version":"v2", + "cloud-region":"region1", + "resources": [ + { + "GVK": { + "Group":"apps", + "Version":"v1", + "Kind":"Deployment" + }, + "Name": "deployment-1" + }, + { + "GVK": { + "Group":"", + "Version":"v1", + "Kind":"Service" + }, + "Name": "service-1" + } + ] + }`), + }, + } + + t.Run("Successfully Find Instance By Name", func(t *testing.T) { + db.DBconn = &db.MockDB{ + Items: items, + } + + expected := []InstanceResponse{ + { + ID: "HaKpys8e", + RBName: "test-rbdef", + RBVersion: "v1", + ProfileName: "profile1", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + { + ID: "HaKpys8f", + RBName: "test-rbdef", + RBVersion: "v1", + ProfileName: "profile2", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + { + ID: "HaKpys8g", + RBName: "test-rbdef", + RBVersion: "v2", + ProfileName: "profile1", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + } + ic := NewInstanceClient() + name := "test-rbdef" + data, err := ic.Find(name, "", "") + if err != nil { + t.Fatalf("TestInstanceFind returned an error (%s)", err) + } + + // Since the order of returned slice is not guaranteed + // Check both and return error if both don't match + sort.Slice(data, func(i, j int) bool { + return data[i].ID < data[j].ID + }) + // Sort both as it is not expected that testCase.expected + // is sorted + sort.Slice(expected, func(i, j int) bool { + return expected[i].ID < expected[j].ID + }) + + if !reflect.DeepEqual(expected, data) { + t.Fatalf("TestInstanceFind returned:\n result=%v\n expected=%v", + data, expected) + } + }) + + t.Run("Successfully Find Instance By Name Version", func(t *testing.T) { + db.DBconn = &db.MockDB{ + Items: items, + } + + expected := []InstanceResponse{ + { + ID: "HaKpys8e", + RBName: "test-rbdef", + RBVersion: "v1", + ProfileName: "profile1", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + { + ID: "HaKpys8f", + RBName: "test-rbdef", + RBVersion: "v1", + ProfileName: "profile2", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + } + ic := NewInstanceClient() + name := "test-rbdef" + data, err := ic.Find(name, "v1", "") + if err != nil { + t.Fatalf("TestInstanceFind returned an error (%s)", err) + } + + // Since the order of returned slice is not guaranteed + // Check both and return error if both don't match + sort.Slice(data, func(i, j int) bool { + return data[i].ID < data[j].ID + }) + // Sort both as it is not expected that testCase.expected + // is sorted + sort.Slice(expected, func(i, j int) bool { + return expected[i].ID < expected[j].ID + }) + + if !reflect.DeepEqual(expected, data) { + t.Fatalf("TestInstanceFind returned:\n result=%v\n expected=%v", + data, expected) + } + }) + + t.Run("Successfully Find Instance By Name Version Profile", func(t *testing.T) { + db.DBconn = &db.MockDB{ + Items: items, + } + + expected := []InstanceResponse{ + { + ID: "HaKpys8e", + RBName: "test-rbdef", + RBVersion: "v1", + ProfileName: "profile1", + CloudRegion: "region1", + Namespace: "testnamespace", + + Resources: []helm.KubernetesResource{ + { + GVK: schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment"}, + Name: "deployment-1", + }, + { + GVK: schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service"}, + Name: "service-1", + }, + }, + }, + } + ic := NewInstanceClient() + name := "test-rbdef" + data, err := ic.Find(name, "v1", "profile1") + if err != nil { + t.Fatalf("TestInstanceFind returned an error (%s)", err) + } + + // Since the order of returned slice is not guaranteed + // Check both and return error if both don't match + sort.Slice(data, func(i, j int) bool { + return data[i].ID < data[j].ID + }) + // Sort both as it is not expected that testCase.expected + // is sorted + sort.Slice(expected, func(i, j int) bool { + return expected[i].ID < expected[j].ID + }) + + if !reflect.DeepEqual(expected, data) { + t.Fatalf("TestInstanceFind returned:\n result=%v\n expected=%v", + data, expected) + } + }) + + t.Run("Find non-existing Instance", func(t *testing.T) { + db.DBconn = &db.MockDB{ + Items: map[string]map[string][]byte{ + InstanceKey{ID: "HaKpys8e"}.String(): { + "instance": []byte( + `{ + "profile-name":"profile1", + "id":"HaKpys8e", + "namespace":"testnamespace", + "rb-name":"test-rbdef", + "rb-version":"v1", + "cloud-region":"region1", + "resources": [ + { + "GVK": { + "Group":"apps", + "Version":"v1", + "Kind":"Deployment" + }, + "Name": "deployment-1" + }, + { + "GVK": { + "Group":"", + "Version":"v1", + "Kind":"Service" + }, + "Name": "service-1" + } + ] + }`), + }, + }, + } + + ic := NewInstanceClient() + name := "non-existing" + resp, _ := ic.Find(name, "", "") + if len(resp) != 0 { + t.Fatalf("Expected 0 responses, but got %d", len(resp)) + } + }) +} + func TestInstanceDelete(t *testing.T) { oldkrdPluginData := utils.LoadedPlugins diff --git a/src/k8splugin/mock_files/mock_yamls/ovn4nfvk8s.yaml b/src/k8splugin/mock_files/mock_yamls/ovn4nfvk8s.yaml index 1a262753..31351dee 100644 --- a/src/k8splugin/mock_files/mock_yamls/ovn4nfvk8s.yaml +++ b/src/k8splugin/mock_files/mock_yamls/ovn4nfvk8s.yaml @@ -1,15 +1,9 @@ apiVersion: v1 -kind: OnapNetwork +kind: Network metadata: name: ovn-priv-net spec: - config: '{ - "cnitype": "ovn4nfvk8s", - "name": "mynet", - "subnet": "172.16.33.0/24", - "gateway": "172.16.33.1", - "routes": [{ - "dst": "172.16.29.1/24", - "gw": "100.64.1.1" - }] - }'
\ No newline at end of file + cnitype: "ovn4nfvk8s" + name: "ovn-priv-net" + subnet: "172.16.33.0/24" + gateway: "172.16.33.1/24" diff --git a/src/k8splugin/plugins/network/plugin.go b/src/k8splugin/plugins/network/plugin.go index fb163189..74ac3473 100644 --- a/src/k8splugin/plugins/network/plugin.go +++ b/src/k8splugin/plugins/network/plugin.go @@ -42,12 +42,7 @@ func Create(data *utils.ResourceData, client kubernetes.Interface) (string, erro return "", pkgerrors.Wrap(err, "Decode network object error") } - config, err := network.DecodeConfig() - if err != nil { - return "", pkgerrors.Wrap(err, "Fail to decode network's configuration") - } - - cniType := config["cnitype"].(string) + cniType := network.Spec.CniType typePlugin, ok := utils.LoadedPlugins[cniType+"-network"] if !ok { return "", pkgerrors.New("No plugin for resource " + cniType + " found") diff --git a/src/k8splugin/plugins/network/plugin_test.go b/src/k8splugin/plugins/network/plugin_test.go index 5bf649a9..e8e113b2 100644 --- a/src/k8splugin/plugins/network/plugin_test.go +++ b/src/k8splugin/plugins/network/plugin_test.go @@ -71,7 +71,7 @@ func TestCreateNetwork(t *testing.T) { input: &utils.ResourceData{ YamlFilePath: "../../mock_files/mock_yamls/service.yaml", }, - expectedError: "Fail to decode network's configuration: Invalid configuration value", + expectedError: "No plugin for resource", }, { label: "Fail to create a network", diff --git a/src/k8splugin/plugins/network/v1/types.go b/src/k8splugin/plugins/network/v1/types.go index b4efa39a..96484efa 100644 --- a/src/k8splugin/plugins/network/v1/types.go +++ b/src/k8splugin/plugins/network/v1/types.go @@ -14,9 +14,7 @@ limitations under the License. package v1 import ( - "encoding/json" - pkgerrors "github.com/pkg/errors" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -33,7 +31,11 @@ type OnapNetwork struct { // OnapNetworkSpec is the spec for OnapNetwork resource type OnapNetworkSpec struct { - Config string `json:"config"` + CniType string `json:"cnitype"` + Name string `json:"name"` + Subnet string `json:"subnet"` + Gateway string `json:"gateway"` + } // DeepCopyObject returns a generically typed copy of an object @@ -50,18 +52,3 @@ func (in OnapNetwork) DeepCopyObject() runtime.Object { func (in OnapNetwork) GetObjectKind() schema.ObjectKind { return &in.TypeMeta } - -// DecodeConfig content -func (in OnapNetwork) DecodeConfig() (map[string]interface{}, error) { - var raw map[string]interface{} - - if in.Spec.Config == "" { - return nil, pkgerrors.New("Invalid configuration value") - } - - if err := json.Unmarshal([]byte(in.Spec.Config), &raw); err != nil { - return nil, pkgerrors.Wrap(err, "JSON unmarshalling error") - } - - return raw, nil -} diff --git a/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go index 959586bc..3f5d80ba 100644 --- a/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go +++ b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin.go @@ -46,6 +46,9 @@ type OVNNbctl struct { // Run a command via ovn-nbctl func (ctl *OVNNbctl) Run(args ...string) (string, string, error) { + if ctl.exec == nil { + ctl.exec = kexec.New() + } if ctl.path == "" { nbctlPath, err := ctl.exec.LookPath(ovnNbctlCommand) if err != nil { @@ -53,9 +56,6 @@ func (ctl *OVNNbctl) Run(args ...string) (string, string, error) { } ctl.path = nbctlPath } - if ctl.exec == nil { - ctl.exec = kexec.New() - } stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} @@ -76,25 +76,21 @@ func init() { // CreateNetwork in OVN controller func CreateNetwork(network *v1.OnapNetwork) (string, error) { - config, err := network.DecodeConfig() - if err != nil { - return "", err - } - name := config["name"].(string) - if name == "" { - return "", pkgerrors.New("Empty Name value") - } + name := network.Spec.Name + if name == "" { + return "", pkgerrors.New("Invalid Network Name") + } - subnet := config["subnet"].(string) - if subnet == "" { - return "", pkgerrors.New("Empty Subnet value") - } + subnet := network.Spec.Subnet + if subnet == "" { + return "", pkgerrors.New("Invalid Subnet Address") + } - gatewayIPMask := config["gateway"].(string) - if gatewayIPMask == "" { - return "", pkgerrors.New("Empty Gateway IP Mask") - } + gatewayIPMask := network.Spec.Gateway + if gatewayIPMask == "" { + return "", pkgerrors.New("Invalid Gateway Address") + } routerMac, stderr, err := ovnCmd.Run(getAuthStr(), "--if-exist", "-v", "get", "logical_router_port", "rtos-"+name, "mac") if err != nil { diff --git a/src/k8splugin/plugins/ovn4nfvk8s-network/plugin_test.go b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin_test.go index ce848a71..6a1054ee 100644 --- a/src/k8splugin/plugins/ovn4nfvk8s-network/plugin_test.go +++ b/src/k8splugin/plugins/ovn4nfvk8s-network/plugin_test.go @@ -43,7 +43,7 @@ func TestCreateOVN4NFVK8SNetwork(t *testing.T) { { label: "Fail to decode a network", input: &v1.OnapNetwork{}, - expectedError: "Invalid configuration value", + expectedError: "Invalid Network Name", }, { label: "Fail to create a network", @@ -52,7 +52,7 @@ func TestCreateOVN4NFVK8SNetwork(t *testing.T) { Name: "test", }, Spec: v1.OnapNetworkSpec{ - Config: "{\"cnitype\": \"ovn4nfvk8s\",\"name\": \"mynet\",\"subnet\": \"172.16.33.0/24\",\"gateway\": \"172.16.33.1\",\"routes\": [{\"dst\": \"172.16.29.1/24\",\"gw\": \"100.64.1.1\"}]}", + CniType: "ovn4nfvk8s", Name: "mynet", Subnet: "172.16.33.0/24", Gateway: "172.16.33.1/24", }, }, expectedError: "Failed to get logical router", @@ -67,7 +67,7 @@ func TestCreateOVN4NFVK8SNetwork(t *testing.T) { Name: "test", }, Spec: v1.OnapNetworkSpec{ - Config: "{\"cnitype\": \"ovn4nfvk8s\",\"name\": \"mynet\",\"subnet\": \"172.16.33.0/24\",\"gateway\": \"172.16.33.1\",\"routes\": [{\"dst\": \"172.16.29.1/24\",\"gw\": \"100.64.1.1\"}]}", + CniType: "ovn4nfvk8s", Name: "mynet", Subnet: "172.16.33.0/24", Gateway: "172.16.33.1/24", }, }, expectedResult: "mynet", |