From e05262aae9cef3c14522f72a2b4d394919f35c34 Mon Sep 17 00:00:00 2001
From: Rick <1450685+LinuxSuRen@users.noreply.github.com>
Date: Wed, 9 Aug 2023 15:53:38 +0800
Subject: [PATCH] feat: support manager store on UI (#161)
---
console/atest-ui/src/App.vue | 93 ++++----
console/atest-ui/src/views/StoreManager.vue | 234 ++++++++++++++++++++
pkg/server/convert.go | 20 ++
pkg/server/convert_test.go | 30 +++
pkg/server/remote_server.go | 27 ++-
pkg/server/remote_server_test.go | 23 +-
pkg/server/server.pb.go | 85 +++----
pkg/server/server.pb.gw.go | 85 +++++++
pkg/server/server.proto | 1 +
pkg/server/server_grpc.pb.go | 36 +++
pkg/testing/loader.go | 4 +-
pkg/testing/loader_file_test.go | 2 +
pkg/testing/parser.go | 1 +
pkg/testing/parser_test.go | 5 +
pkg/testing/store.go | 69 +++++-
pkg/testing/store_test.go | 43 +++-
pkg/testing/testdata/stores.yaml | 2 +
17 files changed, 650 insertions(+), 110 deletions(-)
create mode 100644 console/atest-ui/src/views/StoreManager.vue
diff --git a/console/atest-ui/src/App.vue b/console/atest-ui/src/App.vue
index 4ebf964b..96ac1491 100644
--- a/console/atest-ui/src/App.vue
+++ b/console/atest-ui/src/App.vue
@@ -1,11 +1,12 @@
+
+
+ Store Manager
+
+ New
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ready
+ Not Ready
+
+
+
+
+
+
+ Delete
+ Edit
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pkg/server/convert.go b/pkg/server/convert.go
index caefd9d2..7d7f568d 100644
--- a/pkg/server/convert.go
+++ b/pkg/server/convert.go
@@ -26,6 +26,7 @@ package server
import "github.com/linuxsuren/api-testing/pkg/testing"
+// ToGRPCStore convert the normal store to GRPC store
func ToGRPCStore(store testing.Store) (result *Store) {
result = &Store{
Name: store.Name,
@@ -41,3 +42,22 @@ func ToGRPCStore(store testing.Store) (result *Store) {
}
return
}
+
+// ToNormalStore convert the GRPC store to normal store
+func ToNormalStore(store *Store) (result testing.Store) {
+ result = testing.Store{
+ Name: store.Name,
+ Description: store.Description,
+ URL: store.Url,
+ Username: store.Username,
+ Password: store.Password,
+ Properties: pairToMap(store.Properties),
+ }
+ if store.Kind != nil {
+ result.Kind = testing.StoreKind{
+ Name: store.Kind.Name,
+ URL: store.Kind.Url,
+ }
+ }
+ return
+}
diff --git a/pkg/server/convert_test.go b/pkg/server/convert_test.go
index 7e4ab7fe..506ba27b 100644
--- a/pkg/server/convert_test.go
+++ b/pkg/server/convert_test.go
@@ -60,3 +60,33 @@ func TestToGRPCStore(t *testing.T) {
},
}))
}
+
+func TestToNormalStore(t *testing.T) {
+ assert.Equal(t, atest.Store{
+ Name: "test",
+ Description: "desc",
+ Kind: atest.StoreKind{
+ Name: "test",
+ URL: urlFoo,
+ },
+ URL: urlFoo,
+ Username: "user",
+ Password: "pass",
+ Properties: map[string]string{
+ "foo": "bar",
+ },
+ }, ToNormalStore(&Store{
+ Name: "test",
+ Description: "desc",
+ Kind: &StoreKind{
+ Name: "test",
+ Url: urlFoo,
+ },
+ Url: urlFoo,
+ Username: "user",
+ Password: "pass",
+ Properties: []*Pair{{
+ Key: "foo", Value: "bar",
+ }},
+ }))
+}
diff --git a/pkg/server/remote_server.go b/pkg/server/remote_server.go
index 7325c96a..13864330 100644
--- a/pkg/server/remote_server.go
+++ b/pkg/server/remote_server.go
@@ -602,24 +602,35 @@ func (s *server) GetStores(ctx context.Context, in *Empty) (reply *Stores, err e
for _, item := range stores {
grpcStore := ToGRPCStore(item)
- if !item.IsLocal() {
- storeStatus, sErr := s.VerifyStore(ctx, &SimpleQuery{Name: item.Name})
- grpcStore.Ready = sErr == nil && storeStatus.Success
- } else {
- grpcStore.Ready = true
- }
+ storeStatus, sErr := s.VerifyStore(ctx, &SimpleQuery{Name: item.Name})
+ grpcStore.Ready = sErr == nil && storeStatus.Success
reply.Data = append(reply.Data, grpcStore)
}
+ reply.Data = append(reply.Data, &Store{
+ Name: "local",
+ Kind: &StoreKind{},
+ Ready: true,
+ })
}
return
}
func (s *server) CreateStore(ctx context.Context, in *Store) (reply *Store, err error) {
- // TODO need to implement
+ reply = &Store{}
+ storeFactory := testing.NewStoreFactory(s.configDir)
+ err = storeFactory.CreateStore(ToNormalStore(in))
+ return
+}
+func (s *server) UpdateStore(ctx context.Context, in *Store) (reply *Store, err error) {
+ reply = &Store{}
+ storeFactory := testing.NewStoreFactory(s.configDir)
+ err = storeFactory.UpdateStore(ToNormalStore(in))
return
}
func (s *server) DeleteStore(ctx context.Context, in *Store) (reply *Store, err error) {
- // TODO need to implement
+ reply = &Store{}
+ storeFactory := testing.NewStoreFactory(s.configDir)
+ err = storeFactory.DeleteStore(in.Name)
return
}
func (s *server) VerifyStore(ctx context.Context, in *SimpleQuery) (reply *CommonResult, err error) {
diff --git a/pkg/server/remote_server_test.go b/pkg/server/remote_server_test.go
index dc7951ee..056b1c91 100644
--- a/pkg/server/remote_server_test.go
+++ b/pkg/server/remote_server_test.go
@@ -645,9 +645,16 @@ func TestStoreManager(t *testing.T) {
t.Run("CreateStore", func(t *testing.T) {
server, clean := getRemoteServerInTempDir()
defer clean()
- reply, err := server.CreateStore(ctx, &Store{})
+ reply, err := server.CreateStore(ctx, &Store{
+ Name: "fake",
+ })
+ assert.NoError(t, err)
+ assert.NotNil(t, reply)
+
+ var stores *Stores
+ stores, err = server.GetStores(ctx, &Empty{})
assert.NoError(t, err)
- assert.Nil(t, reply)
+ assert.Equal(t, 2, len(stores.Data))
})
t.Run("DeleteStore", func(t *testing.T) {
@@ -655,7 +662,7 @@ func TestStoreManager(t *testing.T) {
defer clean()
reply, err := server.DeleteStore(ctx, &Store{})
assert.NoError(t, err)
- assert.Nil(t, reply)
+ assert.NotNil(t, reply)
})
t.Run("VerifyStore", func(t *testing.T) {
@@ -666,6 +673,14 @@ func TestStoreManager(t *testing.T) {
assert.Error(t, err)
assert.NotNil(t, reply)
})
+
+ t.Run("UpdateStore", func(t *testing.T) {
+ server, clean := getRemoteServerInTempDir()
+ defer clean()
+
+ _, err := server.UpdateStore(ctx, &Store{})
+ assert.Error(t, err)
+ })
}
func getRemoteServerInTempDir() (server RunnerServer, call func()) {
@@ -673,7 +688,7 @@ func getRemoteServerInTempDir() (server RunnerServer, call func()) {
call = func() { os.RemoveAll(dir) }
writer := atesting.NewFileWriter(dir)
- server = NewRemoteServer(writer, newLocalloaderFromStore(), "")
+ server = NewRemoteServer(writer, newLocalloaderFromStore(), dir)
return
}
diff --git a/pkg/server/server.pb.go b/pkg/server/server.pb.go
index 544af07a..fdf28475 100644
--- a/pkg/server/server.pb.go
+++ b/pkg/server/server.pb.go
@@ -1861,7 +1861,7 @@ var file_pkg_server_server_proto_rawDesc = []byte{
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x54, 0x65, 0x73, 0x74, 0x43, 0x61, 0x73, 0x65,
0x12, 0x1c, 0x0a, 0x09, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x07,
- 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xbc, 0x0b, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e,
+ 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0xeb, 0x0b, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e,
0x65, 0x72, 0x12, 0x2d, 0x0a, 0x03, 0x52, 0x75, 0x6e, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x1a, 0x12, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22,
@@ -1946,17 +1946,20 @@ var file_pkg_server_server_proto_rawDesc = []byte{
0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x73, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72,
- 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b, 0x44,
- 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b, 0x55,
+ 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x56, 0x65,
- 0x72, 0x69, 0x66, 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x14,
- 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65,
- 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
- 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x6e, 0x2f,
- 0x61, 0x70, 0x69, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x6b, 0x67, 0x2f,
- 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x0b, 0x44, 0x65,
+ 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x1a, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x56, 0x65, 0x72,
+ 0x69, 0x66, 0x79, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x14, 0x2e,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x52, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x73, 0x75, 0x72, 0x65, 0x6e, 0x2f, 0x61,
+ 0x70, 0x69, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -2051,35 +2054,37 @@ var file_pkg_server_server_proto_depIdxs = []int32{
27, // 43: server.Runner.GetStoreKinds:input_type -> server.Empty
27, // 44: server.Runner.GetStores:input_type -> server.Empty
20, // 45: server.Runner.CreateStore:input_type -> server.Store
- 20, // 46: server.Runner.DeleteStore:input_type -> server.Store
- 18, // 47: server.Runner.VerifyStore:input_type -> server.SimpleQuery
- 7, // 48: server.Runner.Run:output_type -> server.TestResult
- 0, // 49: server.Runner.GetSuites:output_type -> server.Suites
- 8, // 50: server.Runner.CreateTestSuite:output_type -> server.HelloReply
- 3, // 51: server.Runner.GetTestSuite:output_type -> server.TestSuite
- 8, // 52: server.Runner.UpdateTestSuite:output_type -> server.HelloReply
- 8, // 53: server.Runner.DeleteTestSuite:output_type -> server.HelloReply
- 9, // 54: server.Runner.ListTestCase:output_type -> server.Suite
- 11, // 55: server.Runner.GetSuggestedAPIs:output_type -> server.TestCases
- 15, // 56: server.Runner.RunTestCase:output_type -> server.TestCaseResult
- 12, // 57: server.Runner.GetTestCase:output_type -> server.TestCase
- 8, // 58: server.Runner.CreateTestCase:output_type -> server.HelloReply
- 8, // 59: server.Runner.UpdateTestCase:output_type -> server.HelloReply
- 8, // 60: server.Runner.DeleteTestCase:output_type -> server.HelloReply
- 24, // 61: server.Runner.ListCodeGenerator:output_type -> server.SimpleList
- 23, // 62: server.Runner.GenerateCode:output_type -> server.CommonResult
- 17, // 63: server.Runner.PopularHeaders:output_type -> server.Pairs
- 17, // 64: server.Runner.FunctionsQuery:output_type -> server.Pairs
- 17, // 65: server.Runner.FunctionsQueryStream:output_type -> server.Pairs
- 8, // 66: server.Runner.GetVersion:output_type -> server.HelloReply
- 8, // 67: server.Runner.Sample:output_type -> server.HelloReply
- 21, // 68: server.Runner.GetStoreKinds:output_type -> server.StoreKinds
- 19, // 69: server.Runner.GetStores:output_type -> server.Stores
- 20, // 70: server.Runner.CreateStore:output_type -> server.Store
- 20, // 71: server.Runner.DeleteStore:output_type -> server.Store
- 23, // 72: server.Runner.VerifyStore:output_type -> server.CommonResult
- 48, // [48:73] is the sub-list for method output_type
- 23, // [23:48] is the sub-list for method input_type
+ 20, // 46: server.Runner.UpdateStore:input_type -> server.Store
+ 20, // 47: server.Runner.DeleteStore:input_type -> server.Store
+ 18, // 48: server.Runner.VerifyStore:input_type -> server.SimpleQuery
+ 7, // 49: server.Runner.Run:output_type -> server.TestResult
+ 0, // 50: server.Runner.GetSuites:output_type -> server.Suites
+ 8, // 51: server.Runner.CreateTestSuite:output_type -> server.HelloReply
+ 3, // 52: server.Runner.GetTestSuite:output_type -> server.TestSuite
+ 8, // 53: server.Runner.UpdateTestSuite:output_type -> server.HelloReply
+ 8, // 54: server.Runner.DeleteTestSuite:output_type -> server.HelloReply
+ 9, // 55: server.Runner.ListTestCase:output_type -> server.Suite
+ 11, // 56: server.Runner.GetSuggestedAPIs:output_type -> server.TestCases
+ 15, // 57: server.Runner.RunTestCase:output_type -> server.TestCaseResult
+ 12, // 58: server.Runner.GetTestCase:output_type -> server.TestCase
+ 8, // 59: server.Runner.CreateTestCase:output_type -> server.HelloReply
+ 8, // 60: server.Runner.UpdateTestCase:output_type -> server.HelloReply
+ 8, // 61: server.Runner.DeleteTestCase:output_type -> server.HelloReply
+ 24, // 62: server.Runner.ListCodeGenerator:output_type -> server.SimpleList
+ 23, // 63: server.Runner.GenerateCode:output_type -> server.CommonResult
+ 17, // 64: server.Runner.PopularHeaders:output_type -> server.Pairs
+ 17, // 65: server.Runner.FunctionsQuery:output_type -> server.Pairs
+ 17, // 66: server.Runner.FunctionsQueryStream:output_type -> server.Pairs
+ 8, // 67: server.Runner.GetVersion:output_type -> server.HelloReply
+ 8, // 68: server.Runner.Sample:output_type -> server.HelloReply
+ 21, // 69: server.Runner.GetStoreKinds:output_type -> server.StoreKinds
+ 19, // 70: server.Runner.GetStores:output_type -> server.Stores
+ 20, // 71: server.Runner.CreateStore:output_type -> server.Store
+ 20, // 72: server.Runner.UpdateStore:output_type -> server.Store
+ 20, // 73: server.Runner.DeleteStore:output_type -> server.Store
+ 23, // 74: server.Runner.VerifyStore:output_type -> server.CommonResult
+ 49, // [49:75] is the sub-list for method output_type
+ 23, // [23:49] is the sub-list for method input_type
23, // [23:23] is the sub-list for extension type_name
23, // [23:23] is the sub-list for extension extendee
0, // [0:23] is the sub-list for field type_name
diff --git a/pkg/server/server.pb.gw.go b/pkg/server/server.pb.gw.go
index ecfde7f0..f7a128d4 100644
--- a/pkg/server/server.pb.gw.go
+++ b/pkg/server/server.pb.gw.go
@@ -822,6 +822,40 @@ func local_request_Runner_CreateStore_0(ctx context.Context, marshaler runtime.M
}
+func request_Runner_UpdateStore_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq Store
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UpdateStore(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_Runner_UpdateStore_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq Store
+ var metadata runtime.ServerMetadata
+
+ newReader, berr := utilities.IOReaderFactory(req.Body)
+ if berr != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+ }
+ if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UpdateStore(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
func request_Runner_DeleteStore_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Store
var metadata runtime.ServerMetadata
@@ -1453,6 +1487,31 @@ func RegisterRunnerHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser
})
+ mux.Handle("POST", pattern_Runner_UpdateStore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ var stream runtime.ServerTransportStream
+ ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ var err error
+ var annotatedContext context.Context
+ annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/UpdateStore", runtime.WithHTTPPathPattern("/server.Runner/UpdateStore"))
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_Runner_UpdateStore_0(annotatedContext, inboundMarshaler, server, req, pathParams)
+ md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+ annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+ if err != nil {
+ runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Runner_UpdateStore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
mux.Handle("POST", pattern_Runner_DeleteStore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -2050,6 +2109,28 @@ func RegisterRunnerHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli
})
+ mux.Handle("POST", pattern_Runner_UpdateStore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ var err error
+ var annotatedContext context.Context
+ annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/UpdateStore", runtime.WithHTTPPathPattern("/server.Runner/UpdateStore"))
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_Runner_UpdateStore_0(annotatedContext, inboundMarshaler, client, req, pathParams)
+ annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+ if err != nil {
+ runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_Runner_UpdateStore_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
mux.Handle("POST", pattern_Runner_DeleteStore_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -2144,6 +2225,8 @@ var (
pattern_Runner_CreateStore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "CreateStore"}, ""))
+ pattern_Runner_UpdateStore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "UpdateStore"}, ""))
+
pattern_Runner_DeleteStore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "DeleteStore"}, ""))
pattern_Runner_VerifyStore_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "VerifyStore"}, ""))
@@ -2196,6 +2279,8 @@ var (
forward_Runner_CreateStore_0 = runtime.ForwardResponseMessage
+ forward_Runner_UpdateStore_0 = runtime.ForwardResponseMessage
+
forward_Runner_DeleteStore_0 = runtime.ForwardResponseMessage
forward_Runner_VerifyStore_0 = runtime.ForwardResponseMessage
diff --git a/pkg/server/server.proto b/pkg/server/server.proto
index 3c6c9e25..37bdc9d8 100644
--- a/pkg/server/server.proto
+++ b/pkg/server/server.proto
@@ -38,6 +38,7 @@ service Runner {
rpc GetStoreKinds(Empty) returns (StoreKinds) {}
rpc GetStores(Empty) returns (Stores) {}
rpc CreateStore(Store) returns (Store) {}
+ rpc UpdateStore(Store) returns (Store) {}
rpc DeleteStore(Store) returns (Store) {}
rpc VerifyStore(SimpleQuery) returns (CommonResult) {}
}
diff --git a/pkg/server/server_grpc.pb.go b/pkg/server/server_grpc.pb.go
index 4d20c587..cfdb004a 100644
--- a/pkg/server/server_grpc.pb.go
+++ b/pkg/server/server_grpc.pb.go
@@ -50,6 +50,7 @@ type RunnerClient interface {
GetStoreKinds(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StoreKinds, error)
GetStores(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Stores, error)
CreateStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error)
+ UpdateStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error)
DeleteStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error)
VerifyStore(ctx context.Context, in *SimpleQuery, opts ...grpc.CallOption) (*CommonResult, error)
}
@@ -291,6 +292,15 @@ func (c *runnerClient) CreateStore(ctx context.Context, in *Store, opts ...grpc.
return out, nil
}
+func (c *runnerClient) UpdateStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error) {
+ out := new(Store)
+ err := c.cc.Invoke(ctx, "/server.Runner/UpdateStore", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
func (c *runnerClient) DeleteStore(ctx context.Context, in *Store, opts ...grpc.CallOption) (*Store, error) {
out := new(Store)
err := c.cc.Invoke(ctx, "/server.Runner/DeleteStore", in, out, opts...)
@@ -341,6 +351,7 @@ type RunnerServer interface {
GetStoreKinds(context.Context, *Empty) (*StoreKinds, error)
GetStores(context.Context, *Empty) (*Stores, error)
CreateStore(context.Context, *Store) (*Store, error)
+ UpdateStore(context.Context, *Store) (*Store, error)
DeleteStore(context.Context, *Store) (*Store, error)
VerifyStore(context.Context, *SimpleQuery) (*CommonResult, error)
mustEmbedUnimplementedRunnerServer()
@@ -419,6 +430,9 @@ func (UnimplementedRunnerServer) GetStores(context.Context, *Empty) (*Stores, er
func (UnimplementedRunnerServer) CreateStore(context.Context, *Store) (*Store, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateStore not implemented")
}
+func (UnimplementedRunnerServer) UpdateStore(context.Context, *Store) (*Store, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateStore not implemented")
+}
func (UnimplementedRunnerServer) DeleteStore(context.Context, *Store) (*Store, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteStore not implemented")
}
@@ -860,6 +874,24 @@ func _Runner_CreateStore_Handler(srv interface{}, ctx context.Context, dec func(
return interceptor(ctx, in, info, handler)
}
+func _Runner_UpdateStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Store)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(RunnerServer).UpdateStore(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/server.Runner/UpdateStore",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(RunnerServer).UpdateStore(ctx, req.(*Store))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
func _Runner_DeleteStore_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Store)
if err := dec(in); err != nil {
@@ -991,6 +1023,10 @@ var Runner_ServiceDesc = grpc.ServiceDesc{
MethodName: "CreateStore",
Handler: _Runner_CreateStore_Handler,
},
+ {
+ MethodName: "UpdateStore",
+ Handler: _Runner_UpdateStore_Handler,
+ },
{
MethodName: "DeleteStore",
Handler: _Runner_DeleteStore_Handler,
diff --git a/pkg/testing/loader.go b/pkg/testing/loader.go
index 65b6bd15..23d4dd7f 100644
--- a/pkg/testing/loader.go
+++ b/pkg/testing/loader.go
@@ -8,6 +8,8 @@ type Loader interface {
GetContext() string
GetCount() int
Reset()
+
+ Verify() (err error)
}
type Writer interface {
@@ -25,6 +27,4 @@ type Writer interface {
GetSuite(name string) (*TestSuite, string, error)
UpdateSuite(TestSuite) (err error)
DeleteSuite(name string) (err error)
-
- Verify() (err error)
}
diff --git a/pkg/testing/loader_file_test.go b/pkg/testing/loader_file_test.go
index 1827b8fb..151be0c5 100644
--- a/pkg/testing/loader_file_test.go
+++ b/pkg/testing/loader_file_test.go
@@ -38,6 +38,8 @@ func TestFileLoader(t *testing.T) {
loader.Put(item)
}
tt.verify(t, loader)
+
+ assert.NoError(t, loader.Verify())
})
}
}
diff --git a/pkg/testing/parser.go b/pkg/testing/parser.go
index 8d3a0db1..3faabb23 100644
--- a/pkg/testing/parser.go
+++ b/pkg/testing/parser.go
@@ -41,6 +41,7 @@ func Parse(data []byte) (testSuite *TestSuite, err error) {
return
}
+// ParseFromStream parses the stream and returns the test suite
func ParseFromStream(stream io.Reader) (testSuite *TestSuite, err error) {
var data []byte
if data, err = io.ReadAll(stream); err == nil {
diff --git a/pkg/testing/parser_test.go b/pkg/testing/parser_test.go
index 4635d17f..816aca1f 100644
--- a/pkg/testing/parser_test.go
+++ b/pkg/testing/parser_test.go
@@ -1,6 +1,7 @@
package testing_test
import (
+ "bytes"
"io"
"net/http"
"os"
@@ -54,6 +55,10 @@ func TestParse(t *testing.T) {
assert.Equal(t, "https://gitlab.com/api/v4", suite.API)
}
+ var anotherSuite *atest.TestSuite
+ anotherSuite, err = atest.ParseFromStream(bytes.NewBuffer(data))
+ assert.Equal(t, suite, anotherSuite)
+
_, err = atest.Parse([]byte(invalidTestCaseContent))
assert.NotNil(t, err)
}
diff --git a/pkg/testing/store.go b/pkg/testing/store.go
index 938b943e..c2bd023b 100644
--- a/pkg/testing/store.go
+++ b/pkg/testing/store.go
@@ -25,6 +25,7 @@ SOFTWARE.
package testing
import (
+ "fmt"
"os"
"path"
"strings"
@@ -58,10 +59,6 @@ func (s *Store) ToMap() (result map[string]string) {
return
}
-func (s *Store) IsLocal() bool {
- return s.Name == "local"
-}
-
func MapToStore(data map[string]string) (store Store) {
store = Store{
Name: data["name"],
@@ -94,6 +91,7 @@ type StoreGetterAndSetter interface {
GetStore(name string) (store *Store, err error)
DeleteStore(name string) (err error)
UpdateStore(store Store) (err error)
+ CreateStore(store Store) (err error)
GetStoreKinds() (kinds []StoreKind, err error)
}
@@ -106,12 +104,14 @@ type storeFactory struct {
configDir string
}
+// NewStoreFactory creates a new store factory
func NewStoreFactory(configDir string) StoreGetterAndSetter {
return &storeFactory{
configDir: configDir,
}
}
+// GetStores returns all stores
func (s *storeFactory) GetStores() (stores []Store, err error) {
var data []byte
if data, err = os.ReadFile(path.Join(s.configDir, "stores.yaml")); err == nil {
@@ -119,7 +119,6 @@ func (s *storeFactory) GetStores() (stores []Store, err error) {
} else {
err = nil
}
- stores = append(stores, Store{Name: "local"})
return
}
@@ -137,10 +136,70 @@ func (s *storeFactory) GetStore(name string) (store *Store, err error) {
}
func (s *storeFactory) DeleteStore(name string) (err error) {
+ var stores []Store
+ if stores, err = s.GetStores(); err == nil {
+ for i := range stores {
+ item := stores[i]
+ if item.Name == name {
+ stores = append(stores[:i], stores[i+1:]...)
+ break
+ }
+ }
+ var data []byte
+ if data, err = yaml.Marshal(stores); err == nil {
+ err = os.WriteFile(path.Join(s.configDir, "stores.yaml"), data, 0644)
+ }
+ }
return
}
func (s *storeFactory) UpdateStore(store Store) (err error) {
+ var stores []Store
+ if stores, err = s.GetStores(); err == nil {
+ exist := false
+ for i := range stores {
+ item := stores[i]
+ if item.Name == store.Name {
+ stores[i] = store
+ exist = true
+ break
+ }
+ }
+
+ if exist {
+ var data []byte
+ if data, err = yaml.Marshal(stores); err == nil {
+ err = os.WriteFile(path.Join(s.configDir, "stores.yaml"), data, 0644)
+ }
+ } else {
+ err = fmt.Errorf("store %s is not exists", store.Name)
+ }
+ }
+ return
+}
+
+func (s *storeFactory) CreateStore(store Store) (err error) {
+ var stores []Store
+ if stores, err = s.GetStores(); err == nil {
+ exist := false
+ for i := range stores {
+ item := stores[i]
+ if item.Name == store.Name {
+ exist = true
+ break
+ }
+ }
+
+ if !exist {
+ stores = append(stores, store)
+ var data []byte
+ if data, err = yaml.Marshal(stores); err == nil {
+ err = os.WriteFile(path.Join(s.configDir, "stores.yaml"), data, 0644)
+ }
+ } else {
+ err = fmt.Errorf("store %s already exists", store.Name)
+ }
+ }
return
}
diff --git a/pkg/testing/store_test.go b/pkg/testing/store_test.go
index 7e8599e1..b3fa5f51 100644
--- a/pkg/testing/store_test.go
+++ b/pkg/testing/store_test.go
@@ -25,6 +25,7 @@ SOFTWARE.
package testing
import (
+ "os"
"testing"
"github.com/stretchr/testify/assert"
@@ -70,14 +71,13 @@ func TestStoreFactory(t *testing.T) {
"database": "test",
},
}, store)
- assert.False(t, store.IsLocal())
})
t.Run("GetAllStores", func(t *testing.T) {
stores, err := factory.GetStores()
assert.Nil(t, err)
- assert.Equal(t, 2, len(stores))
- assert.Equal(t, "local", stores[1].Name)
+ assert.Equal(t, 1, len(stores))
+ assert.Equal(t, "db", stores[0].Name)
})
t.Run("DeleteStore", func(t *testing.T) {
@@ -86,22 +86,43 @@ func TestStoreFactory(t *testing.T) {
})
t.Run("UpdateStore", func(t *testing.T) {
- err := factory.UpdateStore(Store{})
- assert.NoError(t, err)
+ err := factory.UpdateStore(Store{Name: "fake"})
+ assert.Error(t, err)
})
t.Run("no stores.yaml found", func(t *testing.T) {
factory := NewStoreFactory("testdata-fake")
stores, err := factory.GetStores()
assert.NoError(t, err)
- assert.Equal(t, []Store{{
- Name: "local",
- }}, stores)
+ assert.Nil(t, stores)
})
- t.Run("local store", func(t *testing.T) {
- store := Store{Name: "local"}
- assert.True(t, store.IsLocal())
+ t.Run("CreateStore", func(t *testing.T) {
+ dir, err := os.MkdirTemp(os.TempDir(), "store")
+ assert.NoError(t, err)
+ defer os.RemoveAll(dir)
+
+ factory := NewStoreFactory(dir)
+ err = factory.CreateStore(Store{Name: "fake"})
+ assert.NoError(t, err)
+
+ // create an existing store
+ err = factory.CreateStore(Store{Name: "fake"})
+ assert.Error(t, err)
+
+ // update an existing store
+ err = factory.UpdateStore(Store{Name: "fake"})
+ assert.NoError(t, err)
+
+ // delete an existing store
+ err = factory.DeleteStore("fake")
+ assert.NoError(t, err)
+
+ // get all stores
+ var stores []Store
+ stores, err = factory.GetStores()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(stores))
})
}
diff --git a/pkg/testing/testdata/stores.yaml b/pkg/testing/testdata/stores.yaml
index e9783a44..994b3944 100644
--- a/pkg/testing/testdata/stores.yaml
+++ b/pkg/testing/testdata/stores.yaml
@@ -2,7 +2,9 @@
kind:
name: database
url: localhost:7071
+ description: ""
url: localhost:4000
username: root
+ password: ""
properties:
database: test