summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBin Yang <bin.yang@windriver.com>2020-02-15 03:02:14 +0000
committerGerrit Code Review <gerrit@onap.org>2020-02-15 03:02:14 +0000
commit8af74ae61508a3fbfd54c25d1cfe037f3ad08ca5 (patch)
treef22f86d106d281aec7ccedf6b7a4f1078f5cef9c
parente8e3cfc3d3df008505520836fafc9920f5643ca6 (diff)
parentc3e1c9a5fefde3fcb6aaf05c19b18f211c1a43ba (diff)
Merge changes I56fb4643,Ia1e9802a
* changes: Add etcd support in infrastructure layer Restructure code and create module library
-rw-r--r--src/orchestrator/api/api.go19
-rw-r--r--src/orchestrator/api/projecthandler.go12
-rw-r--r--src/orchestrator/api/projecthandler_test.go38
-rw-r--r--src/orchestrator/cmd/main.go14
-rw-r--r--src/orchestrator/examples/example_module.go48
-rw-r--r--src/orchestrator/go.sum1
-rw-r--r--src/orchestrator/pkg/infra/auth/auth.go (renamed from src/orchestrator/internal/auth/auth.go)0
-rw-r--r--src/orchestrator/pkg/infra/auth/auth_test.go (renamed from src/orchestrator/internal/auth/auth_test.go)6
-rw-r--r--src/orchestrator/pkg/infra/config/config.go (renamed from src/orchestrator/internal/config/config.go)6
-rw-r--r--src/orchestrator/pkg/infra/config/config_test.go (renamed from src/orchestrator/internal/config/config_test.go)2
-rw-r--r--src/orchestrator/pkg/infra/contextdb/contextdb.go72
-rw-r--r--src/orchestrator/pkg/infra/contextdb/etcd.go175
-rw-r--r--src/orchestrator/pkg/infra/contextdb/etcd_test.go276
-rw-r--r--src/orchestrator/pkg/infra/contextdb/mock.go58
-rw-r--r--src/orchestrator/pkg/infra/db/README.md (renamed from src/orchestrator/internal/db/README.md)0
-rw-r--r--src/orchestrator/pkg/infra/db/mock.go (renamed from src/orchestrator/internal/db/mock.go)0
-rw-r--r--src/orchestrator/pkg/infra/db/mongo.go (renamed from src/orchestrator/internal/db/mongo.go)2
-rw-r--r--src/orchestrator/pkg/infra/db/mongo_test.go (renamed from src/orchestrator/internal/db/mongo_test.go)0
-rw-r--r--src/orchestrator/pkg/infra/db/store.go (renamed from src/orchestrator/internal/db/store.go)2
-rw-r--r--src/orchestrator/pkg/infra/db/store_test.go (renamed from src/orchestrator/internal/db/store_test.go)0
-rw-r--r--src/orchestrator/pkg/infra/logutils/logger.go (renamed from src/orchestrator/internal/logutils/logger.go)0
-rw-r--r--src/orchestrator/pkg/module/module.go34
-rw-r--r--src/orchestrator/pkg/module/project.go (renamed from src/orchestrator/internal/project/project.go)30
-rw-r--r--src/orchestrator/pkg/module/project_test.go (renamed from src/orchestrator/internal/project/project_test.go)10
24 files changed, 737 insertions, 68 deletions
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go
index 83f17bbe..e37b158a 100644
--- a/src/orchestrator/api/api.go
+++ b/src/orchestrator/api/api.go
@@ -10,29 +10,28 @@ 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 api
import (
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/project"
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
"github.com/gorilla/mux"
)
-
+var moduleClient *moduleLib.Client
// NewRouter creates a router that registers the various urls that are supported
-func NewRouter(projectClient project.ProjectManager) *mux.Router {
+func NewRouter(projectClient moduleLib.ProjectManager) *mux.Router {
router := mux.NewRouter().PathPrefix("/v2").Subrouter()
-
+ moduleClient = moduleLib.NewClient()
if projectClient == nil {
- projectClient = project.NewProjectClient()
+ projectClient = moduleClient.Project
}
projHandler := projectHandler{
client: projectClient,
}
- router.HandleFunc("/project", projHandler.createHandler).Methods("POST")
- router.HandleFunc("/project/{project-name}", projHandler.getHandler).Methods("GET")
- router.HandleFunc("/project/{project-name}", projHandler.deleteHandler).Methods("DELETE")
+ router.HandleFunc("/projects", projHandler.createHandler).Methods("POST")
+ router.HandleFunc("/projects/{project-name}", projHandler.getHandler).Methods("GET")
+ router.HandleFunc("/projects/{project-name}", projHandler.deleteHandler).Methods("DELETE")
return router
-}
+} \ No newline at end of file
diff --git a/src/orchestrator/api/projecthandler.go b/src/orchestrator/api/projecthandler.go
index 30f21de3..1830b91d 100644
--- a/src/orchestrator/api/projecthandler.go
+++ b/src/orchestrator/api/projecthandler.go
@@ -21,7 +21,7 @@ import (
"io"
"net/http"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/project"
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
"github.com/gorilla/mux"
)
@@ -31,12 +31,12 @@ import (
type projectHandler struct {
// Interface that implements Project operations
// We will set this variable with a mock interface for testing
- client project.ProjectManager
+ client moduleLib.ProjectManager
}
// Create handles creation of the Project entry in the database
func (h projectHandler) createHandler(w http.ResponseWriter, r *http.Request) {
- var p project.Project
+ var p moduleLib.Project
err := json.NewDecoder(r.Body).Decode(&p)
switch {
@@ -54,7 +54,7 @@ func (h projectHandler) createHandler(w http.ResponseWriter, r *http.Request) {
return
}
- ret, err := h.client.Create(p)
+ ret, err := h.client.CreateProject(p)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -75,7 +75,7 @@ func (h projectHandler) getHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["project-name"]
- ret, err := h.client.Get(name)
+ ret, err := h.client.GetProject(name)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -95,7 +95,7 @@ func (h projectHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["project-name"]
- err := h.client.Delete(name)
+ err := h.client.DeleteProject(name)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
diff --git a/src/orchestrator/api/projecthandler_test.go b/src/orchestrator/api/projecthandler_test.go
index 2699f2e3..41f515d0 100644
--- a/src/orchestrator/api/projecthandler_test.go
+++ b/src/orchestrator/api/projecthandler_test.go
@@ -25,7 +25,7 @@ import (
"reflect"
"testing"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/project"
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
pkgerrors "github.com/pkg/errors"
)
@@ -36,27 +36,27 @@ import (
type mockProjectManager struct {
// Items and err will be used to customize each test
// via a localized instantiation of mockProjectManager
- Items []project.Project
+ Items []moduleLib.Project
Err error
}
-func (m *mockProjectManager) Create(inp project.Project) (project.Project, error) {
+func (m *mockProjectManager) CreateProject(inp moduleLib.Project) (moduleLib.Project, error) {
if m.Err != nil {
- return project.Project{}, m.Err
+ return moduleLib.Project{}, m.Err
}
return m.Items[0], nil
}
-func (m *mockProjectManager) Get(name string) (project.Project, error) {
+func (m *mockProjectManager) GetProject(name string) (moduleLib.Project, error) {
if m.Err != nil {
- return project.Project{}, m.Err
+ return moduleLib.Project{}, m.Err
}
return m.Items[0], nil
}
-func (m *mockProjectManager) Delete(name string) error {
+func (m *mockProjectManager) DeleteProject(name string) error {
return m.Err
}
@@ -64,7 +64,7 @@ func TestProjectCreateHandler(t *testing.T) {
testCases := []struct {
label string
reader io.Reader
- expected project.Project
+ expected moduleLib.Project
expectedCode int
projectClient *mockProjectManager
}{
@@ -80,13 +80,13 @@ func TestProjectCreateHandler(t *testing.T) {
"project-name":"testProject",
"description":"Test Project used for unit testing"
}`)),
- expected: project.Project{
+ expected: moduleLib.Project{
ProjectName: "testProject",
Description: "Test Project used for unit testing",
},
projectClient: &mockProjectManager{
//Items that will be returned by the mocked Client
- Items: []project.Project{
+ Items: []moduleLib.Project{
{
ProjectName: "testProject",
Description: "Test Project used for unit testing",
@@ -106,7 +106,7 @@ func TestProjectCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
- request := httptest.NewRequest("POST", "/v2/project", testCase.reader)
+ request := httptest.NewRequest("POST", "/v2/projects", testCase.reader)
resp := executeRequest(request, NewRouter(testCase.projectClient))
//Check returned code
@@ -116,7 +116,7 @@ func TestProjectCreateHandler(t *testing.T) {
//Check returned body only if statusCreated
if resp.StatusCode == http.StatusCreated {
- got := project.Project{}
+ got := moduleLib.Project{}
json.NewDecoder(resp.Body).Decode(&got)
if reflect.DeepEqual(testCase.expected, got) == false {
@@ -132,7 +132,7 @@ func TestProjectGetHandler(t *testing.T) {
testCases := []struct {
label string
- expected project.Project
+ expected moduleLib.Project
name, version string
expectedCode int
projectClient *mockProjectManager
@@ -140,13 +140,13 @@ func TestProjectGetHandler(t *testing.T) {
{
label: "Get Project",
expectedCode: http.StatusOK,
- expected: project.Project{
+ expected: moduleLib.Project{
ProjectName: "testProject",
Description: "A Test project for unit testing",
},
name: "testProject",
projectClient: &mockProjectManager{
- Items: []project.Project{
+ Items: []moduleLib.Project{
{
ProjectName: "testProject",
Description: "A Test project for unit testing",
@@ -159,7 +159,7 @@ func TestProjectGetHandler(t *testing.T) {
expectedCode: http.StatusInternalServerError,
name: "nonexistingproject",
projectClient: &mockProjectManager{
- Items: []project.Project{},
+ Items: []moduleLib.Project{},
Err: pkgerrors.New("Internal Error"),
},
},
@@ -167,7 +167,7 @@ func TestProjectGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
- request := httptest.NewRequest("GET", "/v2/project/"+testCase.name, nil)
+ request := httptest.NewRequest("GET", "/v2/projects/"+testCase.name, nil)
resp := executeRequest(request, NewRouter(testCase.projectClient))
//Check returned code
@@ -177,7 +177,7 @@ func TestProjectGetHandler(t *testing.T) {
//Check returned body only if statusOK
if resp.StatusCode == http.StatusOK {
- got := project.Project{}
+ got := moduleLib.Project{}
json.NewDecoder(resp.Body).Decode(&got)
if reflect.DeepEqual(testCase.expected, got) == false {
@@ -216,7 +216,7 @@ func TestProjectDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
- request := httptest.NewRequest("DELETE", "/v2/project/"+testCase.name, nil)
+ request := httptest.NewRequest("DELETE", "/v2/projects/"+testCase.name, nil)
resp := executeRequest(request, NewRouter(testCase.projectClient))
//Check returned code
diff --git a/src/orchestrator/cmd/main.go b/src/orchestrator/cmd/main.go
index 657d5bf5..f46fe910 100644
--- a/src/orchestrator/cmd/main.go
+++ b/src/orchestrator/cmd/main.go
@@ -23,10 +23,10 @@ import (
"time"
"github.com/onap/multicloud-k8s/src/orchestrator/api"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/auth"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/config"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/db"
-
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/auth"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/config"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
+ contextDb "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/contextdb"
"github.com/gorilla/handlers"
)
@@ -40,6 +40,12 @@ func main() {
log.Println(err)
log.Fatalln("Exiting...")
}
+ err = contextDb.InitializeContextDatabase()
+ if err != nil {
+ log.Println("Unable to initialize database connection...")
+ log.Println(err)
+ log.Fatalln("Exiting...")
+ }
httpRouter := api.NewRouter(nil)
loggedRouter := handlers.LoggingHandler(os.Stdout, httpRouter)
diff --git a/src/orchestrator/examples/example_module.go b/src/orchestrator/examples/example_module.go
new file mode 100644
index 00000000..29ecdc23
--- /dev/null
+++ b/src/orchestrator/examples/example_module.go
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 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 test
+
+import (
+ moduleLib "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module"
+ "log"
+)
+
+// ExampleClient_Project to test Project
+func ExampleClient_Project() {
+ // Get handle to the client
+ c := moduleLib.NewClient()
+ // Check if project is initialized
+ if c.Project == nil {
+ log.Println("Project is Uninitialized")
+ return
+ }
+ // Perform operations on Project Module
+ _, err := c.Project.CreateProject(moduleLib.Project{ProjectName: "test"})
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ _, err = c.Project.GetProject("test")
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ err = c.Project.DeleteProject("test")
+ if err != nil {
+ log.Println(err)
+ }
+}
diff --git a/src/orchestrator/go.sum b/src/orchestrator/go.sum
index 732bc280..d2015406 100644
--- a/src/orchestrator/go.sum
+++ b/src/orchestrator/go.sum
@@ -171,6 +171,7 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onap/multicloud-k8s v0.0.0-20191115005109-f168ebb73d8d h1:3uFucXVv6gqa3H1u85CjoLOvGraREfD8/NL7m/9W9tc=
+github.com/onap/multicloud-k8s v0.0.0-20200131010833-90e13d101cf0 h1:2qDo6s4pdg/g7Vj6QGrCK02EP4jjwVehgEObnAfipSM=
github.com/onap/multicloud-k8s/src/k8splugin v0.0.0-20191115005109-f168ebb73d8d h1:ucIEjqzNVeFPnQofeuBfUqro0OnilX//fajEFxuLsgA=
github.com/onap/multicloud-k8s/src/k8splugin v0.0.0-20191115005109-f168ebb73d8d/go.mod h1:EnQd/vQGZR1/55IihaHxiux4ZUig/zfXZux7bfmU0S8=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
diff --git a/src/orchestrator/internal/auth/auth.go b/src/orchestrator/pkg/infra/auth/auth.go
index 3da8f2af..3da8f2af 100644
--- a/src/orchestrator/internal/auth/auth.go
+++ b/src/orchestrator/pkg/infra/auth/auth.go
diff --git a/src/orchestrator/internal/auth/auth_test.go b/src/orchestrator/pkg/infra/auth/auth_test.go
index e41cb1ac..fdf81e6d 100644
--- a/src/orchestrator/internal/auth/auth_test.go
+++ b/src/orchestrator/pkg/infra/auth/auth_test.go
@@ -28,9 +28,9 @@ func TestGetTLSConfig(t *testing.T) {
if err == nil {
t.Errorf("Test failed, expected error but got none")
}
- tlsConfig, err := GetTLSConfig("../../tests/certs/auth_test_certificate.pem",
- "../../tests/certs/auth_test_certificate.pem",
- "../../tests/certs/auth_test_key.pem")
+ tlsConfig, err := GetTLSConfig("../../../tests/certs/auth_test_certificate.pem",
+ "../../../tests/certs/auth_test_certificate.pem",
+ "../../../tests/certs/auth_test_key.pem")
if err != nil {
t.Fatal("Test Failed as GetTLSConfig returned error: " + err.Error())
}
diff --git a/src/orchestrator/internal/config/config.go b/src/orchestrator/pkg/infra/config/config.go
index cb4656f0..df9cec92 100644
--- a/src/orchestrator/internal/config/config.go
+++ b/src/orchestrator/pkg/infra/config/config.go
@@ -83,9 +83,9 @@ func defaultConfiguration() *Configuration {
DatabaseType: "mongo",
PluginDir: cwd,
EtcdIP: "127.0.0.1",
- EtcdCert: "etcd.cert",
- EtcdKey: "etcd.key",
- EtcdCAFile: "etcd-ca.cert",
+ EtcdCert: "",
+ EtcdKey: "",
+ EtcdCAFile: "",
ServicePort: "9015",
KubernetesLabelName: "orchestrator.io/rb-instance-id",
}
diff --git a/src/orchestrator/internal/config/config_test.go b/src/orchestrator/pkg/infra/config/config_test.go
index ce7641ae..dce37e76 100644
--- a/src/orchestrator/internal/config/config_test.go
+++ b/src/orchestrator/pkg/infra/config/config_test.go
@@ -29,7 +29,7 @@ func TestReadConfigurationFile(t *testing.T) {
})
t.Run("Read Configuration File", func(t *testing.T) {
- conf, err := readConfigFile("../../tests/configs/mock_config.json")
+ conf, err := readConfigFile("../../../tests/configs/mock_config.json")
if err != nil {
t.Fatal("ReadConfigurationFile: Error reading file: ", err)
}
diff --git a/src/orchestrator/pkg/infra/contextdb/contextdb.go b/src/orchestrator/pkg/infra/contextdb/contextdb.go
new file mode 100644
index 00000000..d18af227
--- /dev/null
+++ b/src/orchestrator/pkg/infra/contextdb/contextdb.go
@@ -0,0 +1,72 @@
+/*
+Copyright 2020 Intel Corporation.
+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 contextdb
+
+import (
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/config"
+ pkgerrors "github.com/pkg/errors"
+)
+
+// Db interface used to talk a concrete Database connection
+var Db ContextDb
+
+// ContextDb is an interface for accessing the context database
+type ContextDb interface {
+ // Returns nil if db health is good
+ HealthCheck() error
+ // Puts Json Struct in db with key
+ Put(key string, value interface{}) error
+ // Delete k,v
+ Delete(key string) error
+ // Gets Json Struct from db
+ Get(key string, value interface{}) error
+ // Returns all keys with a prefix
+ GetAllKeys(path string) ([]string, error)
+}
+
+// createContextDBClient creates the DB client
+func createContextDBClient(dbType string) error {
+ var err error
+ switch dbType {
+ case "etcd":
+ c := EtcdConfig{
+ Endpoint: config.GetConfiguration().EtcdIP,
+ CertFile: config.GetConfiguration().EtcdCert,
+ KeyFile: config.GetConfiguration().EtcdKey,
+ CAFile: config.GetConfiguration().EtcdCAFile,
+ }
+ Db, err = NewEtcdClient(nil, c)
+ if err != nil {
+ pkgerrors.Wrap(err, "Etcd Client Initialization failed with error")
+ }
+ default:
+ return pkgerrors.New(dbType + "DB not supported")
+ }
+ return err
+}
+
+// InitializeContextDatabase sets up the connection to the
+// configured database to allow the application to talk to it.
+func InitializeContextDatabase() error {
+ // Only support Etcd for now
+ err := createContextDBClient("etcd")
+ if err != nil {
+ return pkgerrors.Cause(err)
+ }
+ err = Db.HealthCheck()
+ if err != nil {
+ return pkgerrors.Cause(err)
+ }
+ return nil
+}
diff --git a/src/orchestrator/pkg/infra/contextdb/etcd.go b/src/orchestrator/pkg/infra/contextdb/etcd.go
new file mode 100644
index 00000000..a1922d3b
--- /dev/null
+++ b/src/orchestrator/pkg/infra/contextdb/etcd.go
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2020 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 contextdb
+
+import (
+ "context"
+ "encoding/json"
+ pkgerrors "github.com/pkg/errors"
+ "go.etcd.io/etcd/clientv3"
+ "go.etcd.io/etcd/pkg/transport"
+ "time"
+)
+
+// EtcdConfig Configuration values needed for Etcd Client
+type EtcdConfig struct {
+ Endpoint string
+ CertFile string
+ KeyFile string
+ CAFile string
+}
+
+// EtcdClient for Etcd
+type EtcdClient struct {
+ cli *clientv3.Client
+ endpoint string
+}
+
+// Etcd For Mocking purposes
+type Etcd interface {
+ Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error)
+ Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error)
+ Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error)
+}
+
+var getEtcd = func(e *EtcdClient) Etcd {
+ return e.cli
+}
+
+// NewEtcdClient function initializes Etcd client
+func NewEtcdClient(store *clientv3.Client, c EtcdConfig) (ContextDb, error) {
+ var endpoint string
+ if store == nil {
+ tlsInfo := transport.TLSInfo{
+ CertFile: c.CertFile,
+ KeyFile: c.KeyFile,
+ CAFile: c.CAFile,
+ }
+ tlsConfig, err := tlsInfo.ClientConfig()
+ if err != nil {
+ return nil, pkgerrors.Errorf("Error creating etcd TLSInfo: %s", err.Error())
+ }
+ // NOTE: Client relies on nil tlsConfig
+ // for non-secure connections, update the implicit variable
+ if len(c.CertFile) == 0 && len(c.KeyFile) == 0 && len(c.CAFile) == 0 {
+ tlsConfig = nil
+ }
+ endpoint = ""
+ if tlsConfig == nil {
+ endpoint = "http://" + c.Endpoint + ":2379"
+ } else {
+ endpoint = "https://" + c.Endpoint + ":2379"
+ }
+
+ store, err = clientv3.New(clientv3.Config{
+ Endpoints: []string{endpoint},
+ DialTimeout: 5 * time.Second,
+ TLS: tlsConfig,
+ })
+ if err != nil {
+ return nil, pkgerrors.Errorf("Error creating etcd client: %s", err.Error())
+ }
+ }
+
+ return &EtcdClient{
+ cli: store,
+ endpoint: endpoint,
+ }, nil
+}
+
+// Put values in Etcd DB
+func (e *EtcdClient) Put(key string, value interface{}) error {
+ cli := getEtcd(e)
+ if cli == nil {
+ return pkgerrors.Errorf("Etcd Client not initialized")
+ }
+ if key == "" {
+ return pkgerrors.Errorf("Key is null")
+ }
+ if value == nil {
+ return pkgerrors.Errorf("Value is nil")
+ }
+ v, err := json.Marshal(value)
+ if err != nil {
+ return pkgerrors.Errorf("Json Marshal error: %s", err.Error())
+ }
+ _, err = cli.Put(context.Background(), key, string(v))
+ if err != nil {
+ return pkgerrors.Errorf("Error creating etcd entry: %s", err.Error())
+ }
+ return nil
+}
+
+// Get values from Etcd DB and decodes from json
+func (e *EtcdClient) Get(key string, value interface{}) error {
+ cli := getEtcd(e)
+ if cli == nil {
+ return pkgerrors.Errorf("Etcd Client not initialized")
+ }
+ if key == "" {
+ return pkgerrors.Errorf("Key is null")
+ }
+ if value == nil {
+ return pkgerrors.Errorf("Value is nil")
+ }
+ getResp, err := cli.Get(context.Background(), key)
+ if err != nil {
+ return pkgerrors.Errorf("Error getting etcd entry: %s", err.Error())
+ }
+ if getResp.Count == 0 {
+ return pkgerrors.Errorf("Key doesn't exist")
+ }
+ return json.Unmarshal(getResp.Kvs[0].Value, value)
+}
+
+// GetAllKeys values from Etcd DB
+func (e *EtcdClient) GetAllKeys(key string) ([]string, error) {
+ cli := getEtcd(e)
+ if cli == nil {
+ return nil, pkgerrors.Errorf("Etcd Client not initialized")
+ }
+ getResp, err := cli.Get(context.Background(), key, clientv3.WithPrefix())
+ if err != nil {
+ return nil, pkgerrors.Errorf("Error getting etcd entry: %s", err.Error())
+ }
+ if getResp.Count == 0 {
+ return nil, pkgerrors.Errorf("Key doesn't exist")
+ }
+ var keys []string
+ for _, ev := range getResp.Kvs {
+ keys = append(keys, string(ev.Key))
+ }
+ return keys, nil
+}
+
+// Delete values from Etcd DB
+func (e *EtcdClient) Delete(key string) error {
+ cli := getEtcd(e)
+ if cli == nil {
+ return pkgerrors.Errorf("Etcd Client not initialized")
+ }
+ _, err := cli.Delete(context.Background(), key, clientv3.WithPrefix())
+ if err != nil {
+ return pkgerrors.Errorf("Delete failed etcd entry: %s", err.Error())
+ }
+ return nil
+}
+
+// HealthCheck for checking health of the etcd cluster
+func (e *EtcdClient) HealthCheck() error {
+ return nil
+}
diff --git a/src/orchestrator/pkg/infra/contextdb/etcd_test.go b/src/orchestrator/pkg/infra/contextdb/etcd_test.go
new file mode 100644
index 00000000..17b7a5d5
--- /dev/null
+++ b/src/orchestrator/pkg/infra/contextdb/etcd_test.go
@@ -0,0 +1,276 @@
+/*
+Copyright 2020 Intel Corporation.
+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 contextdb
+
+import (
+ "context"
+ mvccpb "github.com/coreos/etcd/mvcc/mvccpb"
+ pkgerrors "github.com/pkg/errors"
+ "go.etcd.io/etcd/clientv3"
+ "strings"
+ "testing"
+)
+
+type kv struct {
+ Key []byte
+ Value []byte
+}
+
+// MockEtcdClient for mocking etcd
+type MockEtcdClient struct {
+ Kvs []*mvccpb.KeyValue
+ Count int64
+ Err error
+}
+
+// Mocking only Single Value
+// Put function
+func (e *MockEtcdClient) Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
+ var m mvccpb.KeyValue
+ m.Key = []byte(key)
+ m.Value = []byte(val)
+ e.Count = e.Count + 1
+ e.Kvs = append(e.Kvs, &m)
+ return &clientv3.PutResponse{}, e.Err
+}
+
+// Get function
+func (e *MockEtcdClient) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
+ var g clientv3.GetResponse
+ g.Kvs = e.Kvs
+ g.Count = e.Count
+ return &g, e.Err
+}
+
+// Delete function
+func (e *MockEtcdClient) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
+ return &clientv3.DeleteResponse{}, e.Err
+}
+
+type testStruct struct {
+ Name string `json:"name"`
+ Num int `json:"num"`
+}
+
+// TestPut test Put
+func TestPut(t *testing.T) {
+ testCases := []struct {
+ label string
+ mockEtcd *MockEtcdClient
+ expectedError string
+ key string
+ value *testStruct
+ }{
+ {
+ label: "Success Case",
+ mockEtcd: &MockEtcdClient{},
+ key: "test1",
+ value: &testStruct{Name: "test", Num: 5},
+ },
+ {
+ label: "Key is null",
+ mockEtcd: &MockEtcdClient{},
+ key: "",
+ expectedError: "Key is null",
+ },
+ {
+ label: "Value is nil",
+ mockEtcd: &MockEtcdClient{},
+ key: "test1",
+ value: nil,
+ expectedError: "Value is nil",
+ },
+ {
+ label: "Error creating etcd entry",
+ mockEtcd: &MockEtcdClient{Err: pkgerrors.New("DB Error")},
+ key: "test1",
+ value: &testStruct{Name: "test", Num: 5},
+ expectedError: "Error creating etcd entry: DB Error",
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ cli, _ := NewEtcdClient(&clientv3.Client{}, EtcdConfig{})
+ getEtcd = func(e *EtcdClient) Etcd {
+ return testCase.mockEtcd
+ }
+ err := cli.Put(testCase.key, testCase.value)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("Method returned an un-expected (%s)", err)
+ }
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestGet(t *testing.T) {
+ testCases := []struct {
+ label string
+ mockEtcd *MockEtcdClient
+ expectedError string
+ key string
+ value *testStruct
+ }{
+ {
+ label: "Key is null",
+ mockEtcd: &MockEtcdClient{},
+ key: "",
+ value: nil,
+ expectedError: "Key is null",
+ },
+ {
+ label: "Key doesn't exist",
+ mockEtcd: &MockEtcdClient{},
+ key: "test1",
+ value: &testStruct{},
+ expectedError: "Key doesn't exist",
+ },
+ {
+ label: "Error getting etcd entry",
+ mockEtcd: &MockEtcdClient{Err: pkgerrors.New("DB Error")},
+ key: "test1",
+ value: &testStruct{},
+ expectedError: "Error getting etcd entry: DB Error",
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ cli, _ := NewEtcdClient(&clientv3.Client{}, EtcdConfig{})
+ getEtcd = func(e *EtcdClient) Etcd {
+ return testCase.mockEtcd
+ }
+ err := cli.Get(testCase.key, testCase.value)
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("Method returned an un-expected (%s)", err)
+ }
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestGetString(t *testing.T) {
+ testCases := []struct {
+ label string
+ mockEtcd *MockEtcdClient
+ expectedError string
+ value string
+ }{
+ {
+ label: "Success Case",
+ mockEtcd: &MockEtcdClient{},
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ cli, _ := NewEtcdClient(&clientv3.Client{}, EtcdConfig{})
+ getEtcd = func(e *EtcdClient) Etcd {
+ return testCase.mockEtcd
+ }
+ err := cli.Put("test", "test1")
+ if err != nil {
+ t.Error("Test failed", err)
+ }
+ var s string
+ err = cli.Get("test", &s)
+ if err != nil {
+ t.Error("Test failed", err)
+ }
+ if "test1" != s {
+ t.Error("Get Failed")
+ }
+ })
+ }
+}
+
+func TestDelete(t *testing.T) {
+ testCases := []struct {
+ label string
+ mockEtcd *MockEtcdClient
+ expectedError string
+ }{
+ {
+ label: "Success Case",
+ mockEtcd: &MockEtcdClient{},
+ },
+ {
+ label: "Delete failed etcd entry",
+ mockEtcd: &MockEtcdClient{Err: pkgerrors.New("DB Error")},
+ expectedError: "Delete failed etcd entry: DB Error",
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ cli, _ := NewEtcdClient(&clientv3.Client{}, EtcdConfig{})
+ getEtcd = func(e *EtcdClient) Etcd {
+ return testCase.mockEtcd
+ }
+ err := cli.Delete("test")
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("Method returned an un-expected (%s)", err)
+ }
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+
+ })
+ }
+}
+
+func TestGetAll(t *testing.T) {
+ testCases := []struct {
+ label string
+ mockEtcd *MockEtcdClient
+ expectedError string
+ }{
+ {
+ label: "Key doesn't exist",
+ mockEtcd: &MockEtcdClient{},
+ expectedError: "Key doesn't exist",
+ },
+ {
+ label: "Error getting etcd entry",
+ mockEtcd: &MockEtcdClient{Err: pkgerrors.New("DB Error")},
+ expectedError: "Error getting etcd entry: DB Error",
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.label, func(t *testing.T) {
+ cli, _ := NewEtcdClient(&clientv3.Client{}, EtcdConfig{})
+ getEtcd = func(e *EtcdClient) Etcd {
+ return testCase.mockEtcd
+ }
+ _, err := cli.GetAllKeys("test")
+ if err != nil {
+ if testCase.expectedError == "" {
+ t.Fatalf("Method returned an un-expected (%s)", err)
+ }
+ if !strings.Contains(string(err.Error()), testCase.expectedError) {
+ t.Fatalf("Method returned an error (%s)", err)
+ }
+ }
+ })
+ }
+}
diff --git a/src/orchestrator/pkg/infra/contextdb/mock.go b/src/orchestrator/pkg/infra/contextdb/mock.go
new file mode 100644
index 00000000..fc0f8ff7
--- /dev/null
+++ b/src/orchestrator/pkg/infra/contextdb/mock.go
@@ -0,0 +1,58 @@
+/*
+Copyright 2020 Intel Corporation.
+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 contextdb
+
+import (
+ pkgerrors "github.com/pkg/errors"
+)
+
+type MockEtcd struct {
+ Items map[string]interface{}
+ Err error
+}
+
+func (c *MockEtcd) Put(key string, value interface{}) error {
+ if c.Items == nil {
+ c.Items = make(map[string]interface{})
+ }
+ c.Items[key] = value
+ return c.Err
+}
+
+func (c *MockEtcd) Get(key string, value interface{}) error {
+ for kvKey, kvValue := range c.Items {
+ if kvKey == key {
+ value = kvValue
+ return nil
+ }
+ }
+ return pkgerrors.Errorf("Key doesn't exist")
+}
+
+func (c *MockEtcd) Delete(key string) error {
+ delete(c.Items, key)
+ return c.Err
+}
+
+func (c *MockEtcd) GetAllKeys(path string) ([]string, error) {
+ var keys []string
+ for k, _ := range c.Items {
+ keys = append(keys, string(k))
+ }
+ return keys, nil
+}
+
+func (e *MockEtcd) HealthCheck() error {
+ return nil
+}
diff --git a/src/orchestrator/internal/db/README.md b/src/orchestrator/pkg/infra/db/README.md
index cba1b7ea..cba1b7ea 100644
--- a/src/orchestrator/internal/db/README.md
+++ b/src/orchestrator/pkg/infra/db/README.md
diff --git a/src/orchestrator/internal/db/mock.go b/src/orchestrator/pkg/infra/db/mock.go
index 1dbca4b4..1dbca4b4 100644
--- a/src/orchestrator/internal/db/mock.go
+++ b/src/orchestrator/pkg/infra/db/mock.go
diff --git a/src/orchestrator/internal/db/mongo.go b/src/orchestrator/pkg/infra/db/mongo.go
index 3720a4f2..32d0b549 100644
--- a/src/orchestrator/internal/db/mongo.go
+++ b/src/orchestrator/pkg/infra/db/mongo.go
@@ -21,7 +21,7 @@ import (
"golang.org/x/net/context"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/config"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/config"
pkgerrors "github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
diff --git a/src/orchestrator/internal/db/mongo_test.go b/src/orchestrator/pkg/infra/db/mongo_test.go
index 171c908f..171c908f 100644
--- a/src/orchestrator/internal/db/mongo_test.go
+++ b/src/orchestrator/pkg/infra/db/mongo_test.go
diff --git a/src/orchestrator/internal/db/store.go b/src/orchestrator/pkg/infra/db/store.go
index ed394205..1a9632e7 100644
--- a/src/orchestrator/internal/db/store.go
+++ b/src/orchestrator/pkg/infra/db/store.go
@@ -17,7 +17,7 @@ import (
"encoding/json"
"reflect"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/config"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/config"
pkgerrors "github.com/pkg/errors"
)
diff --git a/src/orchestrator/internal/db/store_test.go b/src/orchestrator/pkg/infra/db/store_test.go
index 42a41787..42a41787 100644
--- a/src/orchestrator/internal/db/store_test.go
+++ b/src/orchestrator/pkg/infra/db/store_test.go
diff --git a/src/orchestrator/internal/logutils/logger.go b/src/orchestrator/pkg/infra/logutils/logger.go
index 2e8f9969..2e8f9969 100644
--- a/src/orchestrator/internal/logutils/logger.go
+++ b/src/orchestrator/pkg/infra/logutils/logger.go
diff --git a/src/orchestrator/pkg/module/module.go b/src/orchestrator/pkg/module/module.go
new file mode 100644
index 00000000..e4482098
--- /dev/null
+++ b/src/orchestrator/pkg/module/module.go
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 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 module
+
+import (
+ )
+
+// Client for using the services in the orchestrator
+type Client struct {
+ Project *ProjectClient
+ // Add Clients for API's here
+}
+
+// NewClient creates a new client for using the services
+func NewClient() *Client {
+ c:= &Client{}
+ c.Project = NewProjectClient()
+ // Add Client API handlers here
+ return c
+} \ No newline at end of file
diff --git a/src/orchestrator/internal/project/project.go b/src/orchestrator/pkg/module/project.go
index f0c50065..e44164f9 100644
--- a/src/orchestrator/internal/project/project.go
+++ b/src/orchestrator/pkg/module/project.go
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package project
+package module
import (
"encoding/json"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/db"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
pkgerrors "github.com/pkg/errors"
)
@@ -47,14 +47,14 @@ func (pk ProjectKey) String() string {
return string(out)
}
-// ProjectManager is an interface exposes the Project functionality
+// Manager is an interface exposes the Project functionality
type ProjectManager interface {
- Create(pr Project) (Project, error)
- Get(name string) (Project, error)
- Delete(name string) error
+ CreateProject(pr Project) (Project, error)
+ GetProject(name string) (Project, error)
+ DeleteProject(name string) error
}
-// ProjectClient implements the ProjectManager
+// ProjectClient implements the Manager
// It will also be used to maintain some localized state
type ProjectClient struct {
storeName string
@@ -62,15 +62,15 @@ type ProjectClient struct {
}
// NewProjectClient returns an instance of the ProjectClient
-// which implements the ProjectManager
+// which implements the Manager
func NewProjectClient() *ProjectClient {
return &ProjectClient{
tagMeta: "projectmetadata",
}
}
-// Create a new collection based on the project
-func (v *ProjectClient) Create(p Project) (Project, error) {
+// CreateProject a new collection based on the project
+func (v *ProjectClient) CreateProject(p Project) (Project, error) {
//Construct the composite key to select the entry
key := ProjectKey{
@@ -78,7 +78,7 @@ func (v *ProjectClient) Create(p Project) (Project, error) {
}
//Check if this Project already exists
- _, err := v.Get(p.ProjectName)
+ _, err := v.GetProject(p.ProjectName)
if err == nil {
return Project{}, pkgerrors.New("Project already exists")
}
@@ -91,8 +91,8 @@ func (v *ProjectClient) Create(p Project) (Project, error) {
return p, nil
}
-// Get returns the Project for corresponding name
-func (v *ProjectClient) Get(name string) (Project, error) {
+// GetProject returns the Project for corresponding name
+func (v *ProjectClient) GetProject(name string) (Project, error) {
//Construct the composite key to select the entry
key := ProjectKey{
@@ -116,8 +116,8 @@ func (v *ProjectClient) Get(name string) (Project, error) {
return Project{}, pkgerrors.New("Error getting Project")
}
-// Delete the Project from database
-func (v *ProjectClient) Delete(name string) error {
+// DeleteProject the Project from database
+func (v *ProjectClient) DeleteProject(name string) error {
//Construct the composite key to select the entry
key := ProjectKey{
diff --git a/src/orchestrator/internal/project/project_test.go b/src/orchestrator/pkg/module/project_test.go
index cc691e33..7f4d9b3e 100644
--- a/src/orchestrator/internal/project/project_test.go
+++ b/src/orchestrator/pkg/module/project_test.go
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package project
+package module
import (
"reflect"
"strings"
"testing"
- "github.com/onap/multicloud-k8s/src/orchestrator/internal/db"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
pkgerrors "github.com/pkg/errors"
)
@@ -60,7 +60,7 @@ func TestCreateProject(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
db.DBconn = testCase.mockdb
impl := NewProjectClient()
- got, err := impl.Create(testCase.inp)
+ got, err := impl.CreateProject(testCase.inp)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Create returned an unexpected error %s", err)
@@ -119,7 +119,7 @@ func TestGetProject(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
db.DBconn = testCase.mockdb
impl := NewProjectClient()
- got, err := impl.Get(testCase.name)
+ got, err := impl.GetProject(testCase.name)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Get returned an unexpected error: %s", err)
@@ -163,7 +163,7 @@ func TestDeleteProject(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
db.DBconn = testCase.mockdb
impl := NewProjectClient()
- err := impl.Delete(testCase.name)
+ err := impl.DeleteProject(testCase.name)
if err != nil {
if testCase.expectedError == "" {
t.Fatalf("Delete returned an unexpected error %s", err)