github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/cmd/swift.go (about)

     1  package cmd
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"net/url"
     9  	"os"
    10  	"strconv"
    11  
    12  	"github.com/cozy/cozy-stack/client/request"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  var flagSwiftObjectContentType string
    17  var flagShowDomains bool
    18  
    19  var swiftCmdGroup = &cobra.Command{
    20  	Use:   "swift <command>",
    21  	Short: "Interact directly with OpenStack Swift object storage",
    22  	RunE: func(cmd *cobra.Command, args []string) error {
    23  		return cmd.Usage()
    24  	},
    25  }
    26  
    27  var lsLayoutsCmd = &cobra.Command{
    28  	Use:     "ls-layouts",
    29  	Short:   `Count layouts by types (v3a, v3b, unknown)`,
    30  	Example: "$ cozy-stack swift ls-layouts",
    31  	RunE: func(cmd *cobra.Command, args []string) error {
    32  		ac := newAdminClient()
    33  		values := url.Values{}
    34  		values.Add("show_domains", strconv.FormatBool(flagShowDomains))
    35  		res, err := ac.Req(&request.Options{
    36  			Method:  "GET",
    37  			Path:    "/swift/layouts",
    38  			Queries: values,
    39  		})
    40  		if err != nil {
    41  			return err
    42  		}
    43  		defer res.Body.Close()
    44  
    45  		var buf interface{}
    46  		if err := json.NewDecoder(res.Body).Decode(&buf); err != nil {
    47  			return err
    48  		}
    49  		json, err := json.MarshalIndent(buf, "", "  ")
    50  		if err != nil {
    51  			return err
    52  		}
    53  
    54  		fmt.Println(string(json))
    55  		return nil
    56  	},
    57  }
    58  
    59  var swiftGetCmd = &cobra.Command{
    60  	Use:     "get <domain> <object-name>",
    61  	Aliases: []string{"download"},
    62  	RunE: func(cmd *cobra.Command, args []string) error {
    63  		if len(args) < 2 {
    64  			return cmd.Usage()
    65  		}
    66  
    67  		ac := newAdminClient()
    68  		path := fmt.Sprintf("/swift/vfs/%s", url.PathEscape(args[1]))
    69  		res, err := ac.Req(&request.Options{
    70  			Method: "GET",
    71  			Path:   path,
    72  			Domain: args[0],
    73  		})
    74  		if err != nil {
    75  			return err
    76  		}
    77  		defer res.Body.Close()
    78  
    79  		// Read the body and print it
    80  		_, err = io.Copy(os.Stdout, res.Body)
    81  		return err
    82  	},
    83  }
    84  
    85  var swiftPutCmd = &cobra.Command{
    86  	Use:     "put <domain> <object-name>",
    87  	Aliases: []string{"upload"},
    88  	Long: `cozy-stack swift put can be used to create or update an object in
    89  the swift container associated to the given domain. The content of the file is
    90  expected on the standard input.`,
    91  	RunE: func(cmd *cobra.Command, args []string) error {
    92  		if len(args) < 2 {
    93  			return cmd.Usage()
    94  		}
    95  
    96  		ac := newAdminClient()
    97  		buf := new(bytes.Buffer)
    98  
    99  		_, err := io.Copy(buf, os.Stdin)
   100  		if err != nil {
   101  			return err
   102  		}
   103  
   104  		_, err = ac.Req(&request.Options{
   105  			Method: "PUT",
   106  			Path:   fmt.Sprintf("/swift/vfs/%s", url.PathEscape(args[1])),
   107  			Body:   bytes.NewReader(buf.Bytes()),
   108  			Domain: args[0],
   109  			Headers: map[string]string{
   110  				"Content-Type": flagSwiftObjectContentType,
   111  			},
   112  		})
   113  		if err != nil {
   114  			return err
   115  		}
   116  
   117  		fmt.Println("Object has been added to swift")
   118  		return nil
   119  	},
   120  }
   121  
   122  var swiftDeleteCmd = &cobra.Command{
   123  	Use:     "rm <domain> <object-name>",
   124  	Aliases: []string{"delete"},
   125  	RunE: func(cmd *cobra.Command, args []string) error {
   126  		if len(args) < 2 {
   127  			return cmd.Usage()
   128  		}
   129  
   130  		ac := newAdminClient()
   131  		path := fmt.Sprintf("/swift/vfs/%s", url.PathEscape(args[1]))
   132  		_, err := ac.Req(&request.Options{
   133  			Method: "DELETE",
   134  			Path:   path,
   135  			Domain: args[0],
   136  		})
   137  
   138  		return err
   139  	},
   140  }
   141  
   142  var swiftLsCmd = &cobra.Command{
   143  	Use:     "ls <domain>",
   144  	Aliases: []string{"list"},
   145  	RunE: func(cmd *cobra.Command, args []string) error {
   146  		if len(args) < 1 {
   147  			return cmd.Usage()
   148  		}
   149  
   150  		type resStruct struct {
   151  			ObjectNameList []string `json:"objects_names"`
   152  		}
   153  
   154  		ac := newAdminClient()
   155  		res, err := ac.Req(&request.Options{
   156  			Method: "GET",
   157  			Path:   "/swift/vfs",
   158  			Domain: args[0],
   159  		})
   160  		if err != nil {
   161  			return err
   162  		}
   163  
   164  		names := resStruct{}
   165  		err = json.NewDecoder(res.Body).Decode(&names)
   166  		if err != nil {
   167  			return err
   168  		}
   169  
   170  		for _, name := range names.ObjectNameList {
   171  			fmt.Println(name)
   172  		}
   173  
   174  		return nil
   175  	},
   176  }
   177  
   178  func init() {
   179  	swiftPutCmd.Flags().StringVar(&flagSwiftObjectContentType, "content-type", "", "Specify a Content-Type for the created object")
   180  	lsLayoutsCmd.Flags().BoolVar(&flagShowDomains, "show-domains", false, "Show the domains along the counter")
   181  
   182  	swiftCmdGroup.AddCommand(swiftGetCmd)
   183  	swiftCmdGroup.AddCommand(swiftPutCmd)
   184  	swiftCmdGroup.AddCommand(swiftDeleteCmd)
   185  	swiftCmdGroup.AddCommand(swiftLsCmd)
   186  	swiftCmdGroup.AddCommand(lsLayoutsCmd)
   187  
   188  	RootCmd.AddCommand(swiftCmdGroup)
   189  }