diff --git a/Makefile.am b/Makefile.am index 4e11396..32ac54a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,8 +6,9 @@ bin_PROGRAMS = mstorectl sbin_PROGRAMS = mstored mstorectl_SOURCES = \ + cmd/mstorectl/filecmd.go \ + cmd/mstorectl/imagecmd.go \ cmd/mstorectl/main.go - cmd/mstorectl/file.go mstored_SOURCES = \ cmd/mstored/main.go diff --git a/Makefile.in b/Makefile.in index c2ecc1d..309e0d1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -287,6 +287,8 @@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign no-dependencies no-installinfo GOFLAGS = -v mstorectl_SOURCES = \ + cmd/mstorectl/filecmd.go \ + cmd/mstorectl/imagecmd.go \ cmd/mstorectl/main.go mstored_SOURCES = \ @@ -782,7 +784,6 @@ uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS .PRECIOUS: Makefile - cmd/mstorectl/file.go mstorectl$(EXEEXT): $(mstorectl_SOURCES) env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o mstorectl$(EXEEXT) $(mstorectl_SOURCES) diff --git a/app/config/config.go b/app/config/config.go index 9ab8fe1..d3e21d9 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -97,8 +97,10 @@ func (conf *Config) ReadOptions() error { var err error exename := filepath.Base(os.Args[0]) - flag.Int64Var(&conf.Service.Port, "port", conf.Service.Port, "listen port") - flag.BoolVar(&conf.AsDaemon, "daemon", conf.AsDaemon, "run as daemon") + // TODO: make local scope of flags + + //flag.Int64Var(&conf.Service.Port, "port", conf.Service.Port, "listen port") + //flag.BoolVar(&conf.AsDaemon, "daemon", conf.AsDaemon, "run as daemon") help := func() { fmt.Println("") diff --git a/app/handler/file.go b/app/handler/file.go index 778b18c..57b7308 100644 --- a/app/handler/file.go +++ b/app/handler/file.go @@ -16,8 +16,8 @@ func (hand *Handler) FileExists(rctx *router.Context) { params := &operator.FileExistsParams{ Filepath: filepath, } - - code, res, err := hand.oper.FileExists(params) + ctx := rctx.GetContext() + code, res, err := hand.oper.FileExists(ctx, params) if err != nil { hand.logg.Errorf("FileExists error: %v", err) rctx.SetStatus(code) @@ -46,7 +46,9 @@ func (hand *Handler) PutFile(rctx *router.Context) { ContentType: contentType, Source: rctx.Request.Body, } - code, _, err := hand.oper.PutFile(params) + ctx := rctx.GetContext() + + code, _, err := hand.oper.PutFile(ctx, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) @@ -64,7 +66,8 @@ func (hand *Handler) GetFile(rctx *router.Context) { } hand.logg.Debugf("filepath: %s", filepath) - code, res, err := hand.oper.GetFile(params) + ctx := rctx.GetContext() + code, res, err := hand.oper.GetFile(ctx, params) if err != nil { hand.logg.Errorf("PutFile error: %v", err) rctx.SetStatus(code) @@ -93,10 +96,12 @@ func (hand *Handler) DeleteFile(rctx *router.Context) { params := &operator.DeleteFileParams{ Filepath: filepath, } - code, _, err := hand.oper.DeleteFile(params) + ctx := rctx.GetContext() + code, _, err := hand.oper.DeleteFile(ctx, params) if err != nil { hand.logg.Errorf("GetFile error: %v", err) } + rctx.SetStatus(code) } @@ -107,7 +112,9 @@ func (hand *Handler) ListFiles(rctx *router.Context) { params := &operator.ListFilesParams{ Filepath: filepath, } - code, res, err := hand.oper.ListFiles(params) + ctx := rctx.GetContext() + + code, res, err := hand.oper.ListFiles(ctx, params) if err != nil { hand.logg.Errorf("ListFiles error: %v", err) rctx.SetStatus(code) diff --git a/app/maindb/file.go b/app/maindb/file.go index 88deb92..316712e 100644 --- a/app/maindb/file.go +++ b/app/maindb/file.go @@ -1,10 +1,12 @@ package maindb import ( + "context" + "mstore/app/descr" ) -func (db *Database) InsertFile(file *descr.File) error { +func (db *Database) InsertFile(ctx context.Context, file *descr.File) error { var err error request := `INSERT INTO file(id, collection, name, type, checksum, size, created_at, updated_at, created_by, updated_by) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)` @@ -16,7 +18,7 @@ func (db *Database) InsertFile(file *descr.File) error { return err } -func (db *Database) UpdateFileByID(fileID string, file *descr.File) error { +func (db *Database) UpdateFileByID(ctx context.Context, fileID string, file *descr.File) error { var err error request := `UPDATE file SET id = $1, collection = $2, name = $3, type = $4, checksum = $5, size = $6, updated_at = $7, created_by = $8, updated_by = $9 @@ -29,7 +31,7 @@ func (db *Database) UpdateFileByID(fileID string, file *descr.File) error { return err } -func (db *Database) ListFilesByCollection(collection string) ([]descr.File, error) { +func (db *Database) ListFilesByCollection(ctx context.Context, collection string) ([]descr.File, error) { var err error request := `SELECT * FROM file WHERE collection = $1 ORDER BY collection, name` res := make([]descr.File, 0) @@ -40,7 +42,7 @@ func (db *Database) ListFilesByCollection(collection string) ([]descr.File, erro return res, err } -func (db *Database) ListAllFiles() ([]descr.File, error) { +func (db *Database) ListAllFiles(ctx context.Context) ([]descr.File, error) { var err error request := `SELECT * FROM file ORDER BY collection, name` res := make([]descr.File, 0) @@ -51,7 +53,7 @@ func (db *Database) ListAllFiles() ([]descr.File, error) { return res, err } -func (db *Database) GetFileByID(fileID int64) (bool, *descr.File, error) { +func (db *Database) GetFileByID(ctx context.Context, fileID int64) (bool, *descr.File, error) { var err error var res *descr.File var exists bool @@ -69,7 +71,7 @@ func (db *Database) GetFileByID(fileID int64) (bool, *descr.File, error) { return exists, res, err } -func (db *Database) GetFileByCollection(collection, name string) (bool, *descr.File, error) { +func (db *Database) GetFileByCollection(ctx context.Context, collection, name string) (bool, *descr.File, error) { var err error var res *descr.File var exists bool @@ -89,7 +91,7 @@ func (db *Database) GetFileByCollection(collection, name string) (bool, *descr.F return exists, res, err } -func (db *Database) DeleteFileByCollection(collection, name string) error { +func (db *Database) DeleteFileByCollection(ctx context.Context, collection, name string) error { var err error request := `DELETE FROM file WHERE collection = $1 AND name = $2` diff --git a/app/operator/file.go b/app/operator/file.go index 34f7a6a..4a5e313 100644 --- a/app/operator/file.go +++ b/app/operator/file.go @@ -1,6 +1,7 @@ package operator import ( + "context" "fmt" "io" "net/http" @@ -30,7 +31,7 @@ func cleanFilepath(filename string) (string, error) { return filepath.Clean(filename), nil } -func (oper *Operator) FileExists(param *FileExistsParams) (int, *FileExistsResult, error) { +func (oper *Operator) FileExists(ctx context.Context, param *FileExistsParams) (int, *FileExistsResult, error) { var err error code := http.StatusOK res := &FileExistsResult{} @@ -44,7 +45,7 @@ func (oper *Operator) FileExists(param *FileExistsParams) (int, *FileExistsResul filename := path.Base(xfilepath) collection := path.Dir(xfilepath) - exist, fileDescr, err := oper.mdb.GetFileByCollection(collection, filename) + exist, fileDescr, err := oper.mdb.GetFileByCollection(ctx, collection, filename) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -72,7 +73,7 @@ type PutFileResult struct{} const defaultContentType = "application/octet-stream" -func (oper *Operator) PutFile(param *PutFileParams) (int, *PutFileResult, error) { +func (oper *Operator) PutFile(ctx context.Context, param *PutFileParams) (int, *PutFileResult, error) { var err error res := &PutFileResult{} @@ -108,7 +109,7 @@ func (oper *Operator) PutFile(param *PutFileParams) (int, *PutFileResult, error) return code, res, err } - descrExists, fileDescr, err := oper.mdb.GetFileByCollection(collection, filename) + descrExists, fileDescr, err := oper.mdb.GetFileByCollection(ctx, collection, filename) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -120,7 +121,7 @@ func (oper *Operator) PutFile(param *PutFileParams) (int, *PutFileResult, error) fileDescr.Checksum = checksum fileDescr.UpdatedAt = now fileDescr.Type = contentType - err = oper.mdb.UpdateFileByID(fileDescr.ID, fileDescr) + err = oper.mdb.UpdateFileByID(ctx, fileDescr.ID, fileDescr) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -136,7 +137,7 @@ func (oper *Operator) PutFile(param *PutFileParams) (int, *PutFileResult, error) CreatedAt: now, UpdatedAt: now, } - err = oper.mdb.InsertFile(fileDescr) + err = oper.mdb.InsertFile(ctx, fileDescr) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -163,7 +164,7 @@ type GetFileResult struct { Source io.ReadCloser } -func (oper *Operator) GetFile(param *GetFileParams) (int, *GetFileResult, error) { +func (oper *Operator) GetFile(ctx context.Context, param *GetFileParams) (int, *GetFileResult, error) { var err error res := &GetFileResult{} @@ -179,7 +180,7 @@ func (oper *Operator) GetFile(param *GetFileParams) (int, *GetFileResult, error) oper.logg.Debugf("Get file [%s] [%s]", collection, filename) - descrExists, fileDescr, err := oper.mdb.GetFileByCollection(collection, filename) + descrExists, fileDescr, err := oper.mdb.GetFileByCollection(ctx, collection, filename) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -209,7 +210,7 @@ type DeleteFileParams struct { } type DeleteFileResult struct{} -func (oper *Operator) DeleteFile(param *DeleteFileParams) (int, *DeleteFileResult, error) { +func (oper *Operator) DeleteFile(ctx context.Context, param *DeleteFileParams) (int, *DeleteFileResult, error) { var err error res := &DeleteFileResult{} code := http.StatusOK @@ -222,13 +223,13 @@ func (oper *Operator) DeleteFile(param *DeleteFileParams) (int, *DeleteFileResul filename := path.Base(xfilepath) collection := path.Dir(xfilepath) - exist, _, err := oper.mdb.GetFileByCollection(collection, filename) + exist, _, err := oper.mdb.GetFileByCollection(ctx, collection, filename) if err != nil { code = http.StatusInternalServerError return code, res, err } if exist { - err = oper.mdb.DeleteFileByCollection(collection, filename) + err = oper.mdb.DeleteFileByCollection(ctx, collection, filename) if err != nil { code = http.StatusInternalServerError return code, res, err @@ -250,7 +251,7 @@ type ListFilesResult struct { FileDescrs []descr.File } -func (oper *Operator) ListFiles(param *ListFilesParams) (int, *ListFilesResult, error) { +func (oper *Operator) ListFiles(ctx context.Context, param *ListFilesParams) (int, *ListFilesResult, error) { var err error res := &ListFilesResult{ FileDescrs: make([]descr.File, 0), @@ -267,7 +268,7 @@ func (oper *Operator) ListFiles(param *ListFilesParams) (int, *ListFilesResult, oper.logg.Debugf("List files by %s", collection) - fileDescrs, err := oper.mdb.ListAllFiles() + fileDescrs, err := oper.mdb.ListAllFiles(ctx) if err != nil { code := http.StatusInternalServerError return code, res, err diff --git a/app/router/context.go b/app/router/context.go index b17d16d..cbfef2d 100644 --- a/app/router/context.go +++ b/app/router/context.go @@ -47,3 +47,7 @@ func (rctx *Context) SendText(payload string) { func (rctx *Context) GetHeader(key string) string { return rctx.Request.Header.Get(key) } + +func (rctx *Context) GetContext() context.Context { + return rctx.Request.Context() +} diff --git a/app/service/service.go b/app/service/service.go index e11e3d5..cdb0d89 100644 --- a/app/service/service.go +++ b/app/service/service.go @@ -68,6 +68,10 @@ func (svc *Service) Build() error { svc.rout.Delete("/v3/api/file/{filepath}", svc.hand.DeleteFile) svc.rout.Get("/v3/api/files/{filepath}", svc.hand.ListFiles) + svc.rout.Get("/v2/", svc.hand.GetVersion) + + svc.rout.NotFound(svc.hand.NotFound) + selector := svc.rout.Selector() for _, item := range selector.Routes { svc.logg.Infof("%s\t%s", item.Method, item.RawPath) diff --git a/pkg/client/client.go b/pkg/client/client.go index 420bffc..59013e0 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "strconv" + "time" ) type Client struct { @@ -27,10 +28,12 @@ func NewClientWithAuth(username, password string) *Client { } } -func (cli *Client) ServiceHello(ctx context.Context, ref string) (bool, error) { +func (cli *Client) ServiceHello(ctx context.Context, ref string, timeout time.Duration) (bool, error) { var res bool var err error + ctx, _ = context.WithTimeout(ctx, timeout) + ref, err = convertServiceRefer(ref) if err != nil { return res, err diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go deleted file mode 100644 index fadf287..0000000 --- a/pkg/client/client_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package client - -import ( - "context" - "fmt" - "math/rand" - "os" - "path/filepath" - "sync" - "testing" - "time" - - "mstore/app/server" - - "github.com/stretchr/testify/require" -) - -func TestService(t *testing.T) { - var srvport int64 = 10250 - srvdir := t.TempDir() - srvaddr := fmt.Sprintf("127.0.0.1:%d", srvport) - - srv, err := server.NewServer() - require.NoError(t, err) - { - err = srv.Configure() - require.NoError(t, err) - - srv.SetDatadir(srvdir) - srv.SetLogdir(srvdir) - srv.SetRundir(srvdir) - srv.SetPort(srvport) - - err = srv.Build() - require.NoError(t, err) - - var svcWG sync.WaitGroup - errPipe := make(chan error, 5) - - startFunc := func() { - err := srv.Service().Run() - errPipe <- err - svcWG.Done() - } - - stopFunc := func() { - srv.Service().Stop() - svcWG.Wait() - err = <-errPipe - require.NoError(t, err) - } - defer stopFunc() - - svcWG.Add(1) - go startFunc() - time.Sleep(1 * time.Second) - } - { - // ServiceHello - fmt.Printf("=== ServiceHello ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - helloRes, err := cli.ServiceHello(ctx, srvaddr+"/hello") - require.NoError(t, err) - require.True(t, helloRes) - } - filesize := 32 - { - // PutFile - tmpdir := t.TempDir() - tmpfile := filepath.Join(tmpdir, "foo.bin") - - filedata := make([]byte, filesize) - _, err = rand.Read(filedata) - require.NoError(t, err) - - err := os.WriteFile(tmpfile, filedata, 0666) - require.NoError(t, err) - - fmt.Printf("=== PutFile ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - err = cli.PutFile(ctx, tmpfile, srvaddr+"/foo.bin") - require.NoError(t, err) - } - { - // FileExists - fmt.Printf("=== FileExists ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - exists, err := cli.FileExists(ctx, srvaddr+"/foo.bin") - require.NoError(t, err) - require.True(t, exists) - } - { - // GetFile - fmt.Printf("=== GetFile ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - tmpdir := t.TempDir() - tmpfile := filepath.Join(tmpdir, "foo.bin") - - recsize, err := cli.GetFile(ctx, srvaddr+"/foo.bin", tmpfile) - require.NoError(t, err) - require.Equal(t, recsize, int64(filesize)) - } - { - // DeleteFile - fmt.Printf("=== DeleteFile ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - tmpdir := t.TempDir() - tmpfile := filepath.Join(tmpdir, "foo.bin") - - err = cli.DeleteFile(ctx, srvaddr+"/foo.bin", tmpfile) - require.NoError(t, err) - } - { - // !FileExists - fmt.Printf("=== FileExists ===\n") - cli := NewClient() - ctx := context.Background() - ctx, _ = context.WithTimeout(ctx, 1*time.Second) - - exists, err := cli.FileExists(ctx, srvaddr+"/foo.bin") - require.NoError(t, err) - require.False(t, exists) - } - -}