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/08/02 06:38:26 UTC
[servicecomb-kie] branch master updated: add GetHistoryByLabelID
interface with unit test, Register history's UrlPatterns to chassis (#23)
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 e84506f add GetHistoryByLabelID interface with unit test, Register history's UrlPatterns to chassis (#23)
e84506f is described below
commit e84506f5d913898123d57e7fc47b0f298d026511
Author: Qi Liu <30...@users.noreply.github.com>
AuthorDate: Fri Aug 2 14:38:22 2019 +0800
add GetHistoryByLabelID interface with unit test, Register history's UrlPatterns to chassis (#23)
* add getHistoryByLabelID interface with unit test
1. add getHistoryByLabelID interface along with unit test.
2. new interface fit new dao structure.
* remove fake handler, modify history model
* remove comment in history unit test
---
cmd/kieserver/main.go | 6 +-
go.mod | 9 ++-
pkg/model/kv.go | 8 +++
pkg/model/mongodb_doc.go | 6 +-
server/resource/v1/doc_struct.go | 5 ++
server/resource/v1/history_resource.go | 64 +++++++++++++++++++
server/resource/v1/history_resource_test.go | 91 ++++++++++++++++++++++++++
server/resource/v1/kv_resource.go | 5 +-
server/resource/v1/kv_resource_test.go | 54 ++++++++++++----
server/service/history/dao.go | 32 ++++++++++
server/service/history/service.go | 13 +++-
swagger/servicecomb-kie.yaml | 99 +++++++++++++++--------------
12 files changed, 321 insertions(+), 71 deletions(-)
diff --git a/cmd/kieserver/main.go b/cmd/kieserver/main.go
index 1c95c27..b861289 100644
--- a/cmd/kieserver/main.go
+++ b/cmd/kieserver/main.go
@@ -18,12 +18,13 @@
package main
import (
- "github.com/apache/servicecomb-kie/server/db"
"os"
+ "github.com/apache/servicecomb-kie/server/db"
+
"github.com/apache/servicecomb-kie/server/config"
_ "github.com/apache/servicecomb-kie/server/handler"
- "github.com/apache/servicecomb-kie/server/resource/v1"
+ v1 "github.com/apache/servicecomb-kie/server/resource/v1"
"github.com/go-chassis/go-chassis"
"github.com/go-mesh/openlogging"
"github.com/urfave/cli"
@@ -72,6 +73,7 @@ func main() {
openlogging.Fatal(err.Error())
}
chassis.RegisterSchema("rest", &v1.KVResource{})
+ chassis.RegisterSchema("rest", &v1.HistoryResource{})
if err := chassis.Init(); err != nil {
openlogging.Fatal(err.Error())
}
diff --git a/go.mod b/go.mod
index b76a7cd..db325ae 100644
--- a/go.mod
+++ b/go.mod
@@ -3,16 +3,19 @@ module github.com/apache/servicecomb-kie
require (
github.com/emicklei/go-restful v2.8.0+incompatible
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/go-archaius v0.20.0
+ github.com/go-chassis/go-chassis v1.6.2-0.20190730080139-fcfd929304bc
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/golang/snappy v0.0.1 // indirect
+ github.com/google/go-cmp v0.3.0 // indirect
github.com/onsi/ginkgo v1.8.0
github.com/onsi/gomega v1.5.0
github.com/stretchr/testify v1.3.0
+ github.com/tidwall/pretty v1.0.0 // indirect
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.3
+ go.mongodb.org/mongo-driver v1.0.0
gopkg.in/yaml.v2 v2.2.1
)
diff --git a/pkg/model/kv.go b/pkg/model/kv.go
index 2635f6e..968574c 100644
--- a/pkg/model/kv.go
+++ b/pkg/model/kv.go
@@ -28,3 +28,11 @@ type LabelDocResponse struct {
LabelID string `json:"label_id,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}
+
+//LabelHistoryResponse is label history revision struct
+type LabelHistoryResponse struct {
+ LabelID string `json:"label_id,omitempty" bson:"label_id,omitempty"`
+ Labels map[string]string `json:"labels,omitempty"`
+ KVs []*KVDoc `json:"data,omitempty"`
+ Revision int `json:"revision"`
+}
diff --git a/pkg/model/mongodb_doc.go b/pkg/model/mongodb_doc.go
index ce32c5d..07397ff 100644
--- a/pkg/model/mongodb_doc.go
+++ b/pkg/model/mongodb_doc.go
@@ -45,8 +45,8 @@ type KVDoc struct {
type LabelRevisionDoc struct {
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
LabelID string `json:"label_id,omitempty" bson:"label_id,omitempty"`
- Labels map[string]string `json:"labels,omitempty"` //redundant
- Domain string `json:"domain,omitempty"` //redundant
- KVs []*KVDoc `json:"data,omitempty"` // save states of this revision
+ Labels map[string]string `json:"labels,omitempty"`
+ Domain string `json:"-"`
+ KVs []*KVDoc `json:"data,omitempty"`
Revision int `json:"revision"`
}
diff --git a/server/resource/v1/doc_struct.go b/server/resource/v1/doc_struct.go
index 5b79d17..371ed63 100644
--- a/server/resource/v1/doc_struct.go
+++ b/server/resource/v1/doc_struct.go
@@ -44,6 +44,11 @@ var (
Name: "key",
ParamType: goRestful.PathParameterKind,
}
+ DocPathLabelID = &restful.Parameters{
+ DataType: "string",
+ Name: "label_id",
+ ParamType: goRestful.PathParameterKind,
+ }
kvIDParameters = &restful.Parameters{
DataType: "string",
Name: "kvID",
diff --git a/server/resource/v1/history_resource.go b/server/resource/v1/history_resource.go
index 0bca053..2a2fc3c 100644
--- a/server/resource/v1/history_resource.go
+++ b/server/resource/v1/history_resource.go
@@ -17,6 +17,70 @@
package v1
+import (
+ "net/http"
+
+ "github.com/apache/servicecomb-kie/pkg/common"
+ "github.com/apache/servicecomb-kie/pkg/model"
+ "github.com/apache/servicecomb-kie/server/db"
+ rvsvc "github.com/apache/servicecomb-kie/server/service/history"
+ goRestful "github.com/emicklei/go-restful"
+ "github.com/go-chassis/go-chassis/server/restful"
+ "github.com/go-mesh/openlogging"
+)
+
//HistoryResource TODO
type HistoryResource struct {
}
+
+//GetRevisionsByLabelID search key only by label
+func (r *HistoryResource) GetRevisionsByLabelID(context *restful.Context) {
+ var err error
+ labelID := context.ReadPathParameter("label_id")
+ if labelID == "" {
+ openlogging.Debug("label id is null")
+ WriteErrResponse(context, http.StatusForbidden, "label_id must not be empty", common.ContentTypeText)
+ return
+ }
+ revisions, err := rvsvc.GetHistoryByLabelID(context.Ctx, labelID)
+ if err != nil {
+ if err == db.ErrRevisionNotExist {
+ WriteErrResponse(context, http.StatusNotFound, err.Error(), common.ContentTypeText)
+ return
+ }
+ WriteErrResponse(context, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
+ return
+ }
+ if len(revisions) == 0 {
+ WriteErrResponse(context, http.StatusNotFound, "no revisions found", common.ContentTypeText)
+ return
+ }
+ err = context.WriteHeaderAndJSON(http.StatusOK, revisions, goRestful.MIME_JSON)
+ if err != nil {
+ openlogging.Error(err.Error())
+ }
+}
+
+//URLPatterns defined config operations
+func (r *HistoryResource) URLPatterns() []restful.Route {
+ return []restful.Route{
+ {
+ Method: http.MethodGet,
+ Path: "/v1/revision/{label_id}",
+ ResourceFuncName: "GetRevisionsByLabelID",
+ FuncDesc: "get all revisions by label id",
+ Parameters: []*restful.Parameters{
+ DocPathLabelID,
+ },
+ Returns: []*restful.Returns{
+ {
+ Code: http.StatusOK,
+ Message: "true",
+ Model: []model.LabelHistoryResponse{},
+ },
+ },
+ Consumes: []string{goRestful.MIME_JSON},
+ Produces: []string{goRestful.MIME_JSON},
+ },
+ }
+}
diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go
new file mode 100644
index 0000000..aacdf54
--- /dev/null
+++ b/server/resource/v1/history_resource_test.go
@@ -0,0 +1,91 @@
+/*
+ * 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 v1_test
+
+import (
+ "context"
+ "encoding/json"
+ "io/ioutil"
+
+ "github.com/go-chassis/go-chassis/core/common"
+ "github.com/go-chassis/go-chassis/core/handler"
+
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+
+ "github.com/apache/servicecomb-kie/pkg/model"
+ "github.com/apache/servicecomb-kie/server/db"
+ kvsvc "github.com/apache/servicecomb-kie/server/service/kv"
+
+ "github.com/apache/servicecomb-kie/server/config"
+ v1 "github.com/apache/servicecomb-kie/server/resource/v1"
+ "github.com/go-chassis/go-chassis/server/restful/restfultest"
+
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("v1 history resource", func() {
+
+ config.Configurations = &config.Config{
+ DB: config.DB{},
+ }
+
+ Describe("get history revisions", func() {
+ config.Configurations.DB.URI = "mongodb://kie:123@127.0.0.1:27017"
+ err := db.Init()
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
+ })
+ Context("valid param", func() {
+ kv := &model.KVDoc{
+ Key: "test",
+ Value: "revisions",
+ Labels: map[string]string{
+ "test": "revisions",
+ },
+ }
+ kv, _ = kvsvc.CreateOrUpdate(context.Background(), "default", kv)
+ path := fmt.Sprintf("/v1/revision/%s", kv.LabelID)
+ r, _ := http.NewRequest("GET", path, nil)
+ revision := &v1.HistoryResource{}
+ chain, _ := handler.GetChain(common.Provider, "")
+ c, err := restfultest.New(revision, chain)
+ It("should not return err or nil", func() {
+ Expect(err).Should(BeNil())
+ })
+ resp := httptest.NewRecorder()
+ c.ServeHTTP(resp, r)
+
+ body, err := ioutil.ReadAll(resp.Body)
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
+ })
+ data := []*model.LabelRevisionDoc{}
+ err = json.Unmarshal(body, &data)
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
+ })
+
+ It("should return all revisions with the same label ID", func() {
+ Expect(len(data) > 0).Should(Equal(true))
+ Expect((data[0]).LabelID).Should(Equal(kv.LabelID))
+ })
+ })
+ })
+})
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index 45f276b..49ed48a 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -20,14 +20,15 @@ package v1
import (
"encoding/json"
+ "net/http"
+
"github.com/apache/servicecomb-kie/pkg/common"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/db"
- "github.com/apache/servicecomb-kie/server/service/kv"
+ kvsvc "github.com/apache/servicecomb-kie/server/service/kv"
goRestful "github.com/emicklei/go-restful"
"github.com/go-chassis/go-chassis/server/restful"
"github.com/go-mesh/openlogging"
- "net/http"
)
//KVResource has API about kv operations
diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go
index 586c25c..bba7d12 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -18,17 +18,23 @@
package v1_test
import (
+ "bytes"
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+
+ "github.com/go-chassis/go-chassis/core/common"
+ "github.com/go-chassis/go-chassis/core/handler"
+ "github.com/go-chassis/go-chassis/server/restful/restfultest"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "bytes"
- "context"
- "encoding/json"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/config"
- "github.com/apache/servicecomb-kie/server/resource/v1"
- "github.com/go-chassis/go-chassis/server/restful/restfultest"
- "net/http"
+ "github.com/apache/servicecomb-kie/server/db"
+ noop "github.com/apache/servicecomb-kie/server/handler"
+ v1 "github.com/apache/servicecomb-kie/server/resource/v1"
)
var _ = Describe("v1 kv resource", func() {
@@ -36,23 +42,47 @@ 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"
+ err := db.Init()
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
+ })
Context("valid param", func() {
kv := &model.KVDoc{
+ Key: "timeout",
Value: "1s",
Labels: map[string]string{"service": "tester"},
}
j, _ := json.Marshal(kv)
r, _ := http.NewRequest("PUT", "/v1/kv/timeout", bytes.NewBuffer(j))
- rctx := restfultest.NewRestfulContext(context.Background(), r)
- rctx.ReadRestfulRequest().SetAttribute("domain", "default")
+ noopH := &noop.NoopAuthHandler{}
+ chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
+ r.Header.Set("Content-Type", "application/json")
kvr := &v1.KVResource{}
- kvr.Put(rctx)
- It("should be 500 ", func() {
- Expect(rctx.Resp.StatusCode()).Should(Equal(http.StatusInternalServerError))
+ c, err := restfultest.New(kvr, chain)
+ It("should not return error", func() {
+ Expect(err).Should(BeNil())
+ })
+ resp := httptest.NewRecorder()
+ c.ServeHTTP(resp, r)
+
+ body, err := ioutil.ReadAll(resp.Body)
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
+ })
+
+ data := &model.KVDoc{}
+ err = json.Unmarshal(body, data)
+ It("should not return err", func() {
+ Expect(err).Should(BeNil())
})
+ It("should return created or updated kv", func() {
+ Expect(data.Value).Should(Equal(kv.Value))
+ Expect(data.Labels).Should(Equal(kv.Labels))
+ })
})
})
})
diff --git a/server/service/history/dao.go b/server/service/history/dao.go
index d6a1aba..a373970 100644
--- a/server/service/history/dao.go
+++ b/server/service/history/dao.go
@@ -20,11 +20,13 @@ package history
import (
"context"
"fmt"
+
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/db"
"github.com/go-mesh/openlogging"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
+ "go.mongodb.org/mongo-driver/mongo/options"
)
//AddHistory increment labels revision and save current label stats to history, then update current revision to db
@@ -63,3 +65,33 @@ func AddHistory(ctx context.Context,
openlogging.Debug(fmt.Sprintf("update revision to %d", labelRevision.Revision))
return labelRevision.Revision, nil
}
+
+func getHistoryByLabelID(ctx context.Context, filter bson.M) ([]*model.LabelRevisionDoc, error) {
+ c, err := db.GetClient()
+ if err != nil {
+ return nil, err
+ }
+ collection := c.Database(db.Name).Collection(db.CollectionLabelRevision)
+ cur, err := collection.Find(ctx, filter, options.Find().SetSort(map[string]interface{}{
+ "revisions": -1,
+ }))
+ if err != nil {
+ return nil, err
+ }
+ rvs := []*model.LabelRevisionDoc{}
+ var exist bool
+ for cur.Next(ctx) {
+ var elem model.LabelRevisionDoc
+ err := cur.Decode(&elem)
+ if err != nil {
+ openlogging.Error("decode to LabelRevisionDoc error: " + err.Error())
+ return nil, err
+ }
+ exist = true
+ rvs = append(rvs, &elem)
+ }
+ if !exist {
+ return nil, db.ErrRevisionNotExist
+ }
+ return rvs, nil
+}
diff --git a/server/service/history/service.go b/server/service/history/service.go
index 1c38bfa..1de7695 100644
--- a/server/service/history/service.go
+++ b/server/service/history/service.go
@@ -20,16 +20,19 @@ package history
import (
"context"
"fmt"
+
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/db"
"github.com/apache/servicecomb-kie/server/service/label"
"github.com/go-mesh/openlogging"
+ "go.mongodb.org/mongo-driver/bson"
)
//GetAndAddHistory get latest labels revision and call AddHistory
func GetAndAddHistory(ctx context.Context,
labelID string, labels map[string]string, kvs []*model.KVDoc, domain string) (int, error) {
- ctx, _ = context.WithTimeout(ctx, db.Timeout)
+ ctx, cancel := context.WithTimeout(ctx, db.Timeout)
+ defer cancel()
r, err := label.GetLatestLabel(ctx, labelID)
if err != nil {
if err == db.ErrRevisionNotExist {
@@ -53,3 +56,11 @@ func GetAndAddHistory(ctx context.Context,
}
return r.Revision, nil
}
+
+//GetHistoryByLabelID get all history by label id
+func GetHistoryByLabelID(ctx context.Context, labelID string) ([]*model.LabelRevisionDoc, error) {
+ ctx, cancel := context.WithTimeout(ctx, db.Timeout)
+ defer cancel()
+ filter := bson.M{"label_id": labelID}
+ return getHistoryByLabelID(ctx, filter)
+}
diff --git a/swagger/servicecomb-kie.yaml b/swagger/servicecomb-kie.yaml
index 4e7685b..4b786d6 100644
--- a/swagger/servicecomb-kie.yaml
+++ b/swagger/servicecomb-kie.yaml
@@ -9,88 +9,91 @@ paths:
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
+ - 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
+ - application/json
produces:
- - application/json
+ - application/json
responses:
"200":
description: get key value success
schema:
type: array
items:
- $ref: '#/definitions/KVResponse'
+ $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'
+ - 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
+ - application/json
produces:
- - application/json
+ - application/json
responses:
"200":
description: get key value success
schema:
type: array
items:
- $ref: '#/definitions/KVResponse'
+ $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'
+ - 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
+ - application/json
produces:
- - application/json
+ - 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
+ 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
+ - name: key
+ in: path
+ required: true
+ type: string
responses:
"204":
description: Delete success
@@ -132,9 +135,9 @@ definitions:
data:
type: array
items:
- $ref: '#/definitions/KVDoc'
+ $ref: "#/definitions/KVDoc"
label:
- $ref: '#/definitions/LabelDocResponse'
+ $ref: "#/definitions/LabelDocResponse"
LabelDocResponse:
type: object
properties: