云存储接入客户端交互
This commit is contained in:
parent
f882b611f4
commit
d8ce73cd29
|
@ -48,6 +48,8 @@ func (s *Server) InitRouters(rt gin.IRoutes, ah *auth.Auth) {
|
|||
rt.POST(cliapi.UserSpaceDownloadPackagePath, certAuth, s.UserSpace().DownloadPackage)
|
||||
rt.POST(cliapi.UserSpaceCreatePackagePath, certAuth, s.UserSpace().CreatePackage)
|
||||
rt.GET(cliapi.UserSpaceGetPath, certAuth, s.UserSpace().Get)
|
||||
rt.GET(cliapi.UserSpaceGetByNamePath, certAuth, s.UserSpace().GetByName)
|
||||
rt.GET(cliapi.UserSpaceGetAllPath, certAuth, s.UserSpace().GetAll)
|
||||
rt.POST(cliapi.UserSpaceCreatePath, certAuth, s.UserSpace().Create)
|
||||
rt.POST(cliapi.UserSpaceUpdatePath, certAuth, s.UserSpace().Update)
|
||||
rt.POST(cliapi.UserSpaceDeletePath, certAuth, s.UserSpace().Delete)
|
||||
|
|
|
@ -85,6 +85,43 @@ func (s *UserSpaceService) Get(ctx *gin.Context) {
|
|||
}))
|
||||
}
|
||||
|
||||
func (s *UserSpaceService) GetByName(ctx *gin.Context) {
|
||||
log := logger.WithField("HTTP", "UserSpace.GetByName")
|
||||
|
||||
var req cliapi.UserSpaceGetByName
|
||||
if err := ctx.ShouldBindQuery(&req); err != nil {
|
||||
log.Warnf("binding query: %s", err.Error())
|
||||
ctx.JSON(http.StatusBadRequest, types.Failed(ecode.BadArgument, "missing argument or invalid argument"))
|
||||
return
|
||||
}
|
||||
|
||||
info, err := s.svc.UserSpaceSvc().GetByName(req.Name)
|
||||
if err != nil {
|
||||
log.Warnf("getting info: %s", err.Error())
|
||||
ctx.JSON(http.StatusOK, types.Failed(ecode.OperationFailed, "get userspace info failed"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, types.OK(cliapi.UserSpaceGetByNameResp{
|
||||
UserSpace: info,
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *UserSpaceService) GetAll(ctx *gin.Context) {
|
||||
log := logger.WithField("HTTP", "UserSpace.GetAll")
|
||||
|
||||
allInfos, err := s.svc.UserSpaceSvc().GetAll()
|
||||
if err != nil {
|
||||
log.Warnf("getting info: %s", err.Error())
|
||||
ctx.JSON(http.StatusOK, types.Failed(ecode.OperationFailed, "get userspaces info failed"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, types.OK(cliapi.UserSpaceGetAllResp{
|
||||
UserSpaces: allInfos,
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *UserSpaceService) Create(ctx *gin.Context) {
|
||||
log := logger.WithField("HTTP", "UserSpace.Create")
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ func (svc *UserSpaceService) GetByName(name string) (clitypes.UserSpace, error)
|
|||
return svc.DB.UserSpace().GetByName(svc.DB.DefCtx(), name)
|
||||
}
|
||||
|
||||
func (svc *UserSpaceService) GetAll() ([]clitypes.UserSpace, error) {
|
||||
return svc.DB.UserSpace().GetAll(svc.DB.DefCtx())
|
||||
}
|
||||
|
||||
func (svc *UserSpaceService) Create(req cliapi.UserSpaceCreate) (*cliapi.UserSpaceCreateResp, *ecode.CodeError) {
|
||||
db2 := svc.DB
|
||||
space, err := db.DoTx01(db2, func(tx db.SQLContext) (clitypes.UserSpace, error) {
|
||||
|
|
|
@ -78,6 +78,49 @@ func (c *Client) UserSpaceGet(req UserSpaceGet) (*UserSpaceGetResp, error) {
|
|||
return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceGetResp{})
|
||||
}
|
||||
|
||||
const UserSpaceGetByNamePath = "/userspace/getByName"
|
||||
|
||||
type UserSpaceGetByName struct {
|
||||
Name string `form:"name" url:"name" binding:"required"`
|
||||
}
|
||||
|
||||
func (r *UserSpaceGetByName) MakeParam() *sdks.RequestParam {
|
||||
return sdks.MakeQueryParam(http.MethodGet, UserSpaceGetByNamePath, r)
|
||||
}
|
||||
|
||||
type UserSpaceGetByNameResp struct {
|
||||
clitypes.UserSpace
|
||||
}
|
||||
|
||||
func (r *UserSpaceGetByNameResp) ParseResponse(resp *http.Response) error {
|
||||
return sdks.ParseCodeDataJSONResponse(resp, r)
|
||||
}
|
||||
|
||||
func (c *Client) UserSpaceGetByName(req UserSpaceGetByName) (*UserSpaceGetByNameResp, error) {
|
||||
return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceGetByNameResp{})
|
||||
}
|
||||
|
||||
const UserSpaceGetAllPath = "/userspace/getAll"
|
||||
|
||||
type UserSpaceGetAll struct{}
|
||||
|
||||
func (r *UserSpaceGetAll) MakeParam() *sdks.RequestParam {
|
||||
return sdks.MakeQueryParam(http.MethodGet, UserSpaceGetAllPath, nil)
|
||||
}
|
||||
|
||||
type UserSpaceGetAllResp struct {
|
||||
UserSpaces []clitypes.UserSpace `json:"userSpaces"`
|
||||
}
|
||||
|
||||
func (r *UserSpaceGetAllResp) ParseResponse(resp *http.Response) error {
|
||||
return sdks.ParseCodeDataJSONResponse(resp, r)
|
||||
}
|
||||
|
||||
func (c *Client) UserSpaceGetAll() (*UserSpaceGetAllResp, error) {
|
||||
req := UserSpaceGetAll{}
|
||||
return JSONAPI(&c.cfg, c.httpCli, &req, &UserSpaceGetAllResp{})
|
||||
}
|
||||
|
||||
// 创建用户空间
|
||||
const UserSpaceCreatePath = "/userspace/create"
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitlink.org.cn/cloudream/common/pkgs/types"
|
||||
"gitlink.org.cn/cloudream/common/utils/serder"
|
||||
)
|
||||
|
||||
type StorageCredential interface {
|
||||
// fmt.Stringer
|
||||
GetStorageCredentialType() string
|
||||
String(showPassword bool) string
|
||||
}
|
||||
|
||||
var _ = serder.UseTypeUnionInternallyTagged(types.Ref(types.NewTypeUnion[StorageCredential](
|
||||
|
@ -26,6 +30,10 @@ type LocalCred struct {
|
|||
RootDir string `json:"rootDir"`
|
||||
}
|
||||
|
||||
func (c *LocalCred) String(showPassword bool) string {
|
||||
return fmt.Sprintf("RootDir=%s", c.RootDir)
|
||||
}
|
||||
|
||||
// type MashupCred struct {
|
||||
// StorageCredential `json:"-"`
|
||||
// serder.Metadata `union:"Mashup"`
|
||||
|
@ -41,6 +49,14 @@ type OSSCred struct {
|
|||
SK string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
func (c *OSSCred) String(showPassword bool) string {
|
||||
maskedSK := "****"
|
||||
if showPassword {
|
||||
maskedSK = c.SK
|
||||
}
|
||||
return fmt.Sprintf("AK=%s, SK=%s", c.AK, maskedSK)
|
||||
}
|
||||
|
||||
type OBSCred struct {
|
||||
StorageCredential `json:"-"`
|
||||
serder.Metadata `union:"OBS"`
|
||||
|
@ -49,6 +65,14 @@ type OBSCred struct {
|
|||
SK string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
func (c *OBSCred) String(showPassword bool) string {
|
||||
maskedSK := "****"
|
||||
if showPassword {
|
||||
maskedSK = c.SK
|
||||
}
|
||||
return fmt.Sprintf("AK=%s, SK=%s", c.AK, maskedSK)
|
||||
}
|
||||
|
||||
type COSCred struct {
|
||||
StorageCredential `json:"-"`
|
||||
serder.Metadata `union:"COS"`
|
||||
|
@ -57,6 +81,14 @@ type COSCred struct {
|
|||
SK string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
func (c *COSCred) String(showPassword bool) string {
|
||||
maskedSK := "****"
|
||||
if showPassword {
|
||||
maskedSK = c.SK
|
||||
}
|
||||
return fmt.Sprintf("AK=%s, SK=%s", c.AK, maskedSK)
|
||||
}
|
||||
|
||||
type EFileCred struct {
|
||||
StorageCredential `json:"-"`
|
||||
serder.Metadata `union:"EFile"`
|
||||
|
@ -69,6 +101,14 @@ type EFileCred struct {
|
|||
OrgID string `json:"orgID"`
|
||||
}
|
||||
|
||||
func (c *EFileCred) String(showPassword bool) string {
|
||||
maskedSK := "****"
|
||||
if showPassword {
|
||||
maskedSK = c.Password
|
||||
}
|
||||
return fmt.Sprintf("TokenURL=%s, APIURL=%s, TokenExpire=%d, User=%s, Password=%s, OrgID=%s", c.TokenURL, c.APIURL, c.TokenExpire, c.User, maskedSK, c.OrgID)
|
||||
}
|
||||
|
||||
// 通用的S3协议的存储服务
|
||||
type S3Cred struct {
|
||||
StorageCredential `json:"-"`
|
||||
|
@ -77,3 +117,11 @@ type S3Cred struct {
|
|||
AK string `json:"accessKeyId"`
|
||||
SK string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
func (c *S3Cred) String(showPassword bool) string {
|
||||
maskedSK := "****"
|
||||
if showPassword {
|
||||
maskedSK = c.SK
|
||||
}
|
||||
return fmt.Sprintf("AK=%s, SK=%s", c.AK, maskedSK)
|
||||
}
|
||||
|
|
15
go.mod
15
go.mod
|
@ -49,19 +49,31 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.6 // indirect
|
||||
github.com/aws/smithy-go v1.22.2 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-tty v0.0.3 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pkg/term v1.2.0-beta.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
|
@ -69,6 +81,7 @@ require (
|
|||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.mongodb.org/mongo-driver v1.12.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect
|
||||
|
@ -81,6 +94,8 @@ require (
|
|||
require (
|
||||
github.com/antonfisher/nested-logrus-formatter v1.3.1 // indirect
|
||||
github.com/c-bata/go-prompt v0.2.6
|
||||
github.com/charmbracelet/bubbletea v1.3.5
|
||||
github.com/chzyer/readline v1.5.1
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
|
|
34
go.sum
34
go.sum
|
@ -28,6 +28,8 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPx
|
|||
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY=
|
||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
|
@ -35,6 +37,22 @@ github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4
|
|||
github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI=
|
||||
github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc=
|
||||
github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
|
||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
|
@ -50,6 +68,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc
|
|||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
|
@ -143,6 +163,8 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3v
|
|||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
|
||||
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
|
@ -155,6 +177,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
|||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
|
@ -171,6 +195,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
|||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
|
@ -225,6 +255,8 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
|
|||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XDc=
|
||||
|
@ -291,6 +323,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
@ -2,4 +2,5 @@ package all
|
|||
|
||||
import (
|
||||
_ "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd/bucket"
|
||||
_ "gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd/userspace"
|
||||
)
|
||||
|
|
|
@ -74,7 +74,7 @@ func RootExecute() {
|
|||
}
|
||||
|
||||
if endpoint == "" {
|
||||
endpoint = "https://127.0.0.1:7890"
|
||||
endpoint = "https://127.0.0.1:8890"
|
||||
}
|
||||
|
||||
cli := cliapi.NewClient(api.Config{
|
||||
|
|
|
@ -0,0 +1,563 @@
|
|||
package userspace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/spf13/cobra"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
|
||||
|
||||
cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
|
||||
)
|
||||
|
||||
type MyUserSpace struct {
|
||||
api.UserSpaceCreate
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd := cobra.Command{
|
||||
Use: "create",
|
||||
Short: "add a new cloud storage",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := cmd.GetCmdCtx(c)
|
||||
create(c, ctx)
|
||||
},
|
||||
}
|
||||
UserSpaceCmd.AddCommand(&cmd)
|
||||
}
|
||||
|
||||
func create(c *cobra.Command, ctx *cmd.CommandContext) {
|
||||
var userSpace MyUserSpace
|
||||
|
||||
rl, err := readline.New("> ")
|
||||
if err != nil {
|
||||
fmt.Printf("初始化命令行失败: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer rl.Close()
|
||||
|
||||
rl.SetPrompt("\033[36m请输入存储服务名称(Name): \033[0m")
|
||||
name, err := rl.Readline()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
userSpace.Name = name
|
||||
|
||||
storageType, err := promptSelectStorage()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch storageType {
|
||||
case "Local":
|
||||
err = userSpace.collectLocalConfig(rl)
|
||||
case "OBS":
|
||||
err = userSpace.collectObsConfig(rl)
|
||||
case "OSS":
|
||||
err = userSpace.collectOssConfig(rl)
|
||||
case "COS":
|
||||
err = userSpace.collectCosConfig(rl)
|
||||
case "EFile":
|
||||
err = userSpace.collectEfileConfig(rl)
|
||||
case "S3":
|
||||
err = userSpace.collectS3Config(rl)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = userSpace.collectShardStore(rl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = userSpace.collectWorkingDir(rl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = ctx.Client.UserSpaceCreate(userSpace.UserSpaceCreate)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m保存配置失败: %v\033[0m", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\033[32m配置保存成功!\033[0m")
|
||||
}
|
||||
|
||||
func promptSelectStorage() (string, error) {
|
||||
rl, _ := readline.NewEx(&readline.Config{
|
||||
Prompt: "\033[36m»\033[0m ",
|
||||
HistoryFile: "/tmp/storage_history.txt",
|
||||
InterruptPrompt: "^C",
|
||||
})
|
||||
defer rl.Close()
|
||||
|
||||
fmt.Println("\033[1;36m请选择存储类型(StorageType):\033[0m")
|
||||
options := []string{"Local", "OBS", "OSS", "COS", "EFile", "S3"}
|
||||
for i, option := range options {
|
||||
fmt.Printf("\033[33m%d. %s\033[0m\n", i+1, option)
|
||||
}
|
||||
|
||||
for {
|
||||
line, err := rl.Readline()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
trimmed := strings.TrimSpace(line)
|
||||
switch trimmed {
|
||||
case "1":
|
||||
return "Local", nil
|
||||
case "2":
|
||||
return "OBS", nil
|
||||
case "3":
|
||||
return "OSS", nil
|
||||
case "4":
|
||||
return "COS", nil
|
||||
case "5":
|
||||
return "EFile", nil
|
||||
case "6":
|
||||
return "S3", nil
|
||||
default:
|
||||
fmt.Printf("\033[31m错误: 无效选项 '%s',请输入序号!\033[0m\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectLocalConfig(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入StorageName: \033[0m")
|
||||
storageName, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Location: \033[0m")
|
||||
location, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入RootDir: \033[0m")
|
||||
rootDir, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userSpace.Storage = &cortypes.LocalType{
|
||||
Type: "Local",
|
||||
Location: cortypes.Location{
|
||||
StorageName: storageName,
|
||||
Location: location,
|
||||
},
|
||||
}
|
||||
userSpace.Credential = &cortypes.LocalCred{
|
||||
Type: "Local",
|
||||
RootDir: rootDir,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectObsConfig(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入Region: \033[0m")
|
||||
region, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Endpoint: \033[0m")
|
||||
endpoint, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Bucket: \033[0m")
|
||||
bucket, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入ProjectID: \033[0m")
|
||||
projectID, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Storage = &cortypes.OBSType{
|
||||
Type: "OBS",
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
Bucket: bucket,
|
||||
ProjectID: projectID,
|
||||
}
|
||||
userSpace.Credential = &cortypes.OBSCred{
|
||||
Type: "OBS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否支持存储服务间直传文件?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.S2STransferFeature{
|
||||
Type: "S2STransfer",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
fmt.Println("\033[36m不支持存储服务间直传文件 \033[0m")
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectOssConfig(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入Region: \033[0m")
|
||||
region, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Endpoint: \033[0m")
|
||||
endpoint, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Bucket: \033[0m")
|
||||
bucket, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Storage = &cortypes.OSSType{
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
Bucket: bucket,
|
||||
}
|
||||
userSpace.Credential = &cortypes.OSSCred{
|
||||
Type: "OSS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectCosConfig(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入Region: \033[0m")
|
||||
region, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Endpoint: \033[0m")
|
||||
endpoint, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Bucket: \033[0m")
|
||||
bucket, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Storage = &cortypes.COSType{
|
||||
Type: "COS",
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
Bucket: bucket,
|
||||
}
|
||||
userSpace.Credential = &cortypes.COSCred{
|
||||
Type: "COS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectEfileConfig(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入ClusterID: \033[0m")
|
||||
clusterID, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入TokenURL: \033[0m")
|
||||
tokenURL, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入APIURL: \033[0m")
|
||||
apiURL, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenExpire := 0
|
||||
for {
|
||||
rl.SetPrompt("\033[36m请输入TokenExpire: \033[0m")
|
||||
valueInt, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(valueInt) == "" {
|
||||
fmt.Println("\033[31m错误:输入不能为空,请输入正整数\033[0m")
|
||||
continue
|
||||
}
|
||||
num, err := strconv.ParseInt(valueInt, 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m错误:'%s' 不是有效整数,请输入正整数\033[0m\n", valueInt)
|
||||
continue
|
||||
}
|
||||
if num <= 0 {
|
||||
fmt.Printf("\033[31m错误:%d 不是正整数,请输入大于 0 的整数\033[0m\n", num)
|
||||
continue
|
||||
}
|
||||
tokenExpire = int(num)
|
||||
break
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入User: \033[0m")
|
||||
user, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
passwordBytes, err := rl.ReadPassword("\033[36m请输入Password: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
password := string(passwordBytes)
|
||||
|
||||
rl.SetPrompt("\033[36m请输入OrgID: \033[0m")
|
||||
orgID, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userSpace.Storage = &cortypes.EFileType{
|
||||
Type: "EFile",
|
||||
ClusterID: clusterID,
|
||||
}
|
||||
userSpace.Credential = &cortypes.EFileCred{
|
||||
Type: "EFile",
|
||||
TokenURL: tokenURL,
|
||||
APIURL: apiURL,
|
||||
TokenExpire: tokenExpire,
|
||||
User: user,
|
||||
Password: password,
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否提供能进行EC计算的接口?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.ECMultiplierFeature{
|
||||
Type: "ECMultiplier",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
fmt.Println("\033[36m未提供能进行EC计算的接口 \033[0m")
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectS3Config(rl *readline.Instance) error {
|
||||
var err error
|
||||
rl.SetPrompt("\033[36m请输入Region: \033[0m")
|
||||
region, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Endpoint: \033[0m")
|
||||
endpoint, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入Bucket: \033[0m")
|
||||
bucket, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Storage = &cortypes.S3Type{
|
||||
Type: "S3",
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
Bucket: bucket,
|
||||
}
|
||||
userSpace.Credential = &cortypes.S3Cred{
|
||||
Type: "S3",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否支持分段上传?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.MultipartUploadFeature{
|
||||
Type: "MultipartUpload",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
fmt.Println("\033[36m不支持分段上传 \033[0m")
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectShardStore(rl *readline.Instance) error {
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否开启分片存储功能?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
for {
|
||||
rl.SetPrompt("\033[36m请输入最大Size: \033[0m")
|
||||
sizeInput, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(sizeInput) == "" {
|
||||
fmt.Println("\033[31m错误:输入不能为空31m错误:输入不能为空,请输入正整数\033[0m")
|
||||
continue
|
||||
}
|
||||
|
||||
maxSize, err := strconv.ParseInt(sizeInput, 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m错误:'%s' 不是有效整数,请输入正整数\033[0m\n", sizeInput)
|
||||
continue
|
||||
}
|
||||
if maxSize <= 0 {
|
||||
fmt.Printf("\033[31m错误:%d 不是正整数,请输入大于 0 的整数\033[0m\n", maxSize)
|
||||
continue
|
||||
}
|
||||
userSpace.ShardStore = &cortypes.ShardStoreUserConfig{
|
||||
MaxSize: maxSize,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
case "n", "no":
|
||||
fmt.Println("\033[31m分片存储未启用 \033[0m")
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *MyUserSpace) collectWorkingDir(rl *readline.Instance) error {
|
||||
for {
|
||||
rl.SetPrompt("\033[36m默认工作路径(WorkingDir)为jcs,是否修改?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
rl.SetPrompt("\033[36m请输入新的工作路径(WorkingDir): \033[0m")
|
||||
newValue, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if newValue != "" {
|
||||
userSpace.WorkingDir = newValue
|
||||
}
|
||||
return nil
|
||||
case "n", "no":
|
||||
userSpace.WorkingDir = "jcs"
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package userspace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/spf13/cobra"
|
||||
cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
|
||||
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmd := cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "delete a cloud storage",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := cmd.GetCmdCtx(c)
|
||||
delete(c, ctx)
|
||||
},
|
||||
}
|
||||
UserSpaceCmd.AddCommand(&cmd)
|
||||
}
|
||||
|
||||
func delete(c *cobra.Command, ctx *cmd.CommandContext) {
|
||||
rl, err := readline.New("> ")
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m初始化命令行失败: %v\033[0m\n", err)
|
||||
return
|
||||
}
|
||||
defer rl.Close()
|
||||
|
||||
fmt.Printf("\033[1;36m请选择删除依据: \033[0m\n")
|
||||
options := []string{"ID", "Name"}
|
||||
for i, option := range options {
|
||||
fmt.Printf("\033[33m%d. %s\033[0m\n", i+1, option)
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m> \033[0m")
|
||||
line, err := rl.Readline()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var userSpace clitypes.UserSpace
|
||||
trimmed := strings.TrimSpace(line)
|
||||
switch trimmed {
|
||||
case "1":
|
||||
rl.SetPrompt("\033[36m请输入云存储ID(ID): \033[0m")
|
||||
idInput, err := rl.Readline()
|
||||
if err != nil || idInput == "" {
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(strings.TrimSpace(idInput), 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31mID 格式错误: %v\033[0m\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := ctx.Client.UserSpaceGet(cliapi.UserSpaceGet{
|
||||
UserSpaceID: clitypes.UserSpaceID(id),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m保存配置失败: %v\033[0m", err)
|
||||
return
|
||||
}
|
||||
userSpace = resp.UserSpace
|
||||
|
||||
case "2":
|
||||
rl.SetPrompt("\033[36m请输入云存储名称(Name): \033[0m")
|
||||
nameInput, err := rl.Readline()
|
||||
if err != nil || nameInput == "" {
|
||||
fmt.Println("\033[31m输入已取消\033[0m")
|
||||
return
|
||||
}
|
||||
name := strings.TrimSpace(nameInput)
|
||||
|
||||
resp, err := ctx.Client.UserSpaceGetByName(cliapi.UserSpaceGetByName{
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m保存配置失败: %v\033[0m", err)
|
||||
return
|
||||
}
|
||||
userSpace = resp.UserSpace
|
||||
|
||||
default:
|
||||
fmt.Printf("\033[31m错误: 无效选项 '%s',请输入序号!\033[0m\n", line)
|
||||
}
|
||||
|
||||
fmt.Println("\n\033[1;36m找到云存储:\033[0m")
|
||||
fmt.Printf("\033[1;36mID:%d 名称:%s 类型:%s\033[0m\n", userSpace.UserSpaceID, userSpace.Name, userSpace.Storage.GetStorageType())
|
||||
|
||||
rl.SetPrompt("\033[31m确认删除?(y/n): \033[0m")
|
||||
confirm, err := rl.Readline()
|
||||
if err != nil || strings.ToLower(strings.TrimSpace(confirm)) != "y" {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = ctx.Client.UserSpaceDelete(cliapi.UserSpaceDelete{
|
||||
UserSpaceID: userSpace.UserSpaceID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m删除失败: %v\033[0m\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("\n\033[32m删除成功: %s\033[0m\n", userSpace.Name)
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package userspace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/spf13/cobra"
|
||||
cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
|
||||
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
|
||||
)
|
||||
|
||||
func init() {
|
||||
var opt lsOpt
|
||||
cmd := cobra.Command{
|
||||
Use: "ls",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := cmd.GetCmdCtx(c)
|
||||
ls(c, ctx, opt, args)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opt.ByID, "id", "", false, "按id查询")
|
||||
cmd.Flags().BoolVarP(&opt.ShowPassword, "password", "p", false, "显示密码信息,请在安全环境下使用")
|
||||
UserSpaceCmd.AddCommand(&cmd)
|
||||
}
|
||||
|
||||
type lsOpt struct {
|
||||
ByID bool
|
||||
ShowPassword bool
|
||||
}
|
||||
|
||||
func ls(c *cobra.Command, ctx *cmd.CommandContext, opt lsOpt, args []string) {
|
||||
// 仅ls无参数
|
||||
if len(args) == 0 {
|
||||
resp, err := ctx.Client.UserSpaceGetAll()
|
||||
if err != nil {
|
||||
cmd.ErrorExitln(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("total: %d\n", len(resp.UserSpaces))
|
||||
tb := table.NewWriter()
|
||||
tb.AppendHeader(table.Row{"ID", "Name", "StorageType"})
|
||||
for _, userSpace := range resp.UserSpaces {
|
||||
tb.AppendRow(table.Row{userSpace.UserSpaceID, userSpace.Name, userSpace.Storage.GetStorageType()})
|
||||
}
|
||||
fmt.Println(tb.Render())
|
||||
return
|
||||
}
|
||||
|
||||
searchKey := args[0]
|
||||
var userSpace *clitypes.UserSpace
|
||||
if opt.ByID {
|
||||
id, err := strconv.Atoi(searchKey)
|
||||
if err != nil {
|
||||
cmd.ErrorExitln("ID必须是数字")
|
||||
return
|
||||
}
|
||||
|
||||
result, err := ctx.Client.UserSpaceGet(cliapi.UserSpaceGet{
|
||||
UserSpaceID: clitypes.UserSpaceID(id),
|
||||
})
|
||||
if err != nil {
|
||||
cmd.ErrorExitln(err.Error())
|
||||
return
|
||||
}
|
||||
userSpace = &result.UserSpace
|
||||
|
||||
} else {
|
||||
result, err := ctx.Client.UserSpaceGetByName(cliapi.UserSpaceGetByName{
|
||||
Name: searchKey,
|
||||
})
|
||||
if err != nil {
|
||||
cmd.ErrorExitln(err.Error())
|
||||
return
|
||||
}
|
||||
userSpace = &result.UserSpace
|
||||
}
|
||||
|
||||
if userSpace == nil {
|
||||
cmd.ErrorExitln(fmt.Sprintf("未找到匹配的云存储: %s", searchKey))
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("\n\033[1;36m云存储详情\033[0m")
|
||||
fmt.Println("----------------------------------")
|
||||
fmt.Printf("\033[1m%-8s\033[0m %d\n", "ID:", userSpace.UserSpaceID)
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "名称:", userSpace.Name)
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "类型:", userSpace.Storage.GetStorageType())
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "Location:", userSpace.Storage.GetLocation().Location)
|
||||
if opt.ShowPassword {
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "Credential:", userSpace.Credential.String(true))
|
||||
} else {
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "Credential:", userSpace.Credential.String(false))
|
||||
}
|
||||
|
||||
if len(userSpace.Features) > 0 {
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "Features:", userSpace.Features[0].GetFeatureType())
|
||||
}
|
||||
fmt.Printf("\033[1m%-8s\033[0m %s\n", "WorkingDir:", userSpace.WorkingDir)
|
||||
fmt.Println("----------------------------------")
|
||||
|
||||
}
|
|
@ -0,0 +1,321 @@
|
|||
package userspace
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/chzyer/readline"
|
||||
"github.com/spf13/cobra"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
|
||||
cliapi "gitlink.org.cn/cloudream/jcs-pub/client/sdk/api/v1"
|
||||
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
|
||||
cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
|
||||
)
|
||||
|
||||
type UserSpaceUpdate struct {
|
||||
api.UserSpaceUpdate
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd := cobra.Command{
|
||||
Use: "update",
|
||||
Short: "update a new cloud storage",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
ctx := cmd.GetCmdCtx(c)
|
||||
update(c, ctx)
|
||||
},
|
||||
}
|
||||
UserSpaceCmd.AddCommand(&cmd)
|
||||
}
|
||||
|
||||
func update(c *cobra.Command, ctx *cmd.CommandContext) {
|
||||
rl, err := readline.New("> ")
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m初始化命令行失败: %v\033[0m\n", err)
|
||||
return
|
||||
}
|
||||
defer rl.Close()
|
||||
|
||||
rl.SetPrompt("\033[36m请输入云存储ID(ID): \033[0m")
|
||||
idInput, err := rl.Readline()
|
||||
if err != nil || idInput == "" {
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(strings.TrimSpace(idInput), 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31mID 格式错误: %v\033[0m\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := ctx.Client.UserSpaceGet(cliapi.UserSpaceGet{
|
||||
UserSpaceID: clitypes.UserSpaceID(id),
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m云存储id=%d 不存在: %v\033[0m\n", id, err)
|
||||
return
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入修改后的存储服务名称(Name): \033[0m")
|
||||
name, err := rl.Readline()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var userSpaceUpdate UserSpaceUpdate
|
||||
userSpaceUpdate.UserSpaceID = clitypes.UserSpaceID(id)
|
||||
userSpaceUpdate.Name = name
|
||||
|
||||
storageType := resp.UserSpace.Storage.GetStorageType()
|
||||
switch storageType {
|
||||
case "Local":
|
||||
err = userSpaceUpdate.collectLocalConfig(rl)
|
||||
case "OBS":
|
||||
err = userSpaceUpdate.collectObsConfig(rl)
|
||||
case "OSS":
|
||||
err = userSpaceUpdate.collectOssConfig(rl)
|
||||
case "COS":
|
||||
err = userSpaceUpdate.collectCosConfig(rl)
|
||||
case "EFile":
|
||||
err = userSpaceUpdate.collectEfileConfig(rl)
|
||||
case "S3":
|
||||
err = userSpaceUpdate.collectS3Config(rl)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = ctx.Client.UserSpaceUpdate(userSpaceUpdate.UserSpaceUpdate)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m更新配置失败: %v\033[0m", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("\033[32m配置更新成功!\033[0m")
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectLocalConfig(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入RootDir: \033[0m")
|
||||
rootDir, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userSpace.Credential = &cortypes.LocalCred{
|
||||
Type: "Local",
|
||||
RootDir: rootDir,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectObsConfig(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Credential = &cortypes.OBSCred{
|
||||
Type: "OBS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否支持存储服务间直传文件?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.S2STransferFeature{
|
||||
Type: "S2STransfer",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
userSpace.Features = nil
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectOssConfig(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Credential = &cortypes.OSSCred{
|
||||
Type: "OSS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectCosConfig(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Credential = &cortypes.COSCred{
|
||||
Type: "COS",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectEfileConfig(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入TokenURL: \033[0m")
|
||||
tokenURL, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入APIURL: \033[0m")
|
||||
apiURL, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokenExpire := 0
|
||||
for {
|
||||
rl.SetPrompt("\033[36m请输入TokenExpire: \033[0m")
|
||||
valueInt, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(valueInt) == "" {
|
||||
fmt.Println("\033[31m错误:输入不能为空,请输入正整数\033[0m")
|
||||
continue
|
||||
}
|
||||
num, err := strconv.ParseInt(valueInt, 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("\033[31m错误:'%s' 不是有效整数,请输入正整数\033[0m\n", valueInt)
|
||||
continue
|
||||
}
|
||||
if num <= 0 {
|
||||
fmt.Printf("\033[31m错误:%d 不是正整数,请输入大于 0 的整数\033[0m\n", num)
|
||||
continue
|
||||
}
|
||||
tokenExpire = int(num)
|
||||
break
|
||||
}
|
||||
|
||||
rl.SetPrompt("\033[36m请输入User: \033[0m")
|
||||
user, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
passwordBytes, err := rl.ReadPassword("\033[36m请输入Password: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
password := string(passwordBytes)
|
||||
|
||||
rl.SetPrompt("\033[36m请输入OrgID: \033[0m")
|
||||
orgID, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userSpace.Credential = &cortypes.EFileCred{
|
||||
Type: "EFile",
|
||||
TokenURL: tokenURL,
|
||||
APIURL: apiURL,
|
||||
TokenExpire: tokenExpire,
|
||||
User: user,
|
||||
Password: password,
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否提供能进行EC计算的接口?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.ECMultiplierFeature{
|
||||
Type: "ECMultiplier",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
userSpace.Features = nil
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (userSpace *UserSpaceUpdate) collectS3Config(rl *readline.Instance) error {
|
||||
rl.SetPrompt("\033[36m请输入AccessKeyID: \033[0m")
|
||||
accessKey, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secretBytes, err := rl.ReadPassword("\033[36m请输入AccessKeySecret: \033[0m")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretKey := string(secretBytes)
|
||||
|
||||
userSpace.Credential = &cortypes.S3Cred{
|
||||
Type: "S3",
|
||||
AK: accessKey,
|
||||
SK: secretKey,
|
||||
}
|
||||
|
||||
for {
|
||||
rl.SetPrompt("\033[36m是否支持分段上传?(y/n): \033[0m")
|
||||
input, err := rl.Readline()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(input)) {
|
||||
case "y", "yes":
|
||||
userSpace.Features = append(userSpace.Features, &cortypes.MultipartUploadFeature{
|
||||
Type: "MultipartUpload",
|
||||
})
|
||||
return nil
|
||||
case "n", "no":
|
||||
userSpace.Features = nil
|
||||
return nil
|
||||
default:
|
||||
fmt.Println("\033[31m无效输入!请输入 y/n 或 yes/no \033[0m")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package userspace
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"gitlink.org.cn/cloudream/jcs-pub/jcsctl/cmd"
|
||||
)
|
||||
|
||||
var UserSpaceCmd = &cobra.Command{
|
||||
Use: "userspace",
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmd.RootCmd.AddCommand(UserSpaceCmd)
|
||||
}
|
Loading…
Reference in New Issue