summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShashank Kumar Shankar <shashank.kumar.shankar@intel.com>2018-02-15 14:48:19 -0800
committerShashank Kumar Shankar <shashank.kumar.shankar@intel.com>2018-02-21 13:51:08 -0800
commit3e92cb38f9be554afccf7ac409dfbedbeec769a2 (patch)
treeb09247734194975c161987e06d7e1aa0abf8ae24
parent88a7fd4b899bbd1230852be63e380ce843dec338 (diff)
Update tests and refactor code
This patch adds some more tests and refactors the codebase. Change-Id: Iee669b85c5c7f9bdd01271fe86df20506f567d23 Issue-ID: MUSIC-23 Signed-off-by: Shashank Kumar Shankar <shashank.kumar.shankar@intel.com>
-rw-r--r--src/dkv/Gopkg.lock8
-rw-r--r--src/dkv/api/consulConnection.go107
-rw-r--r--src/dkv/api/consulConnection_test.go2
-rw-r--r--src/dkv/api/endpointViews.go59
-rw-r--r--src/dkv/api/endpointViews_fake.go96
-rw-r--r--src/dkv/api/endpointViews_test.go182
-rw-r--r--src/dkv/api/initialise.go27
-rw-r--r--src/dkv/api/initialise_test.go (renamed from src/dkv/api/utils_test.go)25
-rw-r--r--src/dkv/api/propertiesReader.go84
-rw-r--r--src/dkv/api/utils.go101
-rw-r--r--src/dkv/main.go11
-rw-r--r--swagger.json24
12 files changed, 533 insertions, 193 deletions
diff --git a/src/dkv/Gopkg.lock b/src/dkv/Gopkg.lock
index 33c42f6..97abfee 100644
--- a/src/dkv/Gopkg.lock
+++ b/src/dkv/Gopkg.lock
@@ -14,6 +14,12 @@
version = "v1.1"
[[projects]]
+ name = "github.com/gorilla/handlers"
+ packages = ["."]
+ revision = "90663712d74cb411cbef281bc1e08c19d1a76145"
+ version = "v1.3.0"
+
+[[projects]]
name = "github.com/gorilla/mux"
packages = ["."]
revision = "53c1911da2b537f792e7cafcb446b05ffe33b996"
@@ -70,6 +76,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "b980f85326f4b80746ec5b571cb1d39ebd88faba4028d4000bb84775aef0470f"
+ inputs-digest = "da4b4bdf45858b18ffddcdd32894f4af272104c2501a5334bf1d01abfa6d9a23"
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/src/dkv/api/consulConnection.go b/src/dkv/api/consulConnection.go
index b8074e2..5ea79fd 100644
--- a/src/dkv/api/consulConnection.go
+++ b/src/dkv/api/consulConnection.go
@@ -18,55 +18,66 @@ package api
import (
"errors"
- "fmt"
- "github.com/hashicorp/consul/api"
+ consulapi "github.com/hashicorp/consul/api"
"os"
)
-func (kvStruct *KeyValue) WriteKVsToConsul() error {
- for key, value := range kvStruct.kv {
- if os.Getenv("CONSUL_IP") == "" {
- return errors.New("CONSUL_IP environment variable not set.")
- }
- err := requestPUT(os.Getenv("CONSUL_IP"), key, value)
- if err != nil {
- return err
- }
- fmt.Println("key:", key, "value", value)
- }
- fmt.Println("Wrote KVs to Consul")
- return nil
+// Interface to have all signature methods.
+type ConsulRequester interface {
+ InitializeConsulClient() error
+ CheckConsulHealth() error
+ RequestPUT(string, string) error
+ RequestGET(string) (string, error)
+ RequestGETS() ([]string, error)
+ RequestDELETE(string) error
}
-func GetKVFromConsul(key string) (string, error) {
- if os.Getenv("CONSUL_IP") == "" {
- return "", errors.New("CONSUL_IP environment variable not set.")
- }
- resp, err := requestGET(os.Getenv("CONSUL_IP"), key)
- return resp, err
+type ConsulStruct struct {
+ consulClient *consulapi.Client
}
-func GetKVsFromConsul() ([]string, error) {
- if os.Getenv("CONSUL_IP") == "" {
- return []string{""}, errors.New("CONSUL_IP environment variable not set.")
+/*
+This var is an interface used to initialize ConsulStruct when the who API is brought up. This is done this way so
+that a fake Consul can be created which satisfies the interface and we can use that fake Consul in unit testing.
+*/
+var Consul ConsulRequester
+
+/*
+The following functions seems like they are not used. But since they are following the ConsulRequest interface,
+they can be visible to any Struct which is initiated using the ConsulRequest. This is done for this project in
+the initialise.go file where we are creating a ConsulStruct and assigning it to Consul var which is declared
+above.
+*/
+func (c *ConsulStruct) InitializeConsulClient() error {
+ config := consulapi.DefaultConfig()
+ config.Address = os.Getenv("CONSUL_IP") + ":8500"
+
+ client, err := consulapi.NewClient(config)
+ if err != nil {
+ return err
}
- resp, err := requestGETS(os.Getenv("CONSUL_IP"))
- return resp, err
-}
+ c.consulClient = client
-func requestPUT(url string, key string, value string) error {
- config := api.DefaultConfig()
- config.Address = url + ":8500"
- client, err := api.NewClient(config)
+ return nil
+}
+func (c *ConsulStruct) CheckConsulHealth() error {
+ kv := c.consulClient.KV()
+ _, _, err := kv.Get("test", nil)
if err != nil {
- return err
+ return errors.New("[ERROR] Cannot talk to Consul. Check if it is running/reachable.")
}
+ return nil
+}
+
+func (c *ConsulStruct) RequestPUT(key string, value string) error {
+
+ kv := c.consulClient.KV()
+
+ p := &consulapi.KVPair{Key: key, Value: []byte(value)}
- kv := client.KV()
+ _, err := kv.Put(p, nil)
- p := &api.KVPair{Key: key, Value: []byte(value)}
- _, err = kv.Put(p, nil)
if err != nil {
return err
}
@@ -74,12 +85,9 @@ func requestPUT(url string, key string, value string) error {
return nil
}
-func requestGET(url string, key string) (string, error) {
- config := api.DefaultConfig()
- config.Address = url + ":8500"
- client, err := api.NewClient(config)
+func (c *ConsulStruct) RequestGET(key string) (string, error) {
- kv := client.KV()
+ kv := c.consulClient.KV()
pair, _, err := kv.Get(key, nil)
@@ -90,12 +98,9 @@ func requestGET(url string, key string) (string, error) {
}
-func requestGETS(url string) ([]string, error) {
- config := api.DefaultConfig()
- config.Address = url + ":8500"
- client, err := api.NewClient(config)
+func (c *ConsulStruct) RequestGETS() ([]string, error) {
- kv := client.KV()
+ kv := c.consulClient.KV()
pairs, _, err := kv.List("", nil)
@@ -111,3 +116,15 @@ func requestGETS(url string) ([]string, error) {
return res, err
}
+
+func (c *ConsulStruct) RequestDELETE(key string) error {
+ kv := c.consulClient.KV()
+
+ _, err := kv.Delete(key, nil)
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/src/dkv/api/consulConnection_test.go b/src/dkv/api/consulConnection_test.go
index 342542a..cc973ce 100644
--- a/src/dkv/api/consulConnection_test.go
+++ b/src/dkv/api/consulConnection_test.go
@@ -15,5 +15,3 @@
*/
package api
-
-// TODO(sshank)
diff --git a/src/dkv/api/endpointViews.go b/src/dkv/api/endpointViews.go
index 3c47ee5..7d19a6a 100644
--- a/src/dkv/api/endpointViews.go
+++ b/src/dkv/api/endpointViews.go
@@ -18,15 +18,44 @@ package api
import (
"encoding/json"
+ "errors"
"github.com/gorilla/mux"
"net/http"
)
-var getkvs = GetKVsFromConsul
+type ResponseStringStruct struct {
+ Response string `json:"response"`
+}
+
+type ResponseGETStruct struct {
+ Response map[string]string `json:"response"`
+}
+
+type ResponseGETSStruct struct {
+ Response []string `json:"response"`
+}
+
+type POSTBodyStruct struct {
+ Type *TypeStruct `json:"type"`
+}
+
+type TypeStruct struct {
+ FilePath string `json:"file_path"`
+}
+
+func ValidateBody(body POSTBodyStruct) error {
+ if body.Type == nil {
+ return errors.New("Type not set. Recheck POST data.")
+ } else if body.Type.FilePath == "" {
+ return errors.New("file_path not set")
+ } else {
+ return nil
+ }
+}
func HandlePOST(w http.ResponseWriter, r *http.Request) {
- var body LoadStruct
+ var body POSTBodyStruct
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&body)
@@ -49,7 +78,7 @@ func HandlePOST(w http.ResponseWriter, r *http.Request) {
return
}
- err = KVStruct.ReadConfigs(body)
+ err = KeyValues.ReadConfigs(body)
if err != nil {
req := ResponseStringStruct{Response: string(err.Error())}
@@ -59,7 +88,7 @@ func HandlePOST(w http.ResponseWriter, r *http.Request) {
return
}
- err = KVStruct.WriteKVsToConsul()
+ err = KeyValues.WriteKVsToConsul()
if err != nil {
req := ResponseStringStruct{Response: string(err.Error())}
@@ -77,7 +106,7 @@ func HandleGET(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
key := vars["key"]
- value, err := GetKVFromConsul(key)
+ value, err := Consul.RequestGET(key)
if err != nil {
req := ResponseStringStruct{Response: string(err.Error())}
@@ -93,7 +122,7 @@ func HandleGET(w http.ResponseWriter, r *http.Request) {
func HandleGETS(w http.ResponseWriter, r *http.Request) {
- values, err := getkvs()
+ values, err := Consul.RequestGETS()
if err != nil {
req := ResponseStringStruct{Response: string(err.Error())}
@@ -106,3 +135,21 @@ func HandleGETS(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(req)
}
}
+
+func HandleDELETE(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ key := vars["key"]
+
+ err := Consul.RequestDELETE(key)
+
+ if err != nil {
+ req := ResponseStringStruct{Response: string(err.Error())}
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(req)
+ } else {
+ req := ResponseStringStruct{Response: "Key deletion successful."}
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(&req)
+ }
+}
diff --git a/src/dkv/api/endpointViews_fake.go b/src/dkv/api/endpointViews_fake.go
new file mode 100644
index 0000000..c147673
--- /dev/null
+++ b/src/dkv/api/endpointViews_fake.go
@@ -0,0 +1,96 @@
+/*
+ * 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 api
+
+import "errors"
+
+/*
+A ConsulStruct is added inside this so that FakeConsul becomes an implementation of the Consul interface.
+If we don't add ConsulStruct inside this, it complains that the FakeConsul Struct doesn't implement all the methods
+defined in Consul interface.
+*/
+// Correct
+type FakeConsul struct {
+ ConsulStruct
+}
+
+func (f *FakeConsul) RequestGETS() ([]string, error) {
+ return []string{"key1", "key2"}, nil
+}
+
+func (f *FakeConsul) RequestGET(key string) (string, error) {
+ return key, nil
+}
+
+func (f *FakeConsul) RequestPUT(key string, value string) error {
+ return nil
+}
+
+func (f *FakeConsul) RequestDELETE(key string) error {
+ return nil
+}
+
+// Error
+type FakeConsulErr struct {
+ ConsulStruct
+}
+
+func (f *FakeConsulErr) RequestGETS() ([]string, error) {
+ return []string{"", ""}, errors.New("Internal Server Error")
+}
+
+func (f *FakeConsulErr) RequestGET(key string) (string, error) {
+ return "", errors.New("Internal Server Error")
+}
+
+func (f *FakeConsulErr) RequestPUT(key string, value string) error {
+ return errors.New("Internal Server Error")
+}
+
+func (f *FakeConsulErr) RequestDELETE(key string) error {
+ return errors.New("Internal Server Error")
+}
+
+/*
+This is done similar to the fake Consul above to pass FakeKeyValues to the interface and control method's outputs
+as required.
+*/
+//Correct
+type FakeKeyValues struct {
+ KeyValuesStruct
+}
+
+func (f *FakeKeyValues) ReadConfigs(body POSTBodyStruct) error {
+ return nil
+}
+
+func (f *FakeKeyValues) WriteKVsToConsul() error {
+ return nil
+}
+
+// Error
+type FakeKeyValuesErr struct {
+ KeyValuesStruct
+}
+
+func (f *FakeKeyValuesErr) ReadConfigs(body POSTBodyStruct) error {
+ return errors.New("Internal Server Error")
+}
+
+func (f *FakeKeyValuesErr) WriteKVsToConsul() error {
+ return errors.New("Internal Server Error")
+}
diff --git a/src/dkv/api/endpointViews_test.go b/src/dkv/api/endpointViews_test.go
index f603af4..1f7abf3 100644
--- a/src/dkv/api/endpointViews_test.go
+++ b/src/dkv/api/endpointViews_test.go
@@ -17,7 +17,8 @@
package api
import (
- //"encoding/json"
+ "bytes"
+ "encoding/json"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"net/http"
@@ -27,32 +28,185 @@ import (
func Router() *mux.Router {
router := mux.NewRouter()
- router.HandleFunc("/getconfigs", HandleGETS).Methods("GET")
router.HandleFunc("/loadconfigs", HandlePOST).Methods("POST")
+ router.HandleFunc("/getconfig/{key}", HandleGET).Methods("GET")
+ router.HandleFunc("/deleteconfig/{key}", HandleDELETE).Methods("DELETE")
+ router.HandleFunc("/getconfigs", HandleGETS).Methods("GET")
return router
}
-func TestHandlePOST(t *testing.T) {
- // TODO(sshank)
- assert.Equal(t, 0, 0, "Not passed.")
+func TestHandleGETS(t *testing.T) {
+ oldConsul := Consul
+ Consul = &FakeConsul{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("GET", "/getconfigs", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 200, response.Code, "200 response is expected")
+}
+
+func TestHandleGETS_err(t *testing.T) {
+ oldConsul := Consul
+ Consul = &FakeConsulErr{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("GET", "/getconfigs", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 400, response.Code, "400 response is expected")
}
func TestHandleGET(t *testing.T) {
- // TODO(sshank)
- assert.Equal(t, 0, 0, "Not passed.")
+ oldConsul := Consul
+ Consul = &FakeConsul{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("GET", "/getconfig/key1", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 200, response.Code, "200 response is expected")
}
-func TestHandleGETS(t *testing.T) {
- getkvOld := getkvs
- defer func() { getkvs = getkvOld }()
+func TestHandleGET_err(t *testing.T) {
+ oldConsul := Consul
+ Consul = &FakeConsulErr{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("GET", "/getconfig/key1", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 400, response.Code, "400 response is expected")
+}
+
+func TestHandlePOST(t *testing.T) {
+ oldConsul := Consul
+ oldKeyValues := KeyValues
+
+ Consul = &FakeConsul{}
+ KeyValues = &FakeKeyValues{}
- getkvs = func() ([]string, error) {
- return nil, nil
+ defer func() {
+ Consul = oldConsul
+ KeyValues = oldKeyValues
+ }()
+
+ body := &POSTBodyStruct{
+ Type: &TypeStruct{
+ FilePath: "default",
+ },
}
- request, _ := http.NewRequest("GET", "/getconfigs", nil)
+ b, _ := json.Marshal(body)
+
+ // json Marshal converts struct to json in Bytes. But bytes doesn't have
+ // io reader needed. So the byte is passed to NewBuffer.
+ request, _ := http.NewRequest("POST", "/loadconfigs", bytes.NewBuffer(b))
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 200, response.Code, "200 response is expected")
+}
+
+func TestHandlePOST_no_body(t *testing.T) {
+ oldConsul := Consul
+ oldKeyValues := KeyValues
+
+ Consul = &FakeConsul{}
+ KeyValues = &FakeKeyValues{}
+
+ defer func() {
+ Consul = oldConsul
+ KeyValues = oldKeyValues
+ }()
+
+ body := &POSTBodyStruct{}
+
+ b, _ := json.Marshal(body)
+
+ request, _ := http.NewRequest("POST", "/loadconfigs", bytes.NewBuffer(b))
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 400, response.Code, "400 response is expected")
+}
+
+func TestHandlePOST_no_filepath(t *testing.T) {
+ oldConsul := Consul
+ oldKeyValues := KeyValues
+
+ Consul = &FakeConsul{}
+ KeyValues = &FakeKeyValues{}
+
+ defer func() {
+ Consul = oldConsul
+ KeyValues = oldKeyValues
+ }()
+
+ body := &POSTBodyStruct{
+ Type: &TypeStruct{},
+ }
+
+ b, _ := json.Marshal(body)
+
+ request, _ := http.NewRequest("POST", "/loadconfigs", bytes.NewBuffer(b))
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 400, response.Code, "400 response is expected")
+}
+
+func TestHandlePOST_ConsulError(t *testing.T) {
+ oldConsul := Consul
+ oldKeyValues := KeyValues
+
+ Consul = &FakeConsulErr{}
+ KeyValues = &FakeKeyValuesErr{}
+
+ defer func() {
+ Consul = oldConsul
+ KeyValues = oldKeyValues
+ }()
+
+ body := &POSTBodyStruct{
+ Type: &TypeStruct{
+ FilePath: "default",
+ },
+ }
+
+ b, _ := json.Marshal(body)
+
+ request, _ := http.NewRequest("POST", "/loadconfigs", bytes.NewBuffer(b))
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 500, response.Code, "500 response is expected")
+}
+
+func TestHandleDELETE(t *testing.T) {
+ oldConsul := Consul
+ Consul = &FakeConsul{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("DELETE", "/deleteconfig/key1", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 200, response.Code, "200 response is expected")
+}
+
+func TestHandleDELETE_err(t *testing.T) {
+ oldConsul := Consul
+ Consul = &FakeConsulErr{}
+ defer func() { Consul = oldConsul }()
+
+ request, _ := http.NewRequest("DELETE", "/deleteconfig/key1", nil)
response := httptest.NewRecorder()
Router().ServeHTTP(response, request)
- assert.Equal(t, 200, response.Code, "OK response is expected")
+ assert.Equal(t, 400, response.Code, "400 response is expected")
}
diff --git a/src/dkv/api/initialise.go b/src/dkv/api/initialise.go
new file mode 100644
index 0000000..f85c146
--- /dev/null
+++ b/src/dkv/api/initialise.go
@@ -0,0 +1,27 @@
+package api
+
+import (
+ "errors"
+ "os"
+)
+
+func Initialise() error {
+ if os.Getenv("CONSUL_IP") == "" {
+ return errors.New("CONSUL_IP environment variable not set.")
+ }
+
+ Consul = &ConsulStruct{}
+ KeyValues = &KeyValuesStruct{kvs: make(map[string]string)}
+
+ err := Consul.InitializeConsulClient()
+ if err != nil {
+ return err
+ }
+
+ err = Consul.CheckConsulHealth()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/src/dkv/api/utils_test.go b/src/dkv/api/initialise_test.go
index 342542a..3063201 100644
--- a/src/dkv/api/utils_test.go
+++ b/src/dkv/api/initialise_test.go
@@ -16,4 +16,27 @@
package api
-// TODO(sshank)
+import (
+ "github.com/stretchr/testify/assert"
+ "os"
+ "testing"
+)
+
+func TestInitialise_errorIP(t *testing.T) {
+ consul_ip := os.Getenv("CONSUL_IP")
+ os.Unsetenv("CONSUL_IP")
+ defer os.Setenv("CONSUL_IP", consul_ip)
+
+ err := Initialise()
+ assert.NotNil(t, err)
+}
+
+func TestInitialise_errorConsul(t *testing.T) {
+ // This is done this way cause the Consul interface with Fake Struct will get
+ // overridden with real Struct during runtime.
+ os.Setenv("CONSUL_IP", "test")
+ defer os.Unsetenv("CONSUL_IP")
+
+ err := Initialise()
+ assert.NotNil(t, err)
+}
diff --git a/src/dkv/api/propertiesReader.go b/src/dkv/api/propertiesReader.go
index 018dabe..a1c94bb 100644
--- a/src/dkv/api/propertiesReader.go
+++ b/src/dkv/api/propertiesReader.go
@@ -20,54 +20,94 @@ import (
"errors"
"github.com/magiconair/properties"
"io/ioutil"
+ "log"
"path"
"runtime"
+ "sync"
)
-func PropertiesFilesToKV(directory string) (map[string]string, error) {
- if directory == "default" {
- kvs := make(map[string]string)
+type KeyValuesInterface interface {
+ WriteKVsToConsul() error
+ ReadConfigs(POSTBodyStruct) error
+ PropertiesFilesToKV(string) error
+ ReadMultipleProperties(string) error
+ ReadProperty(string)
+}
- _, filename, _, ok := runtime.Caller(0)
+type KeyValuesStruct struct {
+ sync.RWMutex
+ kvs map[string]string
+}
+
+var KeyValues KeyValuesInterface
+func (kvStruct *KeyValuesStruct) WriteKVsToConsul() error {
+ for key, value := range kvStruct.kvs {
+ err := Consul.RequestPUT(key, value)
+ if err != nil {
+ return err
+ }
+ log.Println("[INFO] Key: ", key, "| Value: ", value)
+ }
+ log.Println("[INFO] Wrote KVs to Consul.")
+ return nil
+}
+
+func (kvStruct *KeyValuesStruct) ReadConfigs(body POSTBodyStruct) error {
+ defer kvStruct.Unlock()
+
+ kvStruct.Lock()
+
+ err := kvStruct.PropertiesFilesToKV(body.Type.FilePath)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (kvStruct *KeyValuesStruct) PropertiesFilesToKV(directory string) error {
+
+ if directory == "default" {
+ _, filename, _, ok := runtime.Caller(0)
if !ok {
- return nil, errors.New("No caller")
+ return errors.New("No caller")
}
- configDir := path.Dir(filename) + "/../configurations/"
- err := ReadMultipleProperties(configDir, kvs)
+ defaultDir := path.Dir(filename) + "/../configurations/"
+ err := kvStruct.ReadMultipleProperties(defaultDir)
if err != nil {
- return nil, err
+ return err
}
- return kvs, nil
+
+ return nil
+
} else {
- // Add case if directory is not there.
- kvs := make(map[string]string)
directory += "/"
- err := ReadMultipleProperties(directory, kvs)
+ err := kvStruct.ReadMultipleProperties(directory)
if err != nil {
- return nil, err
+ return err
}
- return kvs, nil
- }
-}
-func ReadProperty(path string, kvs map[string]string) {
- p := properties.MustLoadFile(path, properties.UTF8)
- for _, key := range p.Keys() {
- kvs[key] = p.MustGet(key)
+ return nil
}
}
-func ReadMultipleProperties(path string, kvs map[string]string) error {
+func (kvStruct *KeyValuesStruct) ReadMultipleProperties(path string) error {
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, f := range files {
- ReadProperty(path+f.Name(), kvs)
+ kvStruct.ReadProperty(path + f.Name())
}
return nil
}
+
+func (kvStruct *KeyValuesStruct) ReadProperty(path string) {
+ p := properties.MustLoadFile(path, properties.UTF8)
+ for _, key := range p.Keys() {
+ kvStruct.kvs[key] = p.MustGet(key)
+ }
+}
diff --git a/src/dkv/api/utils.go b/src/dkv/api/utils.go
deleted file mode 100644
index 8b87848..0000000
--- a/src/dkv/api/utils.go
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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 api
-
-import (
- "errors"
- "sync"
-)
-
-type KeyValue struct {
- sync.RWMutex
- kv map[string]string
-}
-
-type ResponseStringStruct struct {
- Response string `json:"response"`
-}
-
-type ResponseGETStruct struct {
- Response map[string]string `json:"response"`
-}
-
-type ResponseGETSStruct struct {
- Response []string `json:"response"`
-}
-
-type LoadStruct struct {
- Type *TypeStruct `json:"type"`
-}
-
-type TypeStruct struct {
- FilePath string `json:"file_path"`
-}
-
-var KVStruct = &KeyValue{kv: make(map[string]string)}
-
-func (kvStruct *KeyValue) ReadConfigs(body LoadStruct) error {
- if body.Type.FilePath == "default" {
- err := kvStruct.FileReader("default")
- if err != nil {
- return err
- }
- return nil
- } else {
- err := kvStruct.FileReader(body.Type.FilePath)
- if err != nil {
- return err
- }
- return nil
- }
-}
-
-func (kvStruct *KeyValue) FileReader(directory string) error {
- defer kvStruct.Unlock()
-
- kvStruct.Lock()
-
- if directory == "default" {
- propertiesValues, err := PropertiesFilesToKV("default")
- if err != nil {
- return err
- }
- for key, value := range propertiesValues {
- kvStruct.kv[key] = value
- }
- return nil
- } else {
- propertiesValues, err := PropertiesFilesToKV(directory)
- if err != nil {
- return err
- }
- for key, value := range propertiesValues {
- kvStruct.kv[key] = value
- }
- return nil
- }
-}
-
-func ValidateBody(body LoadStruct) error {
- if body.Type == nil {
- return errors.New("Type not set. Recheck POST data.")
- } else if body.Type.FilePath == "" {
- return errors.New("file_path not set")
- } else {
- return nil
- }
-}
diff --git a/src/dkv/main.go b/src/dkv/main.go
index 5d0c5b6..8b4850f 100644
--- a/src/dkv/main.go
+++ b/src/dkv/main.go
@@ -18,15 +18,24 @@ package main
import (
"dkv/api"
+ "github.com/gorilla/handlers"
"github.com/gorilla/mux"
"log"
"net/http"
+ "os"
)
func main() {
+ err := api.Initialise()
+ if err != nil {
+ log.Fatal(err)
+ }
router := mux.NewRouter()
router.HandleFunc("/loadconfigs", api.HandlePOST).Methods("POST")
router.HandleFunc("/getconfig/{key}", api.HandleGET).Methods("GET")
+ router.HandleFunc("/deleteconfig/{key}", api.HandleDELETE).Methods("DELETE")
router.HandleFunc("/getconfigs", api.HandleGETS).Methods("GET")
- log.Fatal(http.ListenAndServe(":8080", router))
+ loggedRouter := handlers.LoggingHandler(os.Stdout, router)
+ log.Println("[INFO] Started Distributed KV Store server.")
+ log.Fatal(http.ListenAndServe(":8080", loggedRouter))
}
diff --git a/swagger.json b/swagger.json
index 364bcd3..bb76c41 100644
--- a/swagger.json
+++ b/swagger.json
@@ -67,6 +67,25 @@ paths:
description: "successful operation"
schema:
$ref: "#/definitions/Get"
+ /deleteconfig/{key}:
+ delete:
+ tags:
+ - "delete single key"
+ summary: "Delete value for specific key present in Consul."
+ description: "Deletes a specific key."
+ produces:
+ - "application/json"
+ parameters:
+ - name: "key"
+ in: "path"
+ description: "Key used to delete"
+ required: true
+ type: "string"
+ responses:
+ 200:
+ description: "successful operation"
+ schema:
+ $ref: "#/definitions/Delete"
definitions:
LoadRequest:
type: "object"
@@ -94,3 +113,8 @@ definitions:
properties:
response:
type: "string"
+ Delete:
+ type: "object"
+ properties:
+ response:
+ type: "string"