|
- 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.UserSpace().Create(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")
- }
- }
- }
|