Skip to content

Commit

Permalink
feat: support add multiple stores (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
LinuxSuRen committed Jul 29, 2023
1 parent 470ef8e commit 8d459a9
Show file tree
Hide file tree
Showing 43 changed files with 2,867 additions and 1,491 deletions.
3 changes: 3 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tasks:
- init: make build
command: docker run --pull always --network host ghcr.io/linuxsuren/api-testing:master
10 changes: 4 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ install-precheck:
cp .github/pre-commit .git/hooks/pre-commit

grpc:
protoc --go_out=. --go_opt=paths=source_relative \
protoc --proto_path=. \
--go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/server/server.proto

protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pkg/testing/remote/loader.proto
pkg/server/server.proto \
pkg/testing/remote/loader.proto
grpc-gw:
protoc -I . --grpc-gateway_out . \
--grpc-gateway_opt logtostderr=true \
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer,
c.Version = version.GetVersion()
c.AddCommand(createInitCommand(execer),
createRunCommand(), createSampleCmd(),
createServerCmd(gRPCServer, httpServer), createJSONSchemaCmd(),
createServerCmd(execer, gRPCServer, httpServer), createJSONSchemaCmd(),
createServiceCommand(execer), createFunctionCmd())
return
}
Expand Down
8 changes: 5 additions & 3 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ import (
)

func TestCreateRunCommand(t *testing.T) {
execer := fakeruntime.FakeExecer{}

cmd := createRunCommand()
assert.Equal(t, "run", cmd.Use)

init := createInitCommand(fakeruntime.FakeExecer{})
init := createInitCommand(execer)
assert.Equal(t, "init", init.Use)

s := createServerCmd(&fakeGRPCServer{}, server.NewFakeHTTPServer())
s := createServerCmd(execer, &fakeGRPCServer{}, server.NewFakeHTTPServer())
assert.NotNil(t, s)
assert.Equal(t, "server", s.Use)

root := NewRootCmd(fakeruntime.FakeExecer{}, NewFakeGRPCServer(), server.NewFakeHTTPServer())
root := NewRootCmd(execer, NewFakeGRPCServer(), server.NewFakeHTTPServer())
root.SetArgs([]string{"init", "-k=demo.yaml", "--wait-namespace", "demo", "--wait-resource", "demo"})
err := root.Execute()
assert.Nil(t, err)
Expand Down
56 changes: 25 additions & 31 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package cmd

import (
"bytes"
"errors"
"fmt"
"log"
"net"
"net/http"
"os"
"path"
"strings"
"time"
Expand All @@ -19,43 +19,51 @@ import (
"github.com/linuxsuren/api-testing/pkg/testing"
"github.com/linuxsuren/api-testing/pkg/testing/remote"
"github.com/linuxsuren/api-testing/pkg/util"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

func createServerCmd(gRPCServer gRPCServer, httpServer server.HTTPServer) (c *cobra.Command) {
func createServerCmd(execer fakeruntime.Execer, gRPCServer gRPCServer, httpServer server.HTTPServer) (c *cobra.Command) {
opt := &serverOption{
gRPCServer: gRPCServer,
httpServer: httpServer,
execer: execer,
}
c = &cobra.Command{
Use: "server",
Short: "Run as a server mode",
RunE: opt.runE,
Use: "server",
Short: "Run as a server mode",
PreRunE: opt.preRunE,
RunE: opt.runE,
}
flags := c.Flags()
flags.IntVarP(&opt.port, "port", "p", 7070, "The RPC server port")
flags.IntVarP(&opt.httpPort, "http-port", "", 8080, "The HTTP server port")
flags.BoolVarP(&opt.printProto, "print-proto", "", false, "Print the proto content and exit")
flags.StringVarP(&opt.storage, "storage", "", "local", "The storage type, local or etcd")
flags.StringArrayVarP(&opt.localStorage, "local-storage", "", []string{"*.yaml"}, "The local storage path")
flags.StringVarP(&opt.grpcStorage, "grpc-storage", "", "", "The grpc storage address")
flags.StringVarP(&opt.consolePath, "console-path", "", "", "The path of the console")
flags.StringVarP(&opt.configDir, "config-dir", "", "$HOME/.config/atest", "The config directory")
return
}

type serverOption struct {
gRPCServer gRPCServer
httpServer server.HTTPServer
execer fakeruntime.Execer

port int
httpPort int
printProto bool
storage string
localStorage []string
grpcStorage string
consolePath string
configDir string
}

func (o *serverOption) preRunE(cmd *cobra.Command, args []string) (err error) {
o.configDir = os.ExpandEnv(o.configDir)
err = o.execer.MkdirAll(o.configDir, 0755)
return
}

func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
Expand All @@ -79,30 +87,15 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
return
}

var loader testing.Writer
switch o.storage {
case "local":
loader = testing.NewFileWriter("")
for _, storage := range o.localStorage {
if err = loader.Put(storage); err != nil {
break
}
}
case "grpc":
if o.grpcStorage == "" {
err = errors.New("grpc storage address is required")
return
loader := testing.NewFileWriter("")
for _, storage := range o.localStorage {
if loadErr := loader.Put(storage); loadErr != nil {
cmd.PrintErrf("failed to load %s, error: %v\n", storage, loadErr)
continue
}
loader, err = remote.NewGRPCLoader(o.grpcStorage)
default:
err = errors.New("invalid storage type")
}

if err != nil {
return
}

removeServer := server.NewRemoteServer(loader)
removeServer := server.NewRemoteServer(loader, remote.NewGRPCloaderFromStore(), o.configDir)
s := o.gRPCServer
go func() {
if gRPCServer, ok := s.(reflection.GRPCServer); ok {
Expand All @@ -113,13 +106,14 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
s.Serve(lis)
}()

mux := runtime.NewServeMux()
mux := runtime.NewServeMux(runtime.WithMetadata(server.MetadataStoreFunc)) // runtime.WithIncomingHeaderMatcher(func(key string) (s string, b bool) {
err = server.RegisterRunnerHandlerServer(cmd.Context(), mux, removeServer)
if err == nil {
mux.HandlePath(http.MethodGet, "/", frontEndHandlerWithLocation(o.consolePath))
mux.HandlePath(http.MethodGet, "/assets/{asset}", frontEndHandlerWithLocation(o.consolePath))
mux.HandlePath(http.MethodGet, "/healthz", frontEndHandlerWithLocation(o.consolePath))
o.httpServer.WithHandler(mux)
log.Printf("HTTP server listening at %v", httplis.Addr())
err = o.httpServer.Serve(httplis)
}
return
Expand Down
35 changes: 19 additions & 16 deletions cmd/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

_ "embed"

"github.com/linuxsuren/api-testing/cmd/service"
"github.com/linuxsuren/api-testing/pkg/version"
fakeruntime "github.com/linuxsuren/go-fake-runtime"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -272,26 +273,23 @@ type linuxService struct {
commonService
}

const systemCtl = "systemctl"
const serviceName = "atest"

func (s *linuxService) Start() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "start", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "start", service.ServiceName)
return
}

func (s *linuxService) Stop() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "stop", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "stop", service.ServiceName)
return
}

func (s *linuxService) Restart() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "restart", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "restart", service.ServiceName)
return
}

func (s *linuxService) Status() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "status", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "status", service.ServiceName)
if err != nil && err.Error() == "exit status 3" {
// this is normal case
err = nil
Expand All @@ -301,13 +299,13 @@ func (s *linuxService) Status() (output string, err error) {

func (s *linuxService) Install() (output string, err error) {
if err = os.WriteFile(s.scriptPath, []byte(s.script), os.ModeAppend); err == nil {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "enable", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "enable", service.ServiceName)
}
return
}

func (s *linuxService) Uninstall() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(systemCtl, "", "disable", serviceName)
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "disable", service.ServiceName)
return
}

Expand All @@ -324,7 +322,7 @@ type containerService struct {

const defaultImage = "ghcr.io/linuxsuren/api-testing"

func newContainerService(execer fakeruntime.Execer, client, image, tag, localStorage string, writer io.Writer) (service Service) {
func newContainerService(execer fakeruntime.Execer, client, image, tag, localStorage string, writer io.Writer) (svc Service) {
if tag == "" {
tag = "latest"
}
Expand All @@ -335,7 +333,7 @@ func newContainerService(execer fakeruntime.Execer, client, image, tag, localSto
containerServer := &containerService{
Execer: execer,
client: client,
name: serviceName,
name: service.ServiceName,
image: image,
tag: tag,
localStorage: localStorage,
Expand All @@ -344,11 +342,11 @@ func newContainerService(execer fakeruntime.Execer, client, image, tag, localSto
}

if strings.HasSuffix(client, ServiceModePodman.String()) {
service = &podmanService{
svc = &podmanService{
containerService: containerServer,
}
} else {
service = containerServer
svc = containerServer
}
return
}
Expand Down Expand Up @@ -426,14 +424,19 @@ func (s *podmanService) Start() (output string, err error) {
return
}

func (s *podmanService) Stop() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "stop", service.PodmanServiceName)
return
}

func (s *podmanService) installService() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn(s.client, "", "generate", "systemd", "--new", "--files", "--name", s.name)
if err == nil {
var result string
result, err = s.Execer.RunCommandAndReturn("mv", "", "container-atest.service", "/etc/systemd/system")
result, err = s.Execer.RunCommandAndReturn("mv", "", service.PodmanServiceName, "/etc/systemd/system")
if err == nil {
output = fmt.Sprintf("%s\n%s", output, result)
if result, err = s.Execer.RunCommandAndReturn("systemctl", "", "enable", "container-atest.service"); err == nil {
if result, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "enable", service.PodmanServiceName); err == nil {
output = fmt.Sprintf("%s\n%s", output, result)
}
}
Expand All @@ -453,6 +456,6 @@ func (s *podmanService) Uninstall() (output string, err error) {
}

func (s *podmanService) uninstallService() (output string, err error) {
output, err = s.Execer.RunCommandAndReturn("systemctl", "", "disable", "container-atest.service")
output, err = s.Execer.RunCommandAndReturn(service.SystemCtl, "", "disable", service.PodmanServiceName)
return
}
9 changes: 9 additions & 0 deletions cmd/service/constant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package service

const (
// PodmanServiceName is the service name of podman service
PodmanServiceName = "container-atest.service"

SystemCtl = "systemctl"
ServiceName = "atest"
)
6 changes: 6 additions & 0 deletions cmd/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ func TestService(t *testing.T) {
targetOS: fakeruntime.OSLinux,
mode: ServiceModePodman.String(),
expectOutput: "",
}, {
name: "stop in podman",
action: "stop",
targetOS: fakeruntime.OSLinux,
mode: ServiceModePodman.String(),
expectOutput: "",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions console/atest-ui/cypress/e2e/component-exist.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
console.log(Cypress.browser)
describe('Suite Manage', () => {
const suiteName = userID_Alpha()
const store = "local"
const sampleAPIAddress = "http://foo"
console.log(sampleAPIAddress)

Expand All @@ -13,6 +14,11 @@ describe('Suite Manage', () => {

cy.get('[test-id="open-new-suite-dialog"]').click()

const storeSelect = cy.get('[test-id=suite-form-store] input')
storeSelect.click()
storeSelect.type(store)
storeSelect.trigger('keydown', {key: 'Enter'})

cy.get('[test-id=suite-form-name]').should('be.visible').type(suiteName)
cy.get('[test-id=suite-form-api]').should('be.visible').type(sampleAPIAddress)
cy.get('[test-id=suite-form-submit]').should('be.visible').click()
Expand Down
Loading

0 comments on commit 8d459a9

Please sign in to comment.