You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2019/07/13 09:36:27 UTC
[servicecomb-kie] branch master updated: SCB-1331 support mongodb
TLS communication (#20)
This is an automated email from the ASF dual-hosted git repository.
tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git
The following commit(s) were added to refs/heads/master by this push:
new 913ee43 SCB-1331 support mongodb TLS communication (#20)
913ee43 is described below
commit 913ee43f6c4a8a2785e7650d9db658e8e564c411
Author: Shawn <xi...@gmail.com>
AuthorDate: Sat Jul 13 17:36:23 2019 +0800
SCB-1331 support mongodb TLS communication (#20)
---
.gitignore | 1 +
README.md | 6 +-
examples/dev/conf/lager.yaml | 1 +
examples/dev/kie-conf.yaml | 7 +-
go.mod | 11 ++-
pkg/common/common.go | 5 ++
server/config/struct.go | 10 +--
server/dao/errors.go | 34 -------
server/dao/kie_api.go | 29 ++++--
server/dao/kv.go | 36 +++++++-
server/dao/label.go | 2 +-
server/dao/label_history.go | 2 +-
server/resource/v1/common.go | 7 +-
server/resource/v1/kv_resource.go | 56 +++++++-----
server/resource/v1/kv_resource_test.go | 2 +-
swagger/servicecomb-kie.yaml | 157 +++++++++++++++++++++++++++++++++
16 files changed, 275 insertions(+), 91 deletions(-)
diff --git a/.gitignore b/.gitignore
index 8d99bb8..89c876c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ output
*.iml
.idea/
**/*junit.xml
+**/*crt
**/*.exe
**/*.tgz
vendor/**
diff --git a/README.md b/README.md
index 43ece75..df84789 100644
--- a/README.md
+++ b/README.md
@@ -81,15 +81,19 @@ it will launch 3 components
To see how to build a local dev environment, check [here](examples/dev)
### Build
+this will build your own service image and binary in local
```bash
cd build
-export VERSION=0.0.1
+export VERSION=0.0.1 #optional, it is latest by default
./build_server.sh
```
this will generate a "servicecomb-kie-0.0.1-linux-amd64.tar" in "release" folder,
and a docker image "servicecomb/kie:0.0.1"
+# API Doc
+swagger/servicecomb-kie.yaml
+
## Contact
Bugs: [issues](https://issues.apache.org/jira/browse/SCB)
diff --git a/examples/dev/conf/lager.yaml b/examples/dev/conf/lager.yaml
new file mode 100644
index 0000000..419ae46
--- /dev/null
+++ b/examples/dev/conf/lager.yaml
@@ -0,0 +1 @@
+log_format_text: false
\ No newline at end of file
diff --git a/examples/dev/kie-conf.yaml b/examples/dev/kie-conf.yaml
index af99321..c9633fa 100644
--- a/examples/dev/kie-conf.yaml
+++ b/examples/dev/kie-conf.yaml
@@ -1,7 +1,8 @@
db:
+ #uri: mongodb://rwuser:xxx@x.x.x.x:8635/test?authSource=admin
uri: mongodb://kie:123@127.0.0.1:27017
type: mongodb
poolSize: 10
- ssl: false
- sslCA:
- sslCert:
\ No newline at end of file
+ timeout: 5m
+ sslEnabled: false
+ rootCAFile: /opt/kie/ca.crt
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 77abed3..b76a7cd 100644
--- a/go.mod
+++ b/go.mod
@@ -2,18 +2,17 @@ module github.com/apache/servicecomb-kie
require (
github.com/emicklei/go-restful v2.8.0+incompatible
- github.com/go-chassis/foundation v0.0.0-20190516083152-b8b2476b6db7
- github.com/go-chassis/go-archaius v0.18.0
- github.com/go-chassis/go-chassis v1.5.0
+ github.com/go-chassis/foundation v0.0.0-20190621030543-c3b63f787f4c
+ github.com/go-chassis/go-archaius v0.19.0
+ github.com/go-chassis/go-chassis v1.5.1
github.com/go-chassis/paas-lager v1.0.2-0.20190328010332-cf506050ddb2
github.com/go-mesh/openlogging v1.0.1-0.20181205082104-3d418c478b2d
github.com/onsi/ginkgo v1.8.0
github.com/onsi/gomega v1.5.0
- github.com/pkg/errors v0.8.0
- github.com/stretchr/testify v1.2.2
+ github.com/stretchr/testify v1.3.0
github.com/urfave/cli v1.20.0
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
github.com/xdg/stringprep v1.0.0 // indirect
- go.mongodb.org/mongo-driver v1.0.0
+ go.mongodb.org/mongo-driver v1.0.3
gopkg.in/yaml.v2 v2.2.1
)
diff --git a/pkg/common/common.go b/pkg/common/common.go
index f111bce..f6a2ead 100644
--- a/pkg/common/common.go
+++ b/pkg/common/common.go
@@ -28,3 +28,8 @@ const (
HeaderDepth = "X-Depth"
HeaderTenant = "X-Domain-Name"
)
+
+//ContentType
+const (
+ ContentTypeText = "application/text"
+)
diff --git a/server/config/struct.go b/server/config/struct.go
index 0e2cd55..d3ad4da 100644
--- a/server/config/struct.go
+++ b/server/config/struct.go
@@ -24,9 +24,9 @@ type Config struct {
//DB is yaml file struct to set mongodb config
type DB struct {
- URI string `yaml:"uri"`
- PoolSize int `yaml:"poolSize"`
- SSL bool `yaml:"ssl"`
- CABundle []string `yaml:"sslCA"`
- Cert string `yaml:"sslCert"`
+ URI string `yaml:"uri"`
+ PoolSize int `yaml:"poolSize"`
+ SSLEnabled bool `yaml:"sslEnabled"`
+ RootCA string `yaml:"rootCAFile"`
+ Timeout string `yaml:"timeout"`
}
diff --git a/server/dao/errors.go b/server/dao/errors.go
deleted file mode 100644
index 349ca6d..0000000
--- a/server/dao/errors.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 dao
-
-import (
- "errors"
- "fmt"
-
- "github.com/go-mesh/openlogging"
-)
-
-//ErrAction will wrap raw error to biz error and return
-//it record audit log for mongodb operation failure like find, insert, updateKey, deletion
-func ErrAction(action, filter interface{}, err error) error {
- msg := fmt.Sprintf("can not [%s] [%v],err: %s", action, filter, err.Error())
- openlogging.Error(msg)
- return errors.New(msg)
-
-}
diff --git a/server/dao/kie_api.go b/server/dao/kie_api.go
index de65dcd..37e5fa9 100644
--- a/server/dao/kie_api.go
+++ b/server/dao/kie_api.go
@@ -63,7 +63,7 @@ func (s *MongodbService) CreateOrUpdate(ctx context.Context, domain string, kv *
"default": "default",
}
}
- ctx, _ = context.WithTimeout(ctx, DefaultTimeout)
+ ctx, _ = context.WithTimeout(ctx, s.timeout)
//check labels exits or not
labelID, err := s.LabelsExist(ctx, domain, kv.Labels)
var l *model.LabelDoc
@@ -114,7 +114,7 @@ func (s *MongodbService) CreateOrUpdate(ctx context.Context, domain string, kv *
//if map is empty. will return default labels doc which has no labels
func (s *MongodbService) FindLabels(ctx context.Context, domain string, labels map[string]string) (*model.LabelDoc, error) {
collection := s.c.Database(DB).Collection(CollectionLabel)
- ctx, _ = context.WithTimeout(context.Background(), DefaultTimeout)
+ ctx, _ = context.WithTimeout(context.Background(), s.timeout)
filter := bson.M{"domain": domain}
for k, v := range labels {
filter["labels."+k] = v
@@ -125,7 +125,10 @@ func (s *MongodbService) FindLabels(ctx context.Context, domain string, labels m
cur, err := collection.Find(ctx, filter)
if err != nil {
if err.Error() == context.DeadlineExceeded.Error() {
- return nil, ErrAction("find label", filter, fmt.Errorf("can not reach mongodb in %s", s.timeout))
+ openlogging.Error("find label failed, dead line exceeded", openlogging.WithTags(openlogging.Tags{
+ "timeout": s.timeout,
+ }))
+ return nil, fmt.Errorf("can not reach mongodb in %s", s.timeout)
}
return nil, err
}
@@ -158,7 +161,10 @@ func (s *MongodbService) findKeys(ctx context.Context, filter bson.M, withoutLab
cur, err := collection.Find(ctx, filter)
if err != nil {
if err.Error() == context.DeadlineExceeded.Error() {
- return nil, ErrAction("find", filter, fmt.Errorf("can not reach mongodb in %s", s.timeout))
+ openlogging.Error("find kvs failed, dead line exceeded", openlogging.WithTags(openlogging.Tags{
+ "timeout": s.timeout,
+ }))
+ return nil, fmt.Errorf("can not reach mongodb in %s", s.timeout)
}
return nil, err
}
@@ -190,7 +196,7 @@ func (s *MongodbService) findKeys(ctx context.Context, filter bson.M, withoutLab
//key can be empty, then it will return all key values
//if key is given, will return 0-1 key value
func (s *MongodbService) FindKVByLabelID(ctx context.Context, domain, labelID, key string) ([]*model.KVDoc, error) {
- ctx, _ = context.WithTimeout(context.Background(), DefaultTimeout)
+ ctx, _ = context.WithTimeout(context.Background(), s.timeout)
filter := bson.M{"label_id": labelID, "domain": domain}
if key != "" {
filter["key"] = key
@@ -284,7 +290,7 @@ func (s *MongodbService) FindKV(ctx context.Context, domain string, options ...F
//domain=tenant
//1.delete kv;2.add history
func (s *MongodbService) Delete(kvID string, labelID string, domain string) error {
- ctx, _ := context.WithTimeout(context.Background(), DefaultTimeout)
+ ctx, _ := context.WithTimeout(context.Background(), s.timeout)
if domain == "" {
return ErrMissingDomain
}
@@ -354,17 +360,22 @@ func NewMongoService(opts Options) (*MongodbService, error) {
func getClient(opts Options) (*mongo.Client, error) {
if client == nil {
var err error
- client, err = mongo.NewClient(options.Client().ApplyURI(opts.URI))
+ clientOps := []*options.ClientOptions{options.Client().ApplyURI(opts.URI)}
+ if opts.TLS != nil {
+ clientOps = append(clientOps, options.Client().SetTLSConfig(opts.TLS))
+ openlogging.Info("enabled ssl communication to mongodb")
+ }
+ client, err = mongo.NewClient(clientOps...)
if err != nil {
return nil, err
}
- openlogging.Info("connecting to " + opts.URI)
+ openlogging.Info("DB connecting")
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx)
if err != nil {
return nil, err
}
- openlogging.Info("connected to " + opts.URI)
+ openlogging.Info("DB connected")
}
return client, nil
}
diff --git a/server/dao/kv.go b/server/dao/kv.go
index e3dcad1..f2065a5 100644
--- a/server/dao/kv.go
+++ b/server/dao/kv.go
@@ -21,6 +21,7 @@ package dao
import (
"context"
"crypto/tls"
+ "crypto/x509"
"errors"
"fmt"
"github.com/apache/servicecomb-kie/pkg/model"
@@ -29,6 +30,7 @@ import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
+ "io/ioutil"
"time"
)
@@ -42,6 +44,7 @@ var (
ErrRevisionNotExist = errors.New("label revision not exist")
ErrKVIDIsNil = errors.New("kvID id is nil")
ErrKvIDAndLabelIDNotMatch = errors.New("kvID and labelID do not match")
+ ErrRootCAMissing = errors.New("rootCAFile is empty in config file")
)
//Options mongodb options
@@ -56,13 +59,35 @@ type Options struct {
//NewKVService create a kv service
//TODO, multiple config server
func NewKVService() (*MongodbService, error) {
+ var d time.Duration
+ var err error
+ if config.GetDB().Timeout != "" {
+ d, err = time.ParseDuration(config.GetDB().Timeout)
+ if err != nil {
+ return nil, errors.New("timeout setting invalid:" + config.GetDB().Timeout)
+ }
+ }
opts := Options{
URI: config.GetDB().URI,
PoolSize: config.GetDB().PoolSize,
- SSL: config.GetDB().SSL,
+ SSL: config.GetDB().SSLEnabled,
+ Timeout: d,
}
if opts.SSL {
- //TODO tls config
+ if config.GetDB().RootCA == "" {
+ return nil, ErrRootCAMissing
+ }
+ pool := x509.NewCertPool()
+ caCert, err := ioutil.ReadFile(config.GetDB().RootCA)
+ if err != nil {
+ return nil, fmt.Errorf("read ca cert file %s failed", caCert)
+ }
+ pool.AppendCertsFromPEM(caCert)
+ opts.TLS = &tls.Config{
+ RootCAs: pool,
+ InsecureSkipVerify: true,
+ }
+
}
return NewMongoService(opts)
}
@@ -111,7 +136,7 @@ func (s *MongodbService) KVExist(ctx context.Context, domain, key string, option
func (s *MongodbService) findKV(ctx context.Context, domain string, opts FindOptions) (*mongo.Cursor, error) {
collection := s.c.Database(DB).Collection(CollectionKV)
- ctx, _ = context.WithTimeout(ctx, DefaultTimeout)
+ ctx, _ = context.WithTimeout(ctx, s.timeout)
filter := bson.M{"domain": domain}
if opts.Key != "" {
filter["key"] = opts.Key
@@ -123,7 +148,10 @@ func (s *MongodbService) findKV(ctx context.Context, domain string, opts FindOpt
cur, err := collection.Find(ctx, filter)
if err != nil {
if err.Error() == context.DeadlineExceeded.Error() {
- return nil, ErrAction("find", filter, fmt.Errorf("can not reach mongodb in %s", s.timeout))
+ openlogging.Error("find kv failed, deadline exceeded", openlogging.WithTags(openlogging.Tags{
+ "timeout": s.timeout,
+ }))
+ return nil, fmt.Errorf("can not reach mongodb in %s", s.timeout)
}
return nil, err
}
diff --git a/server/dao/label.go b/server/dao/label.go
index 742c3dc..f80088f 100644
--- a/server/dao/label.go
+++ b/server/dao/label.go
@@ -42,7 +42,7 @@ func (s *MongodbService) createLabel(ctx context.Context, domain string, labels
}
func (s *MongodbService) findOneLabels(ctx context.Context, filter bson.M) (*model.LabelDoc, error) {
collection := s.c.Database(DB).Collection(CollectionLabel)
- ctx, _ = context.WithTimeout(context.Background(), DefaultTimeout)
+ ctx, _ = context.WithTimeout(context.Background(), s.timeout)
sr := collection.FindOne(ctx, filter)
if sr.Err() != nil {
return nil, sr.Err()
diff --git a/server/dao/label_history.go b/server/dao/label_history.go
index c796e7b..08f8766 100644
--- a/server/dao/label_history.go
+++ b/server/dao/label_history.go
@@ -29,7 +29,7 @@ import (
func (s *MongodbService) getLatestLabel(ctx context.Context, labelID string) (*model.LabelRevisionDoc, error) {
collection := s.c.Database(DB).Collection(CollectionLabelRevision)
- ctx, _ = context.WithTimeout(ctx, DefaultTimeout)
+ ctx, _ = context.WithTimeout(ctx, s.timeout)
filter := bson.M{"label_id": labelID}
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index f96c11c..db40b4a 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -19,13 +19,13 @@ package v1
import (
"encoding/json"
+ "errors"
"fmt"
"github.com/apache/servicecomb-kie/pkg/common"
"github.com/apache/servicecomb-kie/pkg/model"
goRestful "github.com/emicklei/go-restful"
"github.com/go-chassis/go-chassis/server/restful"
"github.com/go-mesh/openlogging"
- "github.com/pkg/errors"
"strconv"
"strings"
)
@@ -80,14 +80,17 @@ func ReadLabelCombinations(req *goRestful.Request) ([]map[string]string, error)
if len(labelCombinations) == 0 {
return []map[string]string{{"default": "default"}}, nil
}
+
return labelCombinations, nil
}
//WriteErrResponse write error message to client
-func WriteErrResponse(context *restful.Context, status int, msg string) {
+func WriteErrResponse(context *restful.Context, status int, msg, contentType string) {
context.WriteHeader(status)
b, _ := json.MarshalIndent(&ErrorMsg{Msg: msg}, "", " ")
+ context.ReadRestfulResponse().AddHeader(goRestful.HEADER_ContentType, contentType)
context.Write(b)
+
}
//ErrLog record error
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index d8b2d50..443c1a5 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"
@@ -39,23 +40,23 @@ func (r *KVResource) Put(context *restful.Context) {
kv := new(model.KVDoc)
decoder := json.NewDecoder(context.ReadRequest().Body)
if err = decoder.Decode(kv); err != nil {
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
domain := ReadDomain(context)
if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
+ WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty, common.ContentTypeText)
}
kv.Key = key
s, err := dao.NewKVService()
if err != nil {
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
kv, err = s.CreateOrUpdate(context.Ctx, domain.(string), kv)
if err != nil {
ErrLog("put", kv, err)
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
InfoLog("put", kv)
@@ -69,40 +70,40 @@ func (r *KVResource) GetByKey(context *restful.Context) {
var err error
key := context.ReadPathParameter("key")
if key == "" {
- WriteErrResponse(context, http.StatusForbidden, "key must not be empty")
+ WriteErrResponse(context, http.StatusForbidden, "key must not be empty", common.ContentTypeText)
return
}
values := context.ReadRequest().URL.Query()
labels := make(map[string]string, len(values))
for k, v := range values {
if len(v) != 1 {
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalLabels)
+ WriteErrResponse(context, http.StatusBadRequest, MsgIllegalLabels, common.ContentTypeText)
return
}
labels[k] = v[0]
}
s, err := dao.NewKVService()
if err != nil {
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
domain := ReadDomain(context)
if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
+ WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty, common.ContentTypeText)
return
}
d, err := ReadFindDepth(context)
if err != nil {
- WriteErrResponse(context, http.StatusBadRequest, MsgIllegalDepth)
+ WriteErrResponse(context, http.StatusBadRequest, MsgIllegalDepth, common.ContentTypeText)
return
}
kvs, err := s.FindKV(context.Ctx, domain.(string), dao.WithKey(key), dao.WithLabels(labels), dao.WithDepth(d))
if err != nil {
if err == dao.ErrKeyNotExists {
- WriteErrResponse(context, http.StatusNotFound, err.Error())
+ WriteErrResponse(context, http.StatusNotFound, err.Error(), common.ContentTypeText)
return
}
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
err = context.WriteHeaderAndJSON(http.StatusOK, kvs, goRestful.MIME_JSON)
@@ -117,34 +118,41 @@ func (r *KVResource) SearchByLabels(context *restful.Context) {
var err error
labelCombinations, err := ReadLabelCombinations(context.ReadRestfulRequest())
if err != nil {
- WriteErrResponse(context, http.StatusBadRequest, err.Error())
+ WriteErrResponse(context, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
s, err := dao.NewKVService()
if err != nil {
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
domain := ReadDomain(context)
if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
+ WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty, common.ContentTypeText)
return
}
var kvs []*model.KVResponse
for _, labels := range labelCombinations {
+ openlogging.Debug("find by combination", openlogging.WithTags(openlogging.Tags{
+ "q": labels,
+ }))
result, err := s.FindKV(context.Ctx, domain.(string), dao.WithLabels(labels))
if err != nil {
if err == dao.ErrKeyNotExists {
continue
+ } else {
+ openlogging.Error("can not find by labels", openlogging.WithTags(openlogging.Tags{
+ "err": err.Error(),
+ }))
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
+ return
}
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
- return
}
kvs = append(kvs, result...)
}
if len(kvs) == 0 {
- WriteErrResponse(context, http.StatusNotFound, "no kv found")
+ WriteErrResponse(context, http.StatusNotFound, "no kv found", common.ContentTypeText)
return
}
@@ -159,17 +167,17 @@ func (r *KVResource) SearchByLabels(context *restful.Context) {
func (r *KVResource) Delete(context *restful.Context) {
domain := ReadDomain(context)
if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty)
+ WriteErrResponse(context, http.StatusInternalServerError, MsgDomainMustNotBeEmpty, common.ContentTypeText)
}
kvID := context.ReadPathParameter("kvID")
if kvID == "" {
- WriteErrResponse(context, http.StatusBadRequest, ErrKvIDMustNotEmpty)
+ WriteErrResponse(context, http.StatusBadRequest, ErrKvIDMustNotEmpty, common.ContentTypeText)
return
}
labelID := context.ReadQueryParameter("labelID")
s, err := dao.NewKVService()
if err != nil {
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
err = s.Delete(kvID, labelID, domain.(string))
@@ -179,7 +187,7 @@ func (r *KVResource) Delete(context *restful.Context) {
"labelID": labelID,
"error": err.Error(),
}))
- WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
context.WriteHeader(http.StatusNoContent)
@@ -209,7 +217,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
},
Consumes: []string{goRestful.MIME_JSON},
Produces: []string{goRestful.MIME_JSON},
- Read: &KVBody{},
+ Read: KVBody{},
}, {
Method: http.MethodGet,
Path: "/v1/kv/{key}",
@@ -222,7 +230,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
{
Code: http.StatusOK,
Message: "get key value success",
- Model: []*model.KVResponse{},
+ Model: []model.KVResponse{},
},
},
Consumes: []string{goRestful.MIME_JSON},
@@ -240,7 +248,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
{
Code: http.StatusOK,
Message: "get key value success",
- Model: []*model.KVResponse{},
+ Model: []model.KVResponse{},
},
},
Consumes: []string{goRestful.MIME_JSON},
diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go
index 8119ef0..445ef6f 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -36,8 +36,8 @@ var _ = Describe("v1 kv resource", func() {
config.Configurations = &config.Config{
DB: config.DB{},
}
+ config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017"
Describe("put kv", func() {
- config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017"
Context("valid param", func() {
kv := &model.KVDoc{
Value: "1s",
diff --git a/swagger/servicecomb-kie.yaml b/swagger/servicecomb-kie.yaml
new file mode 100644
index 0000000..4e7685b
--- /dev/null
+++ b/swagger/servicecomb-kie.yaml
@@ -0,0 +1,157 @@
+swagger: "2.0"
+info:
+ title: ""
+ version: ""
+basePath: /
+paths:
+ /v1/kv:
+ get:
+ summary: search key values by labels combination
+ operationId: SearchByLabels
+ parameters:
+ - name: q
+ in: query
+ description: 'the combination format is {label_key}:{label_value}+{label_key}:{label_value}
+ for example: /v1/kv?q=app:mall&q=app:mall+service:cart that will query key
+ values from 2 kinds of labels'
+ type: string
+ consumes:
+ - application/json
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: get key value success
+ schema:
+ type: array
+ items:
+ $ref: '#/definitions/KVResponse'
+ /v1/kv/{key}:
+ get:
+ summary: get key values by key and labels
+ operationId: GetByKey
+ parameters:
+ - name: key
+ in: path
+ required: true
+ type: string
+ - name: X-Depth
+ in: header
+ description: integer, default is 1, if you set match policy, you can set,depth
+ to decide label number
+ type: string
+ - name: body
+ in: body
+ required: true
+ schema:
+ $ref: '#/definitions/*v1.KVBody'
+ consumes:
+ - application/json
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: get key value success
+ schema:
+ type: array
+ items:
+ $ref: '#/definitions/KVResponse'
+ put:
+ summary: create or update key value
+ operationId: Put
+ parameters:
+ - name: key
+ in: path
+ required: true
+ type: string
+ - name: X-Realm
+ in: header
+ description: set kv to heterogeneous config server, not implement yet
+ type: string
+ - name: body
+ in: body
+ required: true
+ schema:
+ $ref: '#/definitions/v1.KVBody'
+ consumes:
+ - application/json
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: "true"
+ /v1/kv/{kvID}:
+ delete:
+ summary: Delete key by kvID and labelID,If the labelID is nil, query the collection
+ kv to get it.It means if only get kvID, it can also delete normally.But if
+ you want better performance, you need to pass the labelID
+ operationId: Delete
+ parameters:
+ - name: key
+ in: path
+ required: true
+ type: string
+ responses:
+ "204":
+ description: Delete success
+ "400":
+ description: Failed,check url
+ "500":
+ description: Server error
+definitions:
+ KVDoc:
+ type: object
+ properties:
+ _id:
+ type: array
+ items:
+ type: integer
+ format: byte
+ check:
+ type: string
+ domain:
+ type: string
+ key:
+ type: string
+ label_id:
+ type: string
+ labels:
+ type: object
+ additionalProperties:
+ type: string
+ revision:
+ type: integer
+ format: int32
+ value:
+ type: string
+ value_type:
+ type: string
+ KVResponse:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/definitions/KVDoc'
+ label:
+ $ref: '#/definitions/LabelDocResponse'
+ LabelDocResponse:
+ type: object
+ properties:
+ label_id:
+ type: string
+ labels:
+ type: object
+ additionalProperties:
+ type: string
+ v1.KVBody:
+ type: object
+ properties:
+ labels:
+ type: object
+ additionalProperties:
+ type: string
+ value:
+ type: string
+ valueType:
+ type: string