This is an automated email from the ASF dual-hosted git repository. ningjiang 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 6e9a59f SCB-1312 clear go lint (#12) 6e9a59f is described below commit 6e9a59f0495e7938e330ad225891745f5ddef024 Author: Shawn <xiaoliang.t...@gmail.com> AuthorDate: Tue Jun 18 20:51:39 2019 +0800 SCB-1312 clear go lint (#12) --- .travis.yml | 12 +-- build/build_server.sh | 9 +- client/client.go | 9 +- client/options.go | 3 + cmd/{kie/cmd.go => kieserver/main.go} | 25 +++++- cmd/main.go | 48 ----------- pkg/common/common.go | 7 +- pkg/model/kv.go | 7 ++ pkg/model/mongodb_doc.go | 9 +- scripts/start.sh | 2 +- scripts/travis/start_deps.sh | 4 +- server/config/config.go | 2 + server/config/struct.go | 3 + server/dao/kie_api.go | 148 ++++++++++++++------------------- server/dao/kv.go | 47 ++++++++--- server/dao/label.go | 2 + server/dao/label_history.go | 2 + server/dao/options.go | 4 +- server/dao/tool.go | 40 ++++++++- server/handler/noop_auth_handler.go | 2 + server/resource/v1/common.go | 14 +++- server/resource/v1/doc_struct.go | 29 +++++++ server/resource/v1/history_resource.go | 1 + server/resource/v1/kv_resource.go | 66 +++++---------- 24 files changed, 276 insertions(+), 219 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e4794f..a5361b4 100755 --- a/.travis.yml +++ b/.travis.yml @@ -51,14 +51,10 @@ jobs: - bash scripts/travis/goCycloChecker.sh - stage: Unit Test script: + - GO111MODULE=on go mod download + - GO111MODULE=on go mod vendor - bash scripts/travis/start_deps.sh + - cd $HOME/gopath/src/github.com/apache/servicecomb-kie - go get github.com/mattn/goveralls - go get golang.org/x/tools/cmd/cover - - GO111MODULE=on go mod download - - GO111MODULE=on go mod vendor - - bash scripts/travis/unit_test.sh && $HOME/gopath/bin/goveralls -coverprofile=coverage.txt -service=travis-ci - - - stage: Build - script: - - cd build - - ./build_server.sh + - bash scripts/travis/unit_test.sh diff --git a/build/build_server.sh b/build/build_server.sh index 2ffe85b..099f64c 100755 --- a/build/build_server.sh +++ b/build/build_server.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -x # 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. @@ -46,8 +47,7 @@ echo "build from ${GIT_COMMIT}" echo "building..." -go build -o ${release_dir}/kie github.com/apache/servicecomb-kie/cmd/kie - +go build -o ${release_dir}/kie github.com/apache/servicecomb-kie/cmd/kieserver writeConfig(){ echo "write template config..." @@ -95,5 +95,6 @@ tar zcf ${pkg_name} conf kie echo "building docker..." cp ${PROJECT_DIR}/scripts/start.sh ./ - -sudo docker build -t servicecomb/kie:${version} -f ${PROJECT_DIR}/build/docker/server/Dockerfile . \ No newline at end of file +cp ${PROJECT_DIR}/build/docker/server/Dockerfile ./ +sudo docker version +sudo docker build -t servicecomb/kie:${version} . \ No newline at end of file diff --git a/client/client.go b/client/client.go index 3bcf161..f9df929 100644 --- a/client/client.go +++ b/client/client.go @@ -33,25 +33,32 @@ import ( "net/url" ) +//const const ( APIPathKV = "v1/kv" ) +//client errors var ( ErrKeyNotExist = errors.New("can not find value") ) +//Client is the servicecomb kie rest client. +//it is concurrency safe type Client struct { opts Config cipher security.Cipher c *httpclient.URLClient } + +//Config is the config of client type Config struct { Endpoint string DefaultLabels map[string]string VerifyPeer bool //TODO make it works, now just keep it false } +//New create a client func New(config Config) (*Client, error) { u, err := url.Parse(config.Endpoint) if err != nil { @@ -73,7 +80,7 @@ func New(config Config) (*Client, error) { }, nil } -//GetValue get value of a key +//Get get value of a key func (c *Client) Get(ctx context.Context, key string, opts ...GetOption) ([]*model.KVDoc, error) { options := GetOptions{} for _, o := range opts { diff --git a/client/options.go b/client/options.go index 21f820b..e56b76e 100644 --- a/client/options.go +++ b/client/options.go @@ -17,7 +17,10 @@ package client +//GetOption is the functional option of client func type GetOption func(*GetOptions) + +//GetOptions is the options of client func type GetOptions struct { Labels map[string]string MatchMode string diff --git a/cmd/kie/cmd.go b/cmd/kieserver/main.go similarity index 71% rename from cmd/kie/cmd.go rename to cmd/kieserver/main.go index 4ddad70..f77434f 100644 --- a/cmd/kie/cmd.go +++ b/cmd/kieserver/main.go @@ -15,11 +15,16 @@ * limitations under the License. */ -package kie +package main import ( "os" + "github.com/apache/servicecomb-kie/server/config" + _ "github.com/apache/servicecomb-kie/server/handler" + "github.com/apache/servicecomb-kie/server/resource/v1" + "github.com/go-chassis/go-chassis" + "github.com/go-mesh/openlogging" "github.com/urfave/cli" ) @@ -61,3 +66,21 @@ func Init() error { Configs = &ConfigFromCmd{} return parseConfigFromCmd(os.Args) } +func main() { + if err := Init(); err != nil { + openlogging.Fatal(err.Error()) + } + chassis.RegisterSchema("rest", &v1.KVResource{}) + if err := chassis.Init(); err != nil { + openlogging.Error(err.Error()) + os.Exit(1) + } + if err := config.Init(Configs.ConfigFile); err != nil { + openlogging.Error(err.Error()) + os.Exit(1) + } + if err := chassis.Run(); err != nil { + openlogging.Error("service exit: " + err.Error()) + os.Exit(1) + } +} diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index 4ce2316..0000000 --- a/cmd/main.go +++ /dev/null @@ -1,48 +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 main - -import ( - "github.com/apache/servicecomb-kie/cmd/kie" - _ "github.com/apache/servicecomb-kie/server/handler" - - "github.com/apache/servicecomb-kie/server/config" - "github.com/apache/servicecomb-kie/server/resource/v1" - "github.com/go-chassis/go-chassis" - "github.com/go-mesh/openlogging" - "os" -) - -func main() { - if err := kie.Init(); err != nil { - openlogging.Fatal(err.Error()) - } - chassis.RegisterSchema("rest", &v1.KVResource{}) - if err := chassis.Init(); err != nil { - openlogging.Error(err.Error()) - os.Exit(1) - } - if err := config.Init(kie.Configs.ConfigFile); err != nil { - openlogging.Error(err.Error()) - os.Exit(1) - } - if err := chassis.Run(); err != nil { - openlogging.Error("service exit: " + err.Error()) - os.Exit(1) - } -} diff --git a/pkg/common/common.go b/pkg/common/common.go index 345086a..e39dca6 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -17,12 +17,15 @@ package common +//match mode const ( MatchGreedy = "greedy" MatchExact = "exact" ) +//http headers const ( - HeaderMatch = "X-Match" - HeaderDepth = "X-Depth" + HeaderMatch = "X-Match" + HeaderDepth = "X-Depth" + HeaderTenant = "X-Domain-Name" ) diff --git a/pkg/model/kv.go b/pkg/model/kv.go index 73d33e3..2635f6e 100644 --- a/pkg/model/kv.go +++ b/pkg/model/kv.go @@ -17,7 +17,14 @@ package model +//KVResponse represents the key value list type KVResponse struct { LabelDoc *LabelDocResponse `json:"label"` Data []*KVDoc `json:"data"` } + +//LabelDocResponse is label struct +type LabelDocResponse struct { + LabelID string `json:"label_id,omitempty"` + Labels map[string]string `json:"labels,omitempty"` +} diff --git a/pkg/model/mongodb_doc.go b/pkg/model/mongodb_doc.go index 71a9483..ce32c5d 100644 --- a/pkg/model/mongodb_doc.go +++ b/pkg/model/mongodb_doc.go @@ -19,16 +19,15 @@ package model import "go.mongodb.org/mongo-driver/bson/primitive" -type LabelDocResponse struct { - LabelID string `json:"label_id,omitempty"` - Labels map[string]string `json:"labels,omitempty"` -} +//LabelDoc is database struct to store labels type LabelDoc struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Labels map[string]string `json:"labels,omitempty"` Revision int `json:"revision,omitempty"` Domain string `json:"domain,omitempty"` //tenant info } + +//KVDoc is database struct to store kv type KVDoc struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` LabelID string `json:"label_id,omitempty" bson:"label_id,omitempty"` @@ -41,6 +40,8 @@ type KVDoc struct { Domain string `json:"domain,omitempty"` //redundant Revision int `json:"revision,omitempty" bson:"-"` } + +//LabelRevisionDoc is database struct to store label history stats type LabelRevisionDoc struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` LabelID string `json:"label_id,omitempty" bson:"label_id,omitempty"` diff --git a/scripts/start.sh b/scripts/start.sh index 682634c..9abf470 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -45,7 +45,7 @@ logger_level: ${LOG_LEVEL} logger_file: log/chassis.log -log_format_text: true +log_format_text: false rollingPolicy: size diff --git a/scripts/travis/start_deps.sh b/scripts/travis/start_deps.sh index b4587ef..d2236f6 100755 --- a/scripts/travis/start_deps.sh +++ b/scripts/travis/start_deps.sh @@ -15,4 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -docker-compose up -f $GOPATH/src/github.com/apache/servicecomb-kie/deployments/docker/docker-compose.yaml \ No newline at end of file +cd build +bash build_server.sh +sudo docker-compose -f $GOPATH/src/github.com/apache/servicecomb-kie/deployments/docker/docker-compose.yaml up -d \ No newline at end of file diff --git a/server/config/config.go b/server/config/config.go index 7e03731..76571de 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -26,6 +26,7 @@ import ( var configurations *Config +//Init initiate config files func Init(file string) error { if err := archaius.AddFile(file, archaius.WithFileHandler(filesource.UseFileNameAsKeyContentAsValue)); err != nil { return err @@ -39,6 +40,7 @@ func Init(file string) error { return nil } +//GetDB return db configs func GetDB() DB { return configurations.DB } diff --git a/server/config/struct.go b/server/config/struct.go index cbfb644..0e2cd55 100644 --- a/server/config/struct.go +++ b/server/config/struct.go @@ -17,9 +17,12 @@ package config +//Config is yaml file struct type Config struct { DB DB `yaml:"db"` } + +//DB is yaml file struct to set mongodb config type DB struct { URI string `yaml:"uri"` PoolSize int `yaml:"poolSize"` diff --git a/server/dao/kie_api.go b/server/dao/kie_api.go index 323d8e7..a5cca3d 100644 --- a/server/dao/kie_api.go +++ b/server/dao/kie_api.go @@ -15,6 +15,7 @@ * limitations under the License. */ +//Package dao is the data access layer package dao import ( @@ -32,6 +33,7 @@ import ( var client *mongo.Client +//const for dao const ( DB = "kie" CollectionLabel = "label" @@ -41,11 +43,17 @@ const ( DefaultValueType = "text" ) +//MongodbService operate data in mongodb type MongodbService struct { c *mongo.Client timeout time.Duration } +//CreateOrUpdate will create or update a key value record +//it first check label exists or not, and create labels if labels is first posted. +//if label exists, then get its latest revision, and update current revision, +//save the current label and its all key values to history collection +//then check key exists or not, then create or update it func (s *MongodbService) CreateOrUpdate(ctx context.Context, domain string, kv *model.KVDoc) (*model.KVDoc, error) { if domain == "" { return nil, ErrMissingDomain @@ -176,9 +184,8 @@ func (s *MongodbService) FindKVByLabelID(ctx context.Context, domain, labelID, k filter := bson.M{"label_id": labelID, "domain": domain} if key != "" { return s.findOneKey(ctx, filter, key) - } else { - return s.findKeys(ctx, filter, true) } + return s.findKeys(ctx, filter, true) } @@ -193,107 +200,74 @@ func (s *MongodbService) FindKV(ctx context.Context, domain string, options ...F if domain == "" { return nil, ErrMissingDomain } - collection := s.c.Database(DB).Collection(CollectionKV) - ctx, _ = context.WithTimeout(ctx, DefaultTimeout) - filter := bson.M{"domain": domain} - if opts.Key != "" { - filter["key"] = opts.Key - } - for k, v := range opts.Labels { - filter["labels."+k] = v - } - cur, err := collection.Find(ctx, filter) + cur, err := s.findKV(ctx, domain, opts) if err != nil { - if err.Error() == context.DeadlineExceeded.Error() { - return nil, ErrAction("find", filter, fmt.Errorf("can not reach mongodb in %s", s.timeout)) - } return nil, err } defer cur.Close(ctx) - if cur.Err() != nil { - return nil, err - } + kvResp := make([]*model.KVResponse, 0) if opts.ExactLabels { - openlogging.Debug(fmt.Sprintf("find one [%s] with lables [%s] in [%s]", opts.Key, opts.Labels, domain)) - curKV := &model.KVDoc{} //reuse this pointer to reduce GC, only clear label - - //check label length to get the exact match - for cur.Next(ctx) { //although complexity is O(n), but there won't be so much labels for one key - curKV.Labels = nil - err := cur.Decode(curKV) - if err != nil { - openlogging.Error("decode error: " + err.Error()) - return nil, err - } - if len(curKV.Labels) == len(opts.Labels) { - openlogging.Debug("hit exact labels") - labelGroup := &model.KVResponse{ - LabelDoc: &model.LabelDocResponse{ - Labels: opts.Labels, - LabelID: curKV.LabelID, - }, - Data: make([]*model.KVDoc, 0), - } - clearKV(curKV) - labelGroup.Data = append(labelGroup.Data, curKV) - kvResp = append(kvResp, labelGroup) - return kvResp, nil - } + openlogging.Debug("find one key", openlogging.WithTags( + map[string]interface{}{ + "key": opts.Key, + "label": opts.Labels, + "domain": domain, + }, + )) + return cursorToOneKV(ctx, cur, opts.Labels) + } + if opts.Depth == 0 { + opts.Depth = 1 + } + for cur.Next(ctx) { + curKV := &model.KVDoc{} + if err := cur.Decode(curKV); err != nil { + openlogging.Error("decode to KVs error: " + err.Error()) + return nil, err } - return nil, ErrKeyNotExists - } else { - if opts.Depth == 0 { - opts.Depth = 1 + if (len(curKV.Labels) - len(opts.Labels)) > opts.Depth { + //because it is query by labels, so result can not be minus + //so many labels,then continue + openlogging.Debug("so deep, skip this key") + continue } - for cur.Next(ctx) { - curKV := &model.KVDoc{} - - if err := cur.Decode(curKV); err != nil { - openlogging.Error("decode to KVs error: " + err.Error()) - return nil, err - } - if (len(curKV.Labels) - len(opts.Labels)) > opts.Depth { - //because it is query by labels, so result can not be minus - //so many labels,then continue - openlogging.Debug("so deep, skip this key") - continue - } - openlogging.Info(fmt.Sprintf("%v", curKV)) - var groupExist bool - var labelGroup *model.KVResponse - for _, labelGroup = range kvResp { - if reflect.DeepEqual(labelGroup.LabelDoc.Labels, curKV.Labels) { - groupExist = true - clearKV(curKV) - labelGroup.Data = append(labelGroup.Data, curKV) - break - } - - } - if !groupExist { - labelGroup = &model.KVResponse{ - LabelDoc: &model.LabelDocResponse{ - Labels: curKV.Labels, - LabelID: curKV.LabelID, - }, - Data: []*model.KVDoc{curKV}, - } + openlogging.Info(fmt.Sprintf("%v", curKV)) + var groupExist bool + var labelGroup *model.KVResponse + for _, labelGroup = range kvResp { + if reflect.DeepEqual(labelGroup.LabelDoc.Labels, curKV.Labels) { + groupExist = true clearKV(curKV) - openlogging.Debug("add new label group") - kvResp = append(kvResp, labelGroup) + labelGroup.Data = append(labelGroup.Data, curKV) + break } } - if len(kvResp) == 0 { - return nil, ErrKeyNotExists + if !groupExist { + labelGroup = &model.KVResponse{ + LabelDoc: &model.LabelDocResponse{ + Labels: curKV.Labels, + LabelID: curKV.LabelID, + }, + Data: []*model.KVDoc{curKV}, + } + clearKV(curKV) + openlogging.Debug("add new label group") + kvResp = append(kvResp, labelGroup) } - return kvResp, nil + + } + if len(kvResp) == 0 { + return nil, ErrKeyNotExists } + return kvResp, nil } + +//DeleteByID delete a key value by collection ID func (s *MongodbService) DeleteByID(id string) error { collection := s.c.Database(DB).Collection(CollectionKV) hex, err := primitive.ObjectIDFromHex(id) @@ -312,6 +286,8 @@ func (s *MongodbService) DeleteByID(id string) error { return nil } +//Delete remove a list of key values for a tenant +//domain=tenant func (s *MongodbService) Delete(ids []string, domain string) error { if len(ids) == 0 { openlogging.Warn("delete error,ids is blank") @@ -351,6 +327,8 @@ func (s *MongodbService) Delete(ids []string, domain string) error { } return nil } + +//NewMongoService create a new mongo db service func NewMongoService(opts Options) (*MongodbService, error) { if opts.Timeout == 0 { opts.Timeout = DefaultTimeout diff --git a/server/dao/kv.go b/server/dao/kv.go index c48774b..41aba48 100644 --- a/server/dao/kv.go +++ b/server/dao/kv.go @@ -15,13 +15,14 @@ * limitations under the License. */ -//package dao is a persis layer of kie +//Package dao is a persis layer of kie package dao import ( "context" "crypto/tls" "errors" + "fmt" "github.com/apache/servicecomb-kie/pkg/model" "github.com/apache/servicecomb-kie/server/config" "github.com/go-mesh/openlogging" @@ -31,6 +32,7 @@ import ( "time" ) +//db errors var ( ErrMissingDomain = errors.New("domain info missing, illegal access") ErrKeyNotExists = errors.New("key with labels does not exits") @@ -40,6 +42,7 @@ var ( ErrRevisionNotExist = errors.New("label revision not exist") ) +//Options mongodb options type Options struct { URI string PoolSize int @@ -48,6 +51,8 @@ type Options struct { Timeout time.Duration } +//NewKVService create a kv service +//TODO, multiple config server func NewKVService() (*MongodbService, error) { opts := Options{ URI: config.GetDB().URI, @@ -55,7 +60,7 @@ func NewKVService() (*MongodbService, error) { SSL: config.GetDB().SSL, } if opts.SSL { - + //TODO tls config } return NewMongoService(opts) } @@ -90,16 +95,36 @@ func (s *MongodbService) KVExist(ctx context.Context, domain, key string, option return primitive.NilObjectID, err } return kvs[0].ID, nil - } else { - kvs, err := s.FindKV(ctx, domain, WithExactLabels(), WithLabels(opts.Labels), WithKey(key)) - if err != nil { - return primitive.NilObjectID, err - } - if len(kvs) != 1 { - return primitive.NilObjectID, ErrTooMany - } + } + kvs, err := s.FindKV(ctx, domain, WithExactLabels(), WithLabels(opts.Labels), WithKey(key)) + if err != nil { + return primitive.NilObjectID, err + } + if len(kvs) != 1 { + return primitive.NilObjectID, ErrTooMany + } - return kvs[0].Data[0].ID, nil + return kvs[0].Data[0].ID, nil + +} + +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) + filter := bson.M{"domain": domain} + if opts.Key != "" { + filter["key"] = opts.Key + } + for k, v := range opts.Labels { + filter["labels."+k] = v } + 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)) + } + return nil, err + } + return cur, err } diff --git a/server/dao/label.go b/server/dao/label.go index 3fddd2f..742c3dc 100644 --- a/server/dao/label.go +++ b/server/dao/label.go @@ -58,6 +58,8 @@ func (s *MongodbService) findOneLabels(ctx context.Context, filter bson.M) (*mod } return l, nil } + +//LabelsExist check label exists or not and return label ID func (s *MongodbService) LabelsExist(ctx context.Context, domain string, labels map[string]string) (primitive.ObjectID, error) { l, err := s.FindLabels(ctx, domain, labels) if err != nil { diff --git a/server/dao/label_history.go b/server/dao/label_history.go index fb8164f..a3809d6 100644 --- a/server/dao/label_history.go +++ b/server/dao/label_history.go @@ -56,6 +56,8 @@ func (s *MongodbService) getLatestLabel(ctx context.Context, labelID string) (*m } return h, nil } + +//AddHistory get latest labels revision and plus 1 and save current label stats to history, then update current revision to db func (s *MongodbService) AddHistory(ctx context.Context, labelID string, labels map[string]string, domain string) (int, error) { r, err := s.getLatestLabel(ctx, labelID) if err != nil { diff --git a/server/dao/options.go b/server/dao/options.go index 7e33798..fbbe031 100644 --- a/server/dao/options.go +++ b/server/dao/options.go @@ -17,6 +17,7 @@ package dao +//FindOptions is option to find key value type FindOptions struct { ExactLabels bool Depth int @@ -26,6 +27,7 @@ type FindOptions struct { ClearLabel bool } +//FindOption is functional option to find key value type FindOption func(*FindOptions) //WithExactLabels tell model service to return only one kv matches the labels @@ -49,7 +51,7 @@ func WithLabels(labels map[string]string) FindOption { } } -//WithLabels find kv by labelID +//WithLabelID find kv by labelID func WithLabelID(label string) FindOption { return func(o *FindOptions) { o.LabelID = label diff --git a/server/dao/tool.go b/server/dao/tool.go index b3d5ea4..08ff602 100644 --- a/server/dao/tool.go +++ b/server/dao/tool.go @@ -17,7 +17,12 @@ package dao -import "github.com/apache/servicecomb-kie/pkg/model" +import ( + "context" + "github.com/apache/servicecomb-kie/pkg/model" + "github.com/go-mesh/openlogging" + "go.mongodb.org/mongo-driver/mongo" +) //clearKV clean attr which don't need to return to client side func clearKV(kv *model.KVDoc) { @@ -25,3 +30,36 @@ func clearKV(kv *model.KVDoc) { kv.Labels = nil kv.LabelID = "" } + +func cursorToOneKV(ctx context.Context, cur *mongo.Cursor, labels map[string]string) ([]*model.KVResponse, error) { + kvResp := make([]*model.KVResponse, 0) + curKV := &model.KVDoc{} //reuse this pointer to reduce GC, only clear label + //check label length to get the exact match + for cur.Next(ctx) { //although complexity is O(n), but there won't be so much labels for one key + if cur.Err() != nil { + return nil, cur.Err() + } + curKV.Labels = nil + err := cur.Decode(curKV) + if err != nil { + openlogging.Error("decode error: " + err.Error()) + return nil, err + } + if len(curKV.Labels) == len(labels) { + openlogging.Debug("hit exact labels") + labelGroup := &model.KVResponse{ + LabelDoc: &model.LabelDocResponse{ + Labels: labels, + LabelID: curKV.LabelID, + }, + Data: make([]*model.KVDoc, 0), + } + clearKV(curKV) + labelGroup.Data = append(labelGroup.Data, curKV) + kvResp = append(kvResp, labelGroup) + return kvResp, nil + } + + } + return nil, ErrKeyNotExists +} diff --git a/server/handler/noop_auth_handler.go b/server/handler/noop_auth_handler.go index b2c4a20..b4a3833 100644 --- a/server/handler/noop_auth_handler.go +++ b/server/handler/noop_auth_handler.go @@ -26,6 +26,7 @@ import ( //developer can extend authenticate and authorization by set new handler in chassis.yaml type NoopAuthHandler struct{} +//Handle set local attribute to http request func (bk *NoopAuthHandler) Handle(chain *handler.Chain, inv *invocation.Invocation, cb invocation.ResponseCallBack) { inv.SetMetadata("domain", "default") chain.Next(inv, cb) @@ -35,6 +36,7 @@ func newDomainResolver() handler.Handler { return &NoopAuthHandler{} } +//Name is handler name func (bk *NoopAuthHandler) Name() string { return "auth-handler" } diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go index eca9fef..48baa22 100644 --- a/server/resource/v1/common.go +++ b/server/resource/v1/common.go @@ -27,11 +27,8 @@ import ( "strconv" ) +//const of server const ( - HeaderTenant = "X-Domain-Name" - - FindExact = "exact" - FindMany = "greedy" MsgDomainMustNotBeEmpty = "domain must not be empty" MsgIllegalFindPolicy = "value of header " + common.HeaderMatch + " can be greedy or exact" MsgIllegalLabels = "label's value can not be empty, " + @@ -40,9 +37,12 @@ const ( ErrIDMustNotEmpty = "must supply id if you want to remove key" ) +//ReadDomain get domain info from attribute func ReadDomain(context *restful.Context) interface{} { return context.ReadRestfulRequest().Attribute("domain") } + +//ReadFindDepth get find depth func ReadFindDepth(context *restful.Context) (int, error) { d := context.ReadRestfulRequest().HeaderParameter(common.HeaderDepth) if d == "" { @@ -54,6 +54,8 @@ func ReadFindDepth(context *restful.Context) (int, error) { } return depth, nil } + +//ReadMatchPolicy get match policy func ReadMatchPolicy(context *restful.Context) string { policy := context.ReadRestfulRequest().HeaderParameter(common.HeaderMatch) if policy == "" { @@ -62,16 +64,20 @@ func ReadMatchPolicy(context *restful.Context) string { } return policy } + +//WriteErrResponse write error message to client func WriteErrResponse(context *restful.Context, status int, msg string) { context.WriteHeader(status) b, _ := json.MarshalIndent(&ErrorMsg{Msg: msg}, "", " ") context.Write(b) } +//ErrLog record error func ErrLog(action string, kv *model.KVDoc, err error) { openlogging.Error(fmt.Sprintf("[%s] [%v] err:%s", action, kv, err.Error())) } +//InfoLog record info func InfoLog(action string, kv *model.KVDoc) { openlogging.Info( fmt.Sprintf("[%s] [%s:%s] in [%s] success", action, kv.Key, kv.Value, kv.Domain)) diff --git a/server/resource/v1/doc_struct.go b/server/resource/v1/doc_struct.go index a0402ae..37f7432 100644 --- a/server/resource/v1/doc_struct.go +++ b/server/resource/v1/doc_struct.go @@ -17,12 +17,41 @@ package v1 +import ( + "github.com/apache/servicecomb-kie/pkg/common" + goRestful "github.com/emicklei/go-restful" + "github.com/go-chassis/go-chassis/server/restful" +) + +//swagger doc elements +var ( + DocHeaderDepth = &restful.Parameters{ + DataType: "string", + Name: common.HeaderDepth, + ParamType: goRestful.HeaderParameterKind, + Desc: "integer, default is 1, if you set match policy, you can set,depth to decide label number", + } + DocPathKey = &restful.Parameters{ + DataType: "string", + Name: "key", + ParamType: goRestful.PathParameterKind, + } + DocHeaderMath = &restful.Parameters{ + DataType: "string", + Name: common.HeaderMatch, + ParamType: goRestful.HeaderParameterKind, + Desc: "greedy or exact", + } +) + +//KVBody is open api doc type KVBody struct { Labels map[string]string `json:"labels"` ValueType string `json:"valueType"` Value string `json:"value"` } +//ErrorMsg is open api doc type ErrorMsg struct { Msg string `json:"msg"` } diff --git a/server/resource/v1/history_resource.go b/server/resource/v1/history_resource.go index 3952a19..0bca053 100644 --- a/server/resource/v1/history_resource.go +++ b/server/resource/v1/history_resource.go @@ -17,5 +17,6 @@ package v1 +//HistoryResource TODO type HistoryResource struct { } diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go index 7832f23..a1f94b6 100644 --- a/server/resource/v1/kv_resource.go +++ b/server/resource/v1/kv_resource.go @@ -15,7 +15,7 @@ * limitations under the License. */ -//v1 package hold http rest v1 API +//Package v1 hold http rest v1 API package v1 import ( @@ -31,9 +31,11 @@ import ( "strings" ) +//KVResource has API about kv operations type KVResource struct { } +//Put create or update kv func (r *KVResource) Put(context *restful.Context) { var err error key := context.ReadPathParameter("key") @@ -64,6 +66,8 @@ func (r *KVResource) Put(context *restful.Context) { context.WriteHeaderAndJSON(http.StatusOK, kv, goRestful.MIME_JSON) } + +//FindWithKey search key by label and key func (r *KVResource) FindWithKey(context *restful.Context) { var err error key := context.ReadPathParameter("key") @@ -121,6 +125,8 @@ func (r *KVResource) FindWithKey(context *restful.Context) { } } + +//FindByLabels search key only by label func (r *KVResource) FindByLabels(context *restful.Context) { var err error values := context.ReadRequest().URL.Query() @@ -169,6 +175,8 @@ func (r *KVResource) FindByLabels(context *restful.Context) { } } + +//Delete deletes key by ids func (r *KVResource) Delete(context *restful.Context) { domain := ReadDomain(context) if domain == nil { @@ -203,16 +211,7 @@ func (r *KVResource) URLPatterns() []restful.Route { ResourceFuncName: "Put", FuncDesc: "create or update key value", Parameters: []*restful.Parameters{ - { - DataType: "string", - Name: "key", - ParamType: goRestful.PathParameterKind, - }, { - DataType: "string", - Name: HeaderTenant, - ParamType: goRestful.HeaderParameterKind, - Desc: "set kv to other tenant", - }, { + DocPathKey, { DataType: "string", Name: "X-Realm", ParamType: goRestful.HeaderParameterKind, @@ -234,20 +233,7 @@ func (r *KVResource) URLPatterns() []restful.Route { ResourceFuncName: "FindWithKey", FuncDesc: "get key values by key and labels", Parameters: []*restful.Parameters{ - { - DataType: "string", - Name: "key", - ParamType: goRestful.PathParameterKind, - }, { - DataType: "string", - Name: HeaderTenant, - ParamType: goRestful.HeaderParameterKind, - }, { - DataType: "string", - Name: common.HeaderMatch, - ParamType: goRestful.HeaderParameterKind, - Desc: "greedy or exact", - }, + DocPathKey, DocHeaderMath, DocHeaderDepth, }, Returns: []*restful.Returns{ { @@ -265,16 +251,7 @@ func (r *KVResource) URLPatterns() []restful.Route { ResourceFuncName: "FindByLabels", FuncDesc: "find key values only by labels", Parameters: []*restful.Parameters{ - { - DataType: "string", - Name: HeaderTenant, - ParamType: goRestful.HeaderParameterKind, - }, { - DataType: "string", - Name: common.HeaderMatch, - ParamType: goRestful.HeaderParameterKind, - Desc: "greedy or exact", - }, + DocHeaderMath, DocHeaderDepth, }, Returns: []*restful.Returns{ { @@ -290,18 +267,13 @@ func (r *KVResource) URLPatterns() []restful.Route { Path: "/v1/kv/{ids}", ResourceFuncName: "Delete", FuncDesc: "delete key by id,separated by ','", - Parameters: []*restful.Parameters{ - { - DataType: "string", - Name: HeaderTenant, - ParamType: goRestful.HeaderParameterKind, - }, { - DataType: "string", - Name: "ids", - ParamType: goRestful.PathParameterKind, - Desc: "The id strings to be removed are separated by ',',If the actual number of deletions " + - "and the number of parameters are not equal, no error will be returned and only warn log will be printed.", - }, + Parameters: []*restful.Parameters{{ + DataType: "string", + Name: "ids", + ParamType: goRestful.PathParameterKind, + Desc: "The id strings to be removed are separated by ',',If the actual number of deletions " + + "and the number of parameters are not equal, no error will be returned and only warn log will be printed.", + }, }, Returns: []*restful.Returns{ {