new a goc server with New func

This commit is contained in:
tongjingran 2020-09-25 15:13:36 +08:00
parent c175816849
commit cc7ae82b4f
7 changed files with 60 additions and 45 deletions

View File

@ -50,9 +50,7 @@ goc run . [--buildflags] [--exec] [--arguments]
gocBuild.GoRunArguments = goRunArguments gocBuild.GoRunArguments = goRunArguments
defer gocBuild.Clean() defer gocBuild.Clean()
server := cover.Server{ server := cover.NewMemoryBasedServer() // only save services in memory
Store: cover.NewMemoryStore(), // only save services in memory
}
// start goc server // start goc server
var l = newLocalListener() var l = newLocalListener()

View File

@ -19,6 +19,7 @@ package cmd
import ( import (
"github.com/qiniu/goc/pkg/cover" "github.com/qiniu/goc/pkg/cover"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"log"
) )
var serverCmd = &cobra.Command{ var serverCmd = &cobra.Command{
@ -36,8 +37,9 @@ goc server --port=:8080
goc server --port=localhost:8080 goc server --port=localhost:8080
`, `,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
server := &cover.Server{ server, err := cover.NewFileBasedServer(localPersistence)
Store: cover.NewFileStore(localPersistence), if err != nil {
log.Fatalf("New file based server failed, err: %v", err)
} }
server.Run(port) server.Run(port)
}, },

View File

@ -28,9 +28,8 @@ import (
func TestClientAction(t *testing.T) { func TestClientAction(t *testing.T) {
// mock goc server // mock goc server
server := &Server{ server, err := NewFileBasedServer("_svrs_address.txt")
Store: NewFileStore("_svrs_address.txt"), assert.NoError(t, err)
}
ts := httptest.NewServer(server.Route(os.Stdout)) ts := httptest.NewServer(server.Route(os.Stdout))
defer ts.Close() defer ts.Close()
var client = NewWorker(ts.URL) var client = NewWorker(ts.URL)
@ -49,7 +48,7 @@ func TestClientAction(t *testing.T) {
})) }))
defer profileErrMockSvr.Close() defer profileErrMockSvr.Close()
// regsiter server into goc server // register service into goc server
var src ServiceUnderTest var src ServiceUnderTest
src.Name = "serviceSuccess" src.Name = "serviceSuccess"
src.Address = profileSuccessMockSvr.URL src.Address = profileSuccessMockSvr.URL

View File

@ -33,18 +33,35 @@ import (
"k8s.io/test-infra/gopherage/pkg/cov" "k8s.io/test-infra/gopherage/pkg/cov"
) )
//// DefaultStore implements the IPersistence interface
//var DefaultStore Store
// LogFile a file to save log. // LogFile a file to save log.
const LogFile = "goc.log" const LogFile = "goc.log"
type Server struct { type server struct {
PersistenceFile string
Store Store Store Store
} }
// NewFileBasedServer new a file based server with persistenceFile
func NewFileBasedServer(persistenceFile string) (*server, error) {
store, err := NewFileStore(persistenceFile)
if err != nil {
return nil, err
}
return &server{
PersistenceFile: persistenceFile,
Store: store,
}, nil
}
// NewMemoryBasedServer new a memory based server without persistenceFile
func NewMemoryBasedServer() *server {
return &server{
Store: NewMemoryStore(),
}
}
// Run starts coverage host center // Run starts coverage host center
func (s *Server) Run(port string) { func (s *server) Run(port string) {
f, err := os.Create(LogFile) f, err := os.Create(LogFile)
if err != nil { if err != nil {
log.Fatalf("failed to create log file %s, err: %v", LogFile, err) log.Fatalf("failed to create log file %s, err: %v", LogFile, err)
@ -57,13 +74,13 @@ func (s *Server) Run(port string) {
} }
// Router init goc server engine // Router init goc server engine
func (s *Server) Route(w io.Writer) *gin.Engine { func (s *server) Route(w io.Writer) *gin.Engine {
if w != nil { if w != nil {
gin.DefaultWriter = w gin.DefaultWriter = w
} }
r := gin.Default() r := gin.Default()
// api to show the registered services // api to show the registered services
//r.StaticFile(s.Store, "./"+PersistenceFile) r.StaticFile("static", "./"+s.PersistenceFile)
v1 := r.Group("/v1") v1 := r.Group("/v1")
{ {
@ -93,12 +110,12 @@ type ProfileParam struct {
} }
//listServices list all the registered services //listServices list all the registered services
func (s *Server) listServices(c *gin.Context) { func (s *server) listServices(c *gin.Context) {
services := s.Store.GetAll() services := s.Store.GetAll()
c.JSON(http.StatusOK, services) c.JSON(http.StatusOK, services)
} }
func (s *Server) registerService(c *gin.Context) { func (s *server) registerService(c *gin.Context) {
var service ServiceUnderTest var service ServiceUnderTest
if err := c.ShouldBind(&service); err != nil { if err := c.ShouldBind(&service); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
@ -124,7 +141,7 @@ func (s *Server) registerService(c *gin.Context) {
address := s.Store.Get(service.Name) address := s.Store.Get(service.Name)
if !contains(address, service.Address) { if !contains(address, service.Address) {
if err := s.Store.Add(service); err != nil { if err := s.Store.Add(service); err != nil && err != ErrServiceAlreadyRegistered {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
} }
@ -137,7 +154,7 @@ func (s *Server) registerService(c *gin.Context) {
// profile API examples: // profile API examples:
// POST /v1/cover/profile // POST /v1/cover/profile
// { "force": "true", "service":["a","b"], "address":["c","d"],"coverfile":["e","f"] } // { "force": "true", "service":["a","b"], "address":["c","d"],"coverfile":["e","f"] }
func (s *Server) profile(c *gin.Context) { func (s *server) profile(c *gin.Context) {
var body ProfileParam var body ProfileParam
if err := c.ShouldBind(&body); err != nil { if err := c.ShouldBind(&body); err != nil {
c.JSON(http.StatusExpectationFailed, gin.H{"error": err.Error()}) c.JSON(http.StatusExpectationFailed, gin.H{"error": err.Error()})
@ -216,7 +233,7 @@ func filterProfile(coverFile []string, profiles []*cover.Profile) ([]*cover.Prof
return out, nil return out, nil
} }
func (s *Server) clear(c *gin.Context) { func (s *server) clear(c *gin.Context) {
var body ProfileParam var body ProfileParam
if err := c.ShouldBind(&body); err != nil { if err := c.ShouldBind(&body); err != nil {
c.JSON(http.StatusExpectationFailed, gin.H{"error": err.Error()}) c.JSON(http.StatusExpectationFailed, gin.H{"error": err.Error()})
@ -239,7 +256,7 @@ func (s *Server) clear(c *gin.Context) {
} }
func (s *Server) initSystem(c *gin.Context) { func (s *server) initSystem(c *gin.Context) {
if err := s.Store.Init(); err != nil { if err := s.Store.Init(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return return
@ -313,6 +330,6 @@ func filterAddrs(serviceList, addressList []string, force bool, allInfos map[str
filterAddrList = addressAll filterAddrList = addressAll
} }
// Return all servers when all param is nil // Return all services when all param is nil
return filterAddrList, nil return filterAddrList, nil
} }

View File

@ -113,9 +113,8 @@ func TestFilterAddrs(t *testing.T) {
} }
func TestRegisterService(t *testing.T) { func TestRegisterService(t *testing.T) {
server := &Server{ server, err := NewFileBasedServer("_svrs_address.txt")
Store: NewFileStore("_svrs_address.txt"), assert.NoError(t, err)
}
router := server.Route(os.Stdout) router := server.Route(os.Stdout)
// register with empty service struct // register with empty service struct
@ -172,9 +171,8 @@ func TestRegisterService(t *testing.T) {
} }
func TestProfileService(t *testing.T) { func TestProfileService(t *testing.T) {
server := &Server{ server, err := NewFileBasedServer("_svrs_address.txt")
Store: NewFileStore("_svrs_address.txt"), assert.NoError(t, err)
}
router := server.Route(os.Stdout) router := server.Route(os.Stdout)
// get profile with invalid force parameter // get profile with invalid force parameter
@ -190,7 +188,7 @@ func TestClearService(t *testing.T) {
testObj := new(MockStore) testObj := new(MockStore)
testObj.On("GetAll").Return(map[string][]string{"foo": {"http://127.0.0.1:66666"}}) testObj.On("GetAll").Return(map[string][]string{"foo": {"http://127.0.0.1:66666"}})
server := &Server{ server := &server{
Store: testObj, Store: testObj,
} }
router := server.Route(os.Stdout) router := server.Route(os.Stdout)
@ -231,7 +229,7 @@ func TestInitService(t *testing.T) {
testObj := new(MockStore) testObj := new(MockStore)
testObj.On("Init").Return(fmt.Errorf("lala error")) testObj.On("Init").Return(fmt.Errorf("lala error"))
server := &Server{ server := &server{
Store: testObj, Store: testObj,
} }
router := server.Route(os.Stdout) router := server.Route(os.Stdout)

View File

@ -18,14 +18,13 @@ package cover
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
log "github.com/sirupsen/logrus"
"os" "os"
"path/filepath"
"strings" "strings"
"sync" "sync"
"errors"
log "github.com/sirupsen/logrus"
"path/filepath"
) )
var ErrServiceAlreadyRegistered = errors.New("service already registered") var ErrServiceAlreadyRegistered = errors.New("service already registered")
@ -57,14 +56,14 @@ type fileStore struct {
} }
// NewFileStore creates a store using local file // NewFileStore creates a store using local file
func NewFileStore(persistenceFile string) Store { func NewFileStore(persistenceFile string) (store Store, err error) {
path, err := filepath.Abs(persistenceFile) path, err := filepath.Abs(persistenceFile)
if err != nil { if err != nil {
log.Fatalf("get absolute path of %s fail, err: %v", persistenceFile, err) return nil, err
} }
err = os.MkdirAll(filepath.Dir(path), os.ModePerm) err = os.MkdirAll(filepath.Dir(path), os.ModePerm)
if err != nil { if err != nil {
log.Fatalf("create full path of %s fail, err: %v", filepath.Dir(path), err) return nil, err
} }
l := &fileStore{ l := &fileStore{
persistentFile: path, persistentFile: path,
@ -75,13 +74,13 @@ func NewFileStore(persistenceFile string) Store {
log.Fatalf("load failed, file: %s, err: %v", l.persistentFile, err) log.Fatalf("load failed, file: %s, err: %v", l.persistentFile, err)
} }
return l return l, nil
} }
// Add adds the given service to file Store // Add adds the given service to file Store
func (l *fileStore) Add(s ServiceUnderTest) error { func (l *fileStore) Add(s ServiceUnderTest) error {
if err := l.memoryStore.Add(s); errors.Is(err, ErrServiceAlreadyRegistered) { if err := l.memoryStore.Add(s); err != nil {
return nil return err
} }
// persistent to local store // persistent to local store

View File

@ -22,7 +22,8 @@ import (
) )
func TestLocalStore(t *testing.T) { func TestLocalStore(t *testing.T) {
localStore := NewFileStore("_svrs_address.txt") localStore, err := NewFileStore("_svrs_address.txt")
assert.NoError(t, err)
var tc1 = ServiceUnderTest{ var tc1 = ServiceUnderTest{
Name: "a", Name: "a",
Address: "http://127.0.0.1", Address: "http://127.0.0.1",
@ -40,7 +41,7 @@ func TestLocalStore(t *testing.T) {
Address: "http://127.0.0.4", Address: "http://127.0.0.4",
} }
assert.NoError(t, localStore.Add(tc1)) assert.NoError(t, localStore.Add(tc1))
assert.NoError(t, localStore.Add(tc1)) assert.Equal(t, localStore.Add(tc1), ErrServiceAlreadyRegistered)
assert.NoError(t, localStore.Add(tc2)) assert.NoError(t, localStore.Add(tc2))
assert.NoError(t, localStore.Add(tc3)) assert.NoError(t, localStore.Add(tc3))
assert.NoError(t, localStore.Add(tc4)) assert.NoError(t, localStore.Add(tc4))
@ -59,7 +60,8 @@ func TestLocalStore(t *testing.T) {
t.Error("local store check failed") t.Error("local store check failed")
} }
localStoreNew := NewFileStore("_svrs_address.txt") localStoreNew, err := NewFileStore("_svrs_address.txt")
assert.NoError(t, err)
assert.Equal(t, localStore.GetAll(), localStoreNew.GetAll()) assert.Equal(t, localStore.GetAll(), localStoreNew.GetAll())
localStore.Init() localStore.Init()