This is an automated email from the ASF dual-hosted git repository.

asifdxtreme pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git

commit e2b43842ef6dd237f4e3d9bcf70207a5e3b3e8aa
Author: tian <[email protected]>
AuthorDate: Fri May 17 10:46:30 2019 +0800

    add go client, return 404 if key not exist
---
 build/build_server.sh                              |   6 +-
 client/client.go                                   | 106 +++++++++++++++++++++
 .../client_suite_test.go                           |   6 +-
 client/client_test.go                              |  65 +++++++++++++
 .../dao/model_suite_test.go => client/options.go   |  37 +++----
 go.mod                                             |   1 +
 .../model_suite_test.go => pkg/common/common.go    |  31 ++----
 .../dao/{model_suite_test.go => dao_suite_test.go} |   2 +-
 server/resource/v1/common.go                       |  12 +--
 server/resource/v1/kv_resource.go                  |  29 ++++--
 10 files changed, 228 insertions(+), 67 deletions(-)

diff --git a/build/build_server.sh b/build/build_server.sh
index 4aeeded..2ffe85b 100755
--- a/build/build_server.sh
+++ b/build/build_server.sh
@@ -13,7 +13,11 @@
 # 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.
-
+if [ -z "${GOPATH}" ]; then
+ echo "missing GOPATH env, can not build"
+ exit 1
+fi
+echo "GOPATH is "${GOPATH}
 export BUILD_DIR=$(cd "$(dirname "$0")"; pwd)
 export PROJECT_DIR=$(dirname ${BUILD_DIR})
 echo "downloading dependencies"
diff --git a/client/client.go b/client/client.go
new file mode 100644
index 0000000..cb78d7c
--- /dev/null
+++ b/client/client.go
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 client
+
+import (
+       "context"
+       "crypto/tls"
+       "encoding/json"
+       "errors"
+       "fmt"
+       "github.com/apache/servicecomb-kie/pkg/common"
+       "github.com/apache/servicecomb-kie/pkg/model"
+       "github.com/go-chassis/foundation/httpclient"
+       "github.com/go-chassis/foundation/security"
+       "github.com/go-chassis/go-chassis/pkg/util/httputil"
+       "github.com/go-mesh/openlogging"
+       "net/http"
+       "net/url"
+)
+
+const (
+       APIPathKV = "v1/kv"
+)
+
+var (
+       ErrKeyNotExist = errors.New("can not find value")
+)
+
+type Client struct {
+       opts   Config
+       cipher security.Cipher
+       c      *httpclient.URLClient
+}
+type Config struct {
+       Endpoint      string
+       DefaultLabels map[string]string
+       VerifyPeer    bool //TODO make it works, now just keep it false
+}
+
+func New(config Config) (*Client, error) {
+       u, err := url.Parse(config.Endpoint)
+       if err != nil {
+               return nil, err
+       }
+       httpOpts := &httpclient.URLClientOption{}
+       if u.Scheme == "https" {
+               httpOpts.TLSConfig = &tls.Config{
+                       InsecureSkipVerify: !config.VerifyPeer,
+               }
+       }
+       c, err := httpclient.GetURLClient(httpOpts)
+       if err != nil {
+               return nil, err
+       }
+       return &Client{
+               opts: config,
+               c:    c,
+       }, nil
+}
+
+//GetValue get value of a key
+func (c *Client) Get(ctx context.Context, key string, opts ...GetOption) 
([]*model.KV, error) {
+       options := GetOptions{}
+       for _, o := range opts {
+               o(&options)
+       }
+       url := fmt.Sprintf("%s/%s/%s", c.opts.Endpoint, APIPathKV, key)
+       h := http.Header{}
+       if options.MatchMode != "" {
+               h.Set(common.HeaderMatch, options.MatchMode)
+       }
+       resp, err := c.c.HTTPDo("GET", url, h, nil)
+       if err != nil {
+               return nil, err
+       }
+       b := httputil.ReadBody(resp)
+       if resp.StatusCode != http.StatusOK {
+               if resp.StatusCode == http.StatusNotFound {
+                       return nil, ErrKeyNotExist
+               }
+               return nil, fmt.Errorf("get %s failed,http status [%s], body 
[%s]", key, resp.Status, b)
+       }
+
+       kvs := make([]*model.KV, 0)
+       err = json.Unmarshal(b, kvs)
+       if err != nil {
+               openlogging.Error("unmarshal kv failed:" + err.Error())
+               return nil, err
+       }
+       return kvs, nil
+}
diff --git a/server/dao/model_suite_test.go b/client/client_suite_test.go
similarity index 90%
copy from server/dao/model_suite_test.go
copy to client/client_suite_test.go
index a57389e..27a4f23 100644
--- a/server/dao/model_suite_test.go
+++ b/client/client_suite_test.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package dao_test
+package client_test
 
 import (
        "testing"
@@ -27,10 +27,10 @@ import (
        . "github.com/onsi/gomega"
 )
 
-func TestModel(t *testing.T) {
+func TestClient(t *testing.T) {
        RegisterFailHandler(Fail)
        junitReporter := reporters.NewJUnitReporter("junit.xml")
-       RunSpecsWithDefaultAndCustomReporters(t, "Model Suite", 
[]Reporter{junitReporter})
+       RunSpecsWithDefaultAndCustomReporters(t, "Client Suite", 
[]Reporter{junitReporter})
 }
 
 var _ = BeforeSuite(func() {
diff --git a/client/client_test.go b/client/client_test.go
new file mode 100644
index 0000000..3e02b02
--- /dev/null
+++ b/client/client_test.go
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 client_test
+
+import (
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+
+       "context"
+       . "github.com/apache/servicecomb-kie/client"
+       "os"
+)
+
+var _ = Describe("Client", func() {
+       var c1 *Client
+       os.Setenv("HTTP_DEBUG", "1")
+       Describe("new client ", func() {
+               Context("with http protocol", func() {
+                       var err error
+                       c1, err = New(Config{
+                               Endpoint: "http://127.0.0.1:30110";,
+                       })
+                       It("should not return err", func() {
+                               Expect(err).Should(BeNil())
+                       })
+                       It("should return client", func() {
+                               Expect(c1).ShouldNot(BeNil())
+                       })
+
+               })
+       })
+       Describe("get ", func() {
+               Context("only by key", func() {
+                       _, err := c1.Get(context.TODO(), "app.properties")
+                       It("should be 404 error", func() {
+                               Expect(err).Should(Equal(ErrKeyNotExist))
+                       })
+
+               })
+               Context("by key and labels", func() {
+                       _, err := c1.Get(context.TODO(), "app.properties", 
WithLables(map[string]string{
+                               "app": "mall",
+                       }))
+                       It("should be 404 error", func() {
+                               Expect(err).Should(Equal(ErrKeyNotExist))
+                       })
+
+               })
+       })
+})
diff --git a/server/dao/model_suite_test.go b/client/options.go
similarity index 58%
copy from server/dao/model_suite_test.go
copy to client/options.go
index a57389e..351b476 100644
--- a/server/dao/model_suite_test.go
+++ b/client/options.go
@@ -15,30 +15,23 @@
  * limitations under the License.
  */
 
-package dao_test
+package client
 
-import (
-       "testing"
 
-       "github.com/go-chassis/paas-lager"
-       "github.com/go-mesh/openlogging"
-       . "github.com/onsi/ginkgo"
-       "github.com/onsi/ginkgo/reporters"
-       . "github.com/onsi/gomega"
-)
 
-func TestModel(t *testing.T) {
-       RegisterFailHandler(Fail)
-       junitReporter := reporters.NewJUnitReporter("junit.xml")
-       RunSpecsWithDefaultAndCustomReporters(t, "Model Suite", 
[]Reporter{junitReporter})
+type GetOption func(*GetOptions)
+type GetOptions struct {
+       Labels    map[string]string
+       MatchMode string
 }
 
-var _ = BeforeSuite(func() {
-       log.Init(log.Config{
-               Writers:     []string{"stdout"},
-               LoggerLevel: "DEBUG",
-       })
-
-       logger := log.NewLogger("ut")
-       openlogging.SetLogger(logger)
-})
+func WithLables(l map[string]string) GetOption {
+       return func(options *GetOptions) {
+               options.Labels = l
+       }
+}
+func WithMatchMode(m string) GetOption {
+       return func(options *GetOptions) {
+               options.MatchMode = m
+       }
+}
diff --git a/go.mod b/go.mod
index 2161b5c..dd87b23 100644
--- a/go.mod
+++ b/go.mod
@@ -2,6 +2,7 @@ module github.com/apache/servicecomb-kie
 
 require (
        github.com/emicklei/go-restful v2.8.0+incompatible
+       github.com/go-chassis/foundation v0.0.0-20190203091418-304855ea28bf
        github.com/go-chassis/go-archaius v0.16.0
        github.com/go-chassis/go-chassis v1.4.0
        github.com/go-chassis/paas-lager v1.0.2-0.20190328010332-cf506050ddb2
diff --git a/server/dao/model_suite_test.go b/pkg/common/common.go
similarity index 58%
copy from server/dao/model_suite_test.go
copy to pkg/common/common.go
index a57389e..47e224e 100644
--- a/server/dao/model_suite_test.go
+++ b/pkg/common/common.go
@@ -15,30 +15,13 @@
  * limitations under the License.
  */
 
-package dao_test
+package common
 
-import (
-       "testing"
-
-       "github.com/go-chassis/paas-lager"
-       "github.com/go-mesh/openlogging"
-       . "github.com/onsi/ginkgo"
-       "github.com/onsi/ginkgo/reporters"
-       . "github.com/onsi/gomega"
+const (
+       MatchGreedy = "greedy"
+       MatchExact  = "exact"
 )
 
-func TestModel(t *testing.T) {
-       RegisterFailHandler(Fail)
-       junitReporter := reporters.NewJUnitReporter("junit.xml")
-       RunSpecsWithDefaultAndCustomReporters(t, "Model Suite", 
[]Reporter{junitReporter})
-}
-
-var _ = BeforeSuite(func() {
-       log.Init(log.Config{
-               Writers:     []string{"stdout"},
-               LoggerLevel: "DEBUG",
-       })
-
-       logger := log.NewLogger("ut")
-       openlogging.SetLogger(logger)
-})
+const (
+       HeaderMatch = "X-Match"
+)
diff --git a/server/dao/model_suite_test.go b/server/dao/dao_suite_test.go
similarity index 93%
rename from server/dao/model_suite_test.go
rename to server/dao/dao_suite_test.go
index a57389e..8be7dc3 100644
--- a/server/dao/model_suite_test.go
+++ b/server/dao/dao_suite_test.go
@@ -30,7 +30,7 @@ import (
 func TestModel(t *testing.T) {
        RegisterFailHandler(Fail)
        junitReporter := reporters.NewJUnitReporter("junit.xml")
-       RunSpecsWithDefaultAndCustomReporters(t, "Model Suite", 
[]Reporter{junitReporter})
+       RunSpecsWithDefaultAndCustomReporters(t, "Dao Suite", 
[]Reporter{junitReporter})
 }
 
 var _ = BeforeSuite(func() {
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 5d7bceb..bee9f36 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -20,16 +20,15 @@ package v1
 import (
        "encoding/json"
        "fmt"
+       "github.com/apache/servicecomb-kie/pkg/common"
        "github.com/apache/servicecomb-kie/pkg/model"
        "github.com/go-chassis/go-chassis/server/restful"
        "github.com/go-mesh/openlogging"
 )
 
 const (
-       FindExact               = "exact"
-       FindMany                = "greedy"
        MsgDomainMustNotBeEmpty = "domain must not be empty"
-       MsgIllegalFindPolicy    = "value of header X-Find can be greedy or 
exact"
+       MsgIllegalFindPolicy    = "value of header "+common.HeaderMatch+" can 
be greedy or exact"
        MsgIllegalLabels        = "label's value can not be empty, " +
                "label can not be duplicated, please check your query 
parameters"
 )
@@ -37,10 +36,11 @@ const (
 func ReadDomain(context *restful.Context) interface{} {
        return context.ReadRestfulRequest().Attribute("domain")
 }
-func ReadFindPolicy(context *restful.Context) string {
-       policy := context.ReadRestfulRequest().HeaderParameter("X-Find")
+func ReadMatchPolicy(context *restful.Context) string {
+       policy := 
context.ReadRestfulRequest().HeaderParameter(common.HeaderMatch)
        if policy == "" {
-               return FindMany
+               //default is exact to reduce network traffic
+               return common.MatchExact
        }
        return policy
 }
diff --git a/server/resource/v1/kv_resource.go 
b/server/resource/v1/kv_resource.go
index 7a9d66d..0030e7b 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -20,6 +20,7 @@ package v1
 
 import (
        "encoding/json"
+       "github.com/apache/servicecomb-kie/pkg/common"
        "github.com/apache/servicecomb-kie/pkg/model"
        "github.com/apache/servicecomb-kie/server/dao"
        goRestful "github.com/emicklei/go-restful"
@@ -62,7 +63,7 @@ func (r *KVResource) Put(context *restful.Context) {
        context.WriteHeaderAndJSON(http.StatusOK, kv, goRestful.MIME_JSON)
 
 }
-func (r *KVResource) Find(context *restful.Context) {
+func (r *KVResource) FindWithKey(context *restful.Context) {
        var err error
        key := context.ReadPathParameter("key")
        if key == "" {
@@ -88,18 +89,22 @@ func (r *KVResource) Find(context *restful.Context) {
                WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty)
                return
        }
-       policy := ReadFindPolicy(context)
+       policy := ReadMatchPolicy(context)
        var kvs []*model.KV
        switch policy {
-       case FindMany:
+       case common.MatchGreedy:
                kvs, err = s.Find(domain.(string), dao.WithKey(key), 
dao.WithLabels(labels))
-       case FindExact:
+       case common.MatchExact:
                kvs, err = s.Find(domain.(string), dao.WithKey(key), 
dao.WithLabels(labels),
                        dao.WithExactLabels())
        default:
                WriteErrResponse(context, http.StatusBadRequest, 
MsgIllegalFindPolicy)
                return
        }
+       if err == dao.ErrNotExists {
+               WriteErrResponse(context, http.StatusNotFound, err.Error())
+               return
+       }
        if err != nil {
                WriteErrResponse(context, http.StatusInternalServerError, 
err.Error())
                return
@@ -131,18 +136,22 @@ func (r *KVResource) FindByLabels(context 
*restful.Context) {
                WriteErrResponse(context, http.StatusInternalServerError, 
MsgDomainMustNotBeEmpty)
                return
        }
-       policy := ReadFindPolicy(context)
+       policy := ReadMatchPolicy(context)
        var kvs []*model.KV
        switch policy {
-       case FindMany:
+       case common.MatchGreedy:
                kvs, err = s.Find(domain.(string), dao.WithLabels(labels))
-       case FindExact:
+       case common.MatchExact:
                kvs, err = s.Find(domain.(string), dao.WithLabels(labels),
                        dao.WithExactLabels())
        default:
                WriteErrResponse(context, http.StatusBadRequest, 
MsgIllegalFindPolicy)
                return
        }
+       if err == dao.ErrNotExists {
+               WriteErrResponse(context, http.StatusNotFound, err.Error())
+               return
+       }
        err = context.WriteHeaderAndJSON(http.StatusOK, kvs, 
goRestful.MIME_JSON)
        if err != nil {
                openlogging.Error(err.Error())
@@ -190,7 +199,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
                }, {
                        Method:           http.MethodGet,
                        Path:             "/v1/kv/{key}",
-                       ResourceFuncName: "Find",
+                       ResourceFuncName: "FindWithKey",
                        FuncDesc:         "get key values by key and labels",
                        Parameters: []*restful.Parameters{
                                {
@@ -203,7 +212,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
                                        ParamType: 
goRestful.HeaderParameterKind,
                                }, {
                                        DataType:  "string",
-                                       Name:      "X-Find",
+                                       Name:      common.HeaderMatch,
                                        ParamType: 
goRestful.HeaderParameterKind,
                                        Desc:      "greedy or exact",
                                },
@@ -230,7 +239,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
                                        ParamType: 
goRestful.HeaderParameterKind,
                                }, {
                                        DataType:  "string",
-                                       Name:      "X-Find",
+                                       Name:      common.HeaderMatch,
                                        ParamType: 
goRestful.HeaderParameterKind,
                                        Desc:      "greedy or exact",
                                },

Reply via email to