summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShashank Kumar Shankar <shashank.kumar.shankar@intel.com>2018-02-07 17:50:55 -0800
committerShashank Kumar Shankar <shashank.kumar.shankar@intel.com>2018-02-07 17:53:10 -0800
commitbe355e888af5b332797aee7507fdd6ed93261d6d (patch)
tree000a31f76ed163d596ca91bce0e4aaf734efc314
parent15bfff9d8227b7fd175e6bfd1d54ecd0352caca6 (diff)
Initial seed code for distributed KV store
This patch includes the initial seed code for KV store. Subsequent patches will include documentation, API ref and unit tests. Change-Id: I6296215b6b796400947ba925a2d8c46380e16992 Issue-ID: MUSIC-23 Signed-off-by: Shashank Kumar Shankar <shashank.kumar.shankar@intel.com>
-rw-r--r--.gitignore5
-rw-r--r--.gitreview4
-rw-r--r--Gopkg.lock75
-rw-r--r--Gopkg.toml42
-rw-r--r--README.md4
-rw-r--r--api/consulConnection.go113
-rw-r--r--api/consulConnection_test.go19
-rw-r--r--api/endpointViews.go108
-rw-r--r--api/endpointViews_test.go58
-rw-r--r--api/propertiesReader.go73
-rw-r--r--api/propertiesReader_test.go19
-rw-r--r--api/utils.go101
-rw-r--r--api/utils_test.go19
-rw-r--r--configurations/sampleAAIConfig.properties94
-rw-r--r--configurations/sampleAPPCConfig.properties113
-rw-r--r--main.go32
16 files changed, 879 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..879e9b6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.idea/
+*.iml
+consul
+.DS_Store
+vendor/
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..dd44c66
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,4 @@
+[gerrit]
+host=gerrit.onap.org
+port=29418
+project=music/distributed-kv-store.git
diff --git a/Gopkg.lock b/Gopkg.lock
new file mode 100644
index 0000000..33c42f6
--- /dev/null
+++ b/Gopkg.lock
@@ -0,0 +1,75 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ name = "github.com/davecgh/go-spew"
+ packages = ["spew"]
+ revision = "346938d642f2ec3594ed81d874461961cd0faa76"
+ version = "v1.1.0"
+
+[[projects]]
+ name = "github.com/gorilla/context"
+ packages = ["."]
+ revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a"
+ version = "v1.1"
+
+[[projects]]
+ name = "github.com/gorilla/mux"
+ packages = ["."]
+ revision = "53c1911da2b537f792e7cafcb446b05ffe33b996"
+ version = "v1.6.1"
+
+[[projects]]
+ name = "github.com/hashicorp/consul"
+ packages = ["api"]
+ revision = "48f3dd5642374d079f5a64359023fb8318eb81cc"
+ version = "v1.0.3"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/hashicorp/go-cleanhttp"
+ packages = ["."]
+ revision = "d5fe4b57a186c716b0e00b8c301cbd9b4182694d"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/hashicorp/go-rootcerts"
+ packages = ["."]
+ revision = "6bb64b370b90e7ef1fa532be9e591a81c3493e00"
+
+[[projects]]
+ name = "github.com/hashicorp/serf"
+ packages = ["coordinate"]
+ revision = "d6574a5bb1226678d7010325fb6c985db20ee458"
+ version = "v0.8.1"
+
+[[projects]]
+ name = "github.com/magiconair/properties"
+ packages = ["."]
+ revision = "d419a98cdbed11a922bf76f257b7c4be79b50e73"
+ version = "v1.7.4"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/mitchellh/go-homedir"
+ packages = ["."]
+ revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
+
+[[projects]]
+ name = "github.com/pmezard/go-difflib"
+ packages = ["difflib"]
+ revision = "792786c7400a136282c1664665ae0a8db921c6c2"
+ version = "v1.0.0"
+
+[[projects]]
+ name = "github.com/stretchr/testify"
+ packages = ["assert"]
+ revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
+ version = "v1.2.1"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "b980f85326f4b80746ec5b571cb1d39ebd88faba4028d4000bb84775aef0470f"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
new file mode 100644
index 0000000..3f608e7
--- /dev/null
+++ b/Gopkg.toml
@@ -0,0 +1,42 @@
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+#
+# [prune]
+# non-go = false
+# go-tests = true
+# unused-packages = true
+
+
+[[constraint]]
+ name = "github.com/gorilla/mux"
+ version = "1.6.1"
+
+[[constraint]]
+ name = "github.com/hashicorp/consul"
+ version = "1.0.3"
+
+[[constraint]]
+ name = "github.com/magiconair/properties"
+ version = "1.7.4"
+
+[prune]
+ go-tests = true
+ unused-packages = true
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0273978
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+Distributed Key Value Store using Consul to store application configuration data.
+
+# TODO
+# Add documentation on how to run.
diff --git a/api/consulConnection.go b/api/consulConnection.go
new file mode 100644
index 0000000..b8074e2
--- /dev/null
+++ b/api/consulConnection.go
@@ -0,0 +1,113 @@
+/*
+ * 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"
+ "fmt"
+ "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
+}
+
+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
+}
+
+func GetKVsFromConsul() ([]string, error) {
+ if os.Getenv("CONSUL_IP") == "" {
+ return []string{""}, errors.New("CONSUL_IP environment variable not set.")
+ }
+ resp, err := requestGETS(os.Getenv("CONSUL_IP"))
+ return resp, err
+}
+
+func requestPUT(url string, key string, value string) error {
+ config := api.DefaultConfig()
+ config.Address = url + ":8500"
+ client, err := api.NewClient(config)
+
+ if err != nil {
+ return err
+ }
+
+ kv := client.KV()
+
+ p := &api.KVPair{Key: key, Value: []byte(value)}
+ _, err = kv.Put(p, nil)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func requestGET(url string, key string) (string, error) {
+ config := api.DefaultConfig()
+ config.Address = url + ":8500"
+ client, err := api.NewClient(config)
+
+ kv := client.KV()
+
+ pair, _, err := kv.Get(key, nil)
+
+ if pair == nil {
+ return string("No value found for key."), err
+ }
+ return string(pair.Value), err
+
+}
+
+func requestGETS(url string) ([]string, error) {
+ config := api.DefaultConfig()
+ config.Address = url + ":8500"
+ client, err := api.NewClient(config)
+
+ kv := client.KV()
+
+ pairs, _, err := kv.List("", nil)
+
+ if len(pairs) == 0 {
+ return []string{"No keys found."}, err
+ }
+
+ var res []string
+
+ for _, keypair := range pairs {
+ res = append(res, keypair.Key)
+ }
+
+ return res, err
+}
diff --git a/api/consulConnection_test.go b/api/consulConnection_test.go
new file mode 100644
index 0000000..342542a
--- /dev/null
+++ b/api/consulConnection_test.go
@@ -0,0 +1,19 @@
+/*
+ * 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
+
+// TODO(sshank)
diff --git a/api/endpointViews.go b/api/endpointViews.go
new file mode 100644
index 0000000..3c47ee5
--- /dev/null
+++ b/api/endpointViews.go
@@ -0,0 +1,108 @@
+/*
+ * 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 (
+ "encoding/json"
+ "github.com/gorilla/mux"
+ "net/http"
+)
+
+var getkvs = GetKVsFromConsul
+
+func HandlePOST(w http.ResponseWriter, r *http.Request) {
+
+ var body LoadStruct
+
+ decoder := json.NewDecoder(r.Body)
+ err := decoder.Decode(&body)
+
+ if err != nil {
+ req := ResponseStringStruct{Response: "Empty body."}
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(&req)
+ return
+ }
+
+ err = ValidateBody(body)
+
+ 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)
+ return
+ }
+
+ err = KVStruct.ReadConfigs(body)
+
+ if err != nil {
+ req := ResponseStringStruct{Response: string(err.Error())}
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(req)
+ return
+ }
+
+ err = KVStruct.WriteKVsToConsul()
+
+ if err != nil {
+ req := ResponseStringStruct{Response: string(err.Error())}
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(req)
+ } else {
+ req := ResponseStringStruct{Response: "Configuration read and default Key Values loaded to Consul"}
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(&req)
+ }
+}
+
+func HandleGET(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ key := vars["key"]
+
+ value, err := GetKVFromConsul(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 := ResponseGETStruct{Response: map[string]string{key: value}}
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(req)
+ }
+}
+
+func HandleGETS(w http.ResponseWriter, r *http.Request) {
+
+ values, err := getkvs()
+
+ 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 := ResponseGETSStruct{Response: values}
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(req)
+ }
+}
diff --git a/api/endpointViews_test.go b/api/endpointViews_test.go
new file mode 100644
index 0000000..f603af4
--- /dev/null
+++ b/api/endpointViews_test.go
@@ -0,0 +1,58 @@
+/*
+ * 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 (
+ //"encoding/json"
+ "github.com/gorilla/mux"
+ "github.com/stretchr/testify/assert"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func Router() *mux.Router {
+ router := mux.NewRouter()
+ router.HandleFunc("/getconfigs", HandleGETS).Methods("GET")
+ router.HandleFunc("/loadconfigs", HandlePOST).Methods("POST")
+ return router
+}
+
+func TestHandlePOST(t *testing.T) {
+ // TODO(sshank)
+ assert.Equal(t, 0, 0, "Not passed.")
+}
+
+func TestHandleGET(t *testing.T) {
+ // TODO(sshank)
+ assert.Equal(t, 0, 0, "Not passed.")
+}
+
+func TestHandleGETS(t *testing.T) {
+ getkvOld := getkvs
+ defer func() { getkvs = getkvOld }()
+
+ getkvs = func() ([]string, error) {
+ return nil, nil
+ }
+
+ request, _ := http.NewRequest("GET", "/getconfigs", nil)
+ response := httptest.NewRecorder()
+ Router().ServeHTTP(response, request)
+
+ assert.Equal(t, 200, response.Code, "OK response is expected")
+}
diff --git a/api/propertiesReader.go b/api/propertiesReader.go
new file mode 100644
index 0000000..018dabe
--- /dev/null
+++ b/api/propertiesReader.go
@@ -0,0 +1,73 @@
+/*
+ * 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"
+ "github.com/magiconair/properties"
+ "io/ioutil"
+ "path"
+ "runtime"
+)
+
+func PropertiesFilesToKV(directory string) (map[string]string, error) {
+ if directory == "default" {
+ kvs := make(map[string]string)
+
+ _, filename, _, ok := runtime.Caller(0)
+
+ if !ok {
+ return nil, errors.New("No caller")
+ }
+
+ configDir := path.Dir(filename) + "/../configurations/"
+ err := ReadMultipleProperties(configDir, kvs)
+ if err != nil {
+ return nil, err
+ }
+ return kvs, nil
+ } else {
+ // Add case if directory is not there.
+ kvs := make(map[string]string)
+ directory += "/"
+ err := ReadMultipleProperties(directory, kvs)
+ if err != nil {
+ return nil, 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)
+ }
+}
+
+func ReadMultipleProperties(path string, kvs map[string]string) error {
+ files, err := ioutil.ReadDir(path)
+ if err != nil {
+ return err
+ }
+
+ for _, f := range files {
+ ReadProperty(path+f.Name(), kvs)
+ }
+
+ return nil
+}
diff --git a/api/propertiesReader_test.go b/api/propertiesReader_test.go
new file mode 100644
index 0000000..c564be5
--- /dev/null
+++ b/api/propertiesReader_test.go
@@ -0,0 +1,19 @@
+/*
+ * 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
+
+// TODO(sshank) \ No newline at end of file
diff --git a/api/utils.go b/api/utils.go
new file mode 100644
index 0000000..8b87848
--- /dev/null
+++ b/api/utils.go
@@ -0,0 +1,101 @@
+/*
+ * 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/api/utils_test.go b/api/utils_test.go
new file mode 100644
index 0000000..c564be5
--- /dev/null
+++ b/api/utils_test.go
@@ -0,0 +1,19 @@
+/*
+ * 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
+
+// TODO(sshank) \ No newline at end of file
diff --git a/configurations/sampleAAIConfig.properties b/configurations/sampleAAIConfig.properties
new file mode 100644
index 0000000..6052315
--- /dev/null
+++ b/configurations/sampleAAIConfig.properties
@@ -0,0 +1,94 @@
+####################################################################
+# REMEMBER TO THINK ABOUT ENVIRONMENTAL DIFFERENCES AND CHANGE THE
+# TEMPLATE AND *ALL* DATAFILES
+####################################################################
+
+aai.config.checktime=1000
+
+# this could come from siteconfig.pl?
+aai.config.nodename=AutomaticallyOverwritten
+
+
+
+aai.auth.cspcookies_on=false
+aai.dbmodel.filename=ex5.json
+
+aai.server.url.base=<%= @AAI_SERVER_URL_BASE %>
+aai.server.url=<%= @AAI_SERVER_URL %>
+aai.global.callback.url=<%= @AAI_GLOBAL_CALLBACK_URL %>
+
+aai.tools.enableBasicAuth=true
+aai.tools.username=AAI
+aai.tools.password=AAI
+
+aai.truststore.filename=<%= @AAI_TRUSTSTORE_FILENAME %>
+aai.truststore.passwd.x=<%= @AAI_TRUSTSTORE_PASSWD_X %>
+aai.keystore.filename=<%= @AAI_KEYSTORE_FILENAME %>
+aai.keystore.passwd.x=<%= @AAI_KEYSTORE_PASSWD_X %>
+
+
+aai.notification.current.version=<%= @AAI_NOTIFICATION_CURRENT_VERSION %>
+aai.notificationEvent.default.status=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_EVENT_STATUS %>
+aai.notificationEvent.default.eventType=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_EVENT_TYPE %>
+aai.notificationEvent.default.domain=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_DOMAIN %>
+aai.notificationEvent.default.sourceName=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_SOURCE_NAME %>
+aai.notificationEvent.default.sequenceNumber=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_SEQUENCE_NUMBER %>
+aai.notificationEvent.default.severity=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_SEVERITY %>
+aai.notificationEvent.default.version=<%= @AAI_NOTIFICATION_EVENT_DEFAULT_VERSION %>
+# This one lets us enable/disable resource-version checking on updates/deletes
+aai.resourceversion.enableflag=<%= @RESOURCE_VERSION_ENABLE_FLAG %>
+aai.logging.maxStackTraceEntries=10
+aai.default.api.version=<%= @AAI_DEFAULT_API_VERSION %>
+
+
+
+# Used by Model-processing code
+aai.model.delete.sleep.per.vtx.msec=500
+aai.model.query.resultset.maxcount=50
+aai.model.query.timeout.sec=90
+
+# Used by Data Grooming
+aai.grooming.default.max.file=150
+aai.grooming.default.sleep.minutes=7
+
+aai.model.proc.max.levels=50
+aai.edgeTag.proc.max.levels=50
+
+# for transaction log
+aai.logging.hbase.interceptor=true
+aai.logging.hbase.enabled=true
+aai.logging.hbase.logrequest=true
+aai.logging.hbase.logresponse=true
+
+# for gremlin server
+aai.server.rebind=g
+hbase.table.name=<%= @TXN_HBASE_TABLE_NAME %>
+hbase.table.timestamp.format=YYYYMMdd-HH:mm:ss:SSS
+hbase.zookeeper.quorum=<%= @TXN_ZOOKEEPER_QUORUM %>
+hbase.zookeeper.property.clientPort=<%= @TXN_ZOOKEEPER_PROPERTY_CLIENTPORT %>
+hbase.zookeeper.znode.parent=<%= @TXN_HBASE_ZOOKEEPER_ZNODE_PARENT %>
+
+aai.logging.trace.enabled=true
+aai.logging.trace.logrequest=false
+aai.logging.trace.logresponse=false
+
+
+aai.transaction.logging=true
+aai.transaction.logging.get=false
+aai.transaction.logging.post=false
+
+#limit set for bulk consumer APIS
+aai.bulkconsumer.payloadlimit=30
+
+#uncomment and use header X-OverrideLimit with the value to override the bulk api limit
+#aai.bulkconsumer.payloadoverride=AAI-OVERRIDE-KEY
+aai.bulkconsumer.payloadoverride=false
+
+#timeout for crud enabled flag
+aai.crud.timeoutenabled=true
+
+#timeout app specific
+aai.crud.timeout.appspecific=JUNITTESTAPP1,1|JUNITTESTAPP2,-1|DCAE-CCS,-1|DCAES,-1|AAI-FILEGEN-GFPIP,-1
+
+#default timeout limit added for traversal if not overridden (in ms)
+aai.crud.timeoutlimit=180000 \ No newline at end of file
diff --git a/configurations/sampleAPPCConfig.properties b/configurations/sampleAPPCConfig.properties
new file mode 100644
index 0000000..484337f
--- /dev/null
+++ b/configurations/sampleAPPCConfig.properties
@@ -0,0 +1,113 @@
+### ###
+### Properties for demo ###
+### ###
+appc.demo.poolMembers=10.0.11.1:3904
+appc.demo.topic.read=APPC-CL
+appc.demo.topic.write=APPC-CL
+appc.demo.client.name=appcDemoEventListener
+appc.demo.threads.queuesize.min=1
+appc.demo.threads.queuesize.max=1000
+appc.demo.threads.poolsize.min=1
+appc.demo.threads.poolsize.max=2
+appc.demo.provider.user=admin
+appc.demo.provider.pass=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+appc.demo.provider.url=http://localhost:8181/restconf/operations/appc-provider
+appc.provider.vfodl.url=http://admin:Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U@10.0.2.1:8282/restconf/config/network-topology:network-topology/topology/topology-netconf/node/NODE_NAME/yang-ext:mount/sample-plugin:sample-plugin/pg-streams/
+
+# The properties right below are needed to properly call the Master DG to serve demo purposes
+appc.service.logic.module.name=APPC
+appc.topology.dg.method=topology-operation-all
+appc.topology.dg.version=2.0.0
+
+# TEMP - Properties that might be needed to make the AAI-APPC connection
+org.onap.appc.db.url.appcctl=jdbc:mysql://dbhost:3306/appcctl
+org.onap.appc.db.user.appcctl=appcctl
+org.onap.appc.db.pass.appcctl=appcctl
+
+org.onap.appc.db.url.sdnctl=jdbc:mysql://dbhost:3306/sdnctl
+org.onap.appc.db.user.sdnctl=sdnctl
+org.onap.appc.db.pass.sdnctl=gamma
+
+
+### ###
+### OpenStack credentials (these properties also are used in appc-rest-adapter-bundle, appc-chef-adapter-bundle, appc-iaas-adapter-bundle) ###
+### ###
+provider1.type=OpenStackProvider
+provider1.name=OpenStack
+provider1.identity=http://localhost:8181/apidoc/explorer/index.html
+provider1.tenant1.name=default
+provider1.tenant1.domain=default
+provider1.tenant1.userid=admin
+provider1.tenant1.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+
+
+
+
+
+### ###
+### Properties that are not covered or being replaced from default.properties files. Default value for DMaaP IP is 10.0.11.1:3904 ###
+### which is what the Master HEAT Template to instantiate ONAP is pointing to (version R1). All other default values are ###
+### left there since these are pre-defined as part of APP-C/ONAP default instantiation with Master HEAT Template ###
+### ###
+
+
+# Property below is valid in appc-command-executor-core, appc-license-manager-core, appc-lifecycle-management-core,
+# appc-request-handler-core, appc-workflow-management-core (all from the appc-dispatcher package).
+dmaap.poolMembers=10.0.11.1:3904
+
+
+# appc-event-listener-bundle properties (only defined in src/test of default.properties)
+appc.LCM.poolMembers=10.0.11.1:3904
+appc.LCM.topic.read=APPC-LCM-READ
+appc.LCM.topic.write=APPC-LCM-WRITE
+appc.LCM.client.name=APPC-EVENT-LISTENER-TEST
+appc.LCM.provider.user=admin
+appc.LCM.provider.pass=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+appc.LCM.provider.url=http://localhost:8181/restconf/operations/appc-provider-lcm
+
+
+# properties from appc-netconf-adapter-bundle, appc-dg-common, appc-dmaap-adapter-bundle
+poolMembers=10.0.11.1:3904
+event.pool.members=10.0.11.1:3904
+restconf.user=admin
+restconf.pass=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+
+
+# properties found in appc-rest-adapter-bundle, appc-chef-adapter-bundle, appc-iaas-adapter-bundle)
+#Your OpenStack IP
+test.ip=10.0.11.100
+# Your OpenStack Platform's Keystone Port (default is 5000)
+test.port=5000
+test.tenantid=test
+test.vmid=test
+# Port 8774 below is default port for OpenStack's Nova API Service
+test.url=http://api.appc.local/vm/9999999/test/99999999-9999-9999-9999-999999999999
+#skips hypervisor check which usually occurs during iaas-adapter-bundle startup
+org.onap.appc.iaas.skiphypervisorcheck=true
+
+
+# Properties from default.properties in the src/test and src/main paths of appc-asdc-listener-bundle
+appc.sdc.host=10.0.3.1:8443
+appc.sdc.env=APPC-ASDC-ENV
+appc.sdc.user=test
+appc.sdc.pass=test
+appc.sdc.consumer=APPC-ASDC-CONSUMER
+appc.sdc.consumer.id=APPC-ASDC-CONSUMER-ID
+appc.sdc.provider.url=http://localhost:8181/restconf/operations/AsdcMessage:configuration-document-request
+
+# Properties used by EventSenderDmaapImpl.java
+DCAE.dmaap.event.topic.write=EventSenderTest
+DCAE.dmaap.appc.username=test
+DCAE.dmaap.appc.password=test
+DCAE.dmaap.event.pool.members=10.0.11.1:3904
+
+# OAM Listener
+appc.OAM.disabled=true
+appc.OAM.provider.url=http://localhost:8181/restconf/operations/appc-oam
+appc.OAM.poolMembers=10.0.11.1:3904
+appc.OAM.service=ueb
+appc.OAM.topic.read=testOAM
+appc.OAM.topic.write=testOAM
+appc.OAM.client.name=testOAM
+appc.OAM.provider.user=admin
+appc.OAM.provider.pass=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U \ No newline at end of file
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..59d9634
--- /dev/null
+++ b/main.go
@@ -0,0 +1,32 @@
+/*
+ * 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 main
+
+import (
+ "github.com/gorilla/mux"
+ "distributed-kv-store/api"
+ "log"
+ "net/http"
+)
+
+func main() {
+ router := mux.NewRouter()
+ router.HandleFunc("/loadconfigs", api.HandlePOST).Methods("POST")
+ router.HandleFunc("/getconfig/{key}", api.HandleGET).Methods("GET")
+ router.HandleFunc("/getconfigs", api.HandleGETS).Methods("GET")
+ log.Fatal(http.ListenAndServe(":8080", router))
+}