Skip to content
Permalink
Browse files

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
  • Loading branch information...
liuqi04 authored and tianxiaoliang committed Aug 2, 2019
1 parent 22a2bbe commit e84506f5d913898123d57e7fc47b0f298d026511
@@ -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())
}
9 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
)
@@ -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"`
}
@@ -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"`
}
@@ -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",
@@ -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},
},
}
}
@@ -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))
})
})
})
})
@@ -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
@@ -18,41 +18,71 @@
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() {
//for UT
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))
})
})
})
})
@@ -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
}

0 comments on commit e84506f

Please sign in to comment.
You can’t perform that action at this time.