From d693ae02c65e34c71899a79dd991b5150d10aaeb Mon Sep 17 00:00:00 2001 From: Utkarsh Bhatt Date: Fri, 8 Dec 2023 15:49:53 +0530 Subject: [PATCH] Changed CLI and endpoint interfaces. Signed-off-by: Utkarsh Bhatt --- .github/workflows/tests.yml | 57 +++++- docs/.custom_wordlist.txt | 2 + docs/how-to/s3-user.rst | 4 +- microceph/api/client.go | 8 + microceph/api/client_configs.go | 5 - microceph/api/{s3.go => client_s3.go} | 16 +- microceph/api/endpoints.go | 2 +- microceph/client/s3.go | 8 +- microceph/cmd/microceph/client.go | 5 + microceph/cmd/microceph/client_s3.go | 276 ++++++++++++++++++++++++++ microceph/cmd/microceph/main.go | 3 - microceph/cmd/microceph/s3-user.go | 270 ------------------------- tests/scripts/actionutils.sh | 28 ++- 13 files changed, 376 insertions(+), 308 deletions(-) create mode 100644 microceph/api/client.go rename microceph/api/{s3.go => client_s3.go} (73%) create mode 100644 microceph/cmd/microceph/client_s3.go diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0dd45c47..6f86f952 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,6 +39,27 @@ jobs: path: "*.snap" retention-days: 5 + lint-check: + name: Build microceph snap + runs-on: ubuntu-22.04 + env: + SNAPCRAFT_BUILD_ENVIRONMENT: "lxd" + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install dependencies + run: | + # Python script dependencies + sudo python -m pip install --upgrade pip + sudo pip install flake8 pep8-naming + + - name: Lint check help scripts. + run: | + flake8 ./scripts/ --count --show-source --statistics + unit-tests: name: Run Unit tests runs-on: ubuntu-22.04 @@ -85,11 +106,7 @@ jobs: run: | # Python script dependencies sudo python -m pip install --upgrade pip - sudo pip install flake8 pep8-naming boto3 - - - name: Lint check - run: | - flake8 . --count --show-source --statistics + sudo pip install boto3 - name: Install and setup run: | @@ -219,7 +236,11 @@ jobs: run: ~/actionutils.sh free_runner_disk - name: Install dependencies - run: ~/actionutils.sh setup_lxd + run: | + # Python script dependencies + sudo python -m pip install --upgrade pip + sudo pip install boto3 + ~/actionutils.sh setup_lxd - name: Create containers with loopback devices run: ~/actionutils.sh create_containers @@ -314,6 +335,12 @@ jobs: - name: Copy utils run: cp tests/scripts/actionutils.sh $HOME + - name: Install dependencies + run: | + # Python script dependencies + sudo python -m pip install --upgrade pip + sudo pip install boto3 + - name: Clear FORWARD firewall rules run: ~/actionutils.sh cleaript @@ -370,7 +397,8 @@ jobs: run: ~/actionutils.sh free_runner_disk - name: Install dependencies - run: ~/actionutils.sh setup_lxd + run: | + ~/actionutils.sh setup_lxd - name: Create containers with loopback devices run: ~/actionutils.sh create_containers @@ -394,8 +422,8 @@ jobs: - name: Enable RGW run: ~/actionutils.sh headexec enable_rgw - - name: Exercise RGW - run: ~/actionutils.sh headexec testrgw + - name: Exercise RGW before upgrade + run: ~/actionutils.sh headexec testrgw_old - name: Install local build run: ~/actionutils.sh install_multinode @@ -403,6 +431,13 @@ jobs: - name: Wait until 3 OSDs are up run: ~/actionutils.sh headexec wait_for_osds 3 + - name: Install boto3 on head node. + run: | + ~/actionutils.sh headexec install_boto3 + - name: Exercise RGW again - run: ~/actionutils.sh headexec testrgw - + run: | + # Copy S3 app to head node. + lxc file push ./scripts/ -r node-wrk0/root/ + ~/actionutils.sh headexec testrgw + diff --git a/docs/.custom_wordlist.txt b/docs/.custom_wordlist.txt index 3ae4c897..875996e7 100644 --- a/docs/.custom_wordlist.txt +++ b/docs/.custom_wordlist.txt @@ -47,6 +47,7 @@ Pre mds mon rgw +radosgw rbd RBD MgrReports @@ -59,3 +60,4 @@ qemu writethrough writeback IOPS +json diff --git a/docs/how-to/s3-user.rst b/docs/how-to/s3-user.rst index 5de52d45..8d32c33b 100644 --- a/docs/how-to/s3-user.rst +++ b/docs/how-to/s3-user.rst @@ -1,5 +1,5 @@ -Use S3 user management on MicroCeph -=================================== +Manage S3 users on MicroCeph +============================= MicroCeph provides an easy to use interface for creating, viewing and deleting s3 users for interfacing with the RGW endpoint. This enables smooth and easy access to Object Storage. diff --git a/microceph/api/client.go b/microceph/api/client.go new file mode 100644 index 00000000..41ddf5c8 --- /dev/null +++ b/microceph/api/client.go @@ -0,0 +1,8 @@ +package api + +import "github.com/canonical/microcluster/rest" + +// Top level client API +var clientCmd = rest.Endpoint{ + Path: "client", +} diff --git a/microceph/api/client_configs.go b/microceph/api/client_configs.go index 34cd7e57..03f8305a 100644 --- a/microceph/api/client_configs.go +++ b/microceph/api/client_configs.go @@ -18,11 +18,6 @@ import ( "github.com/canonical/microcluster/state" ) -// Top level client API -var clientCmd = rest.Endpoint{ - Path: "client", -} - // client configs API var clientConfigsCmd = rest.Endpoint{ Path: "client/configs", diff --git a/microceph/api/s3.go b/microceph/api/client_s3.go similarity index 73% rename from microceph/api/s3.go rename to microceph/api/client_s3.go index d2f0bc85..dfa6dd94 100644 --- a/microceph/api/s3.go +++ b/microceph/api/client_s3.go @@ -12,14 +12,14 @@ import ( ) // /1.0/resources endpoint. -var s3Cmd = rest.Endpoint{ - Path: "services/rgw/user", - Get: rest.EndpointAction{Handler: cmdS3Get, ProxyTarget: true}, - Put: rest.EndpointAction{Handler: cmdS3Put, ProxyTarget: true}, - Delete: rest.EndpointAction{Handler: cmdS3Delete, ProxyTarget: true}, +var clientS3Cmd = rest.Endpoint{ + Path: "client/s3", + Get: rest.EndpointAction{Handler: cmdClientS3Get, ProxyTarget: true}, + Put: rest.EndpointAction{Handler: cmdClientS3Put, ProxyTarget: true}, + Delete: rest.EndpointAction{Handler: cmdClientS3Delete, ProxyTarget: true}, } -func cmdS3Get(s *state.State, r *http.Request) response.Response { +func cmdClientS3Get(s *state.State, r *http.Request) response.Response { var err error var req types.S3User @@ -44,7 +44,7 @@ func cmdS3Get(s *state.State, r *http.Request) response.Response { } } -func cmdS3Put(s *state.State, r *http.Request) response.Response { +func cmdClientS3Put(s *state.State, r *http.Request) response.Response { var err error var req types.S3User @@ -61,7 +61,7 @@ func cmdS3Put(s *state.State, r *http.Request) response.Response { return response.SyncResponse(true, output) } -func cmdS3Delete(s *state.State, r *http.Request) response.Response { +func cmdClientS3Delete(s *state.State, r *http.Request) response.Response { var err error var req types.S3User diff --git a/microceph/api/endpoints.go b/microceph/api/endpoints.go index 57c556de..427e0730 100644 --- a/microceph/api/endpoints.go +++ b/microceph/api/endpoints.go @@ -20,5 +20,5 @@ var Endpoints = []rest.Endpoint{ clientCmd, clientConfigsCmd, clientConfigsKeyCmd, - s3Cmd, + clientS3Cmd, } diff --git a/microceph/client/s3.go b/microceph/client/s3.go index 30d36d95..9a7947b1 100644 --- a/microceph/client/s3.go +++ b/microceph/client/s3.go @@ -16,7 +16,7 @@ func GetS3User(ctx context.Context, c *client.Client, user *types.S3User) (strin defer cancel() ret := "" - err := c.Query(queryCtx, "GET", api.NewURL().Path("services", "rgw", "user"), user, &ret) + err := c.Query(queryCtx, "GET", api.NewURL().Path("client", "s3"), user, &ret) if err != nil { logger.Error(err.Error()) return ret, err @@ -31,7 +31,7 @@ func ListS3Users(ctx context.Context, c *client.Client) ([]string, error) { ret := []string{} // List of usernames // GET request with no user name fetches all users. - err := c.Query(queryCtx, "GET", api.NewURL().Path("services", "rgw", "user"), &types.S3User{Name: ""}, &ret) + err := c.Query(queryCtx, "GET", api.NewURL().Path("client", "s3"), &types.S3User{Name: ""}, &ret) if err != nil { logger.Error(err.Error()) return ret, err @@ -45,7 +45,7 @@ func CreateS3User(ctx context.Context, c *client.Client, user *types.S3User) (st defer cancel() ret := "" - err := c.Query(queryCtx, "PUT", api.NewURL().Path("services", "rgw", "user"), user, &ret) + err := c.Query(queryCtx, "PUT", api.NewURL().Path("client", "s3"), user, &ret) if err != nil { logger.Error(err.Error()) return ret, err @@ -59,7 +59,7 @@ func DeleteS3User(ctx context.Context, c *client.Client, user *types.S3User) err defer cancel() ret := types.S3User{} - err := c.Query(queryCtx, "DELETE", api.NewURL().Path("services", "rgw", "user"), user, &ret) + err := c.Query(queryCtx, "DELETE", api.NewURL().Path("client", "s3"), user, &ret) if err != nil { logger.Error(err.Error()) return err diff --git a/microceph/cmd/microceph/client.go b/microceph/cmd/microceph/client.go index a8940fd1..37a42371 100644 --- a/microceph/cmd/microceph/client.go +++ b/microceph/cmd/microceph/client.go @@ -6,6 +6,7 @@ import ( type cmdClient struct { common *CmdControl + client *cmdClient } func (c *cmdClient) Command() *cobra.Command { @@ -18,6 +19,10 @@ func (c *cmdClient) Command() *cobra.Command { clientConfigCmd := cmdClientConfig{common: c.common, client: c} cmd.AddCommand(clientConfigCmd.Command()) + // S3 Subcommand + clientS3Cmd := cmdClientS3{common: c.common, client: c.client} + cmd.AddCommand(clientS3Cmd.Command()) + // Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706 cmd.Args = cobra.NoArgs cmd.Run = func(cmd *cobra.Command, args []string) { _ = cmd.Usage() } diff --git a/microceph/cmd/microceph/client_s3.go b/microceph/cmd/microceph/client_s3.go new file mode 100644 index 00000000..cfe5d74d --- /dev/null +++ b/microceph/cmd/microceph/client_s3.go @@ -0,0 +1,276 @@ +package main + +import ( + "context" + "fmt" + + lxdCmd "github.com/canonical/lxd/shared/cmd" + "github.com/canonical/microceph/microceph/api/types" + "github.com/canonical/microceph/microceph/client" + "github.com/canonical/microcluster/microcluster" + "github.com/spf13/cobra" + "github.com/tidwall/gjson" +) + +type cmdClientS3 struct { + common *CmdControl + client *cmdClient +} + +type cmdClientS3Get struct { + common *CmdControl + client *cmdClient + s3 *cmdClientS3 + jsonOutput bool +} + +type cmdClientS3Create struct { + common *CmdControl + client *cmdClient + s3 *cmdClientS3 + accessKey string + secret string + jsonOutput bool +} + +type cmdClientS3Delete struct { + common *CmdControl + client *cmdClient + s3 *cmdClientS3 +} + +type cmdClientS3List struct { + common *CmdControl + client *cmdClient + s3 *cmdClientS3 +} + +// parent s3 command handle +func (c *cmdClientS3) Command() *cobra.Command { + cmd := &cobra.Command{ + Use: "s3", + Short: "Manage S3 users for Object storage", + } + + // Create + s3CreateCmd := cmdClientS3Create{common: c.common, client: c.client, s3: c} + cmd.AddCommand(s3CreateCmd.Command()) + + // Delete + s3DeleteCmd := cmdClientS3Delete{common: c.common, client: c.client, s3: c} + cmd.AddCommand(s3DeleteCmd.Command()) + + // Get + s3GetCmd := cmdClientS3Get{common: c.common, client: c.client, s3: c} + cmd.AddCommand(s3GetCmd.Command()) + + // List + s3ListCmd := cmdClientS3List{common: c.common, client: c.client, s3: c} + cmd.AddCommand(s3ListCmd.Command()) + + // Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706 + cmd.Args = cobra.NoArgs + cmd.Run = func(cmd *cobra.Command, args []string) { _ = cmd.Usage() } + + return cmd +} + +// s3 Get command handle +func (c *cmdClientS3Get) Command() *cobra.Command { + cmd := &cobra.Command{ + Use: "get ", + Short: "Fetch details of an existing S3 user", + RunE: c.Run, + } + + cmd.Flags().BoolVar(&c.jsonOutput, "json", false, "Provide output in json format") + return cmd +} + +func (c *cmdClientS3Get) Run(cmd *cobra.Command, args []string) error { + // Get should be called with a single name param. + if len(args) != 1 { + return cmd.Help() + } + + m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) + if err != nil { + return fmt.Errorf("unable to fetch S3 user: %w", err) + } + + cli, err := m.LocalClient() + if err != nil { + return err + } + + input := &types.S3User{Name: args[0]} + user, err := client.GetS3User(context.Background(), cli, input) + if err != nil { + return err + } + + err = renderOutput(user, c.jsonOutput) + if err != nil { + return err + } + + return nil +} + +// s3 create command handle +func (c *cmdClientS3Create) Command() *cobra.Command { + cmd := &cobra.Command{ + Use: "create ", + Short: "Create a new S3 user", + RunE: c.Run, + } + + cmd.Flags().StringVar(&c.accessKey, "access-key", "", "custom access-key for new S3 user.") + cmd.Flags().StringVar(&c.secret, "secret", "", "custom secret for new S3 user.") + cmd.Flags().BoolVar(&c.jsonOutput, "json", false, "Provide output in json format") + return cmd +} + +func (c *cmdClientS3Create) Run(cmd *cobra.Command, args []string) error { + // Get should be called with a single name param. + if len(args) != 1 { + return cmd.Help() + } + + m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) + if err != nil { + return fmt.Errorf("unable to create S3 user: %w", err) + } + + cli, err := m.LocalClient() + if err != nil { + return err + } + + // Create a user with given keys. + input := &types.S3User{ + Name: args[0], + Key: c.accessKey, + Secret: c.secret, + } + user, err := client.CreateS3User(context.Background(), cli, input) + if err != nil { + return err + } + + err = renderOutput(user, c.jsonOutput) + if err != nil { + return err + } + + return nil +} + +// s3 delete command handle +func (c *cmdClientS3Delete) Command() *cobra.Command { + cmd := &cobra.Command{ + Use: "delete ", + Short: "Delete an existing S3 user", + RunE: c.Run, + } + return cmd +} + +func (c *cmdClientS3Delete) Run(cmd *cobra.Command, args []string) error { + // Get should be called with a single name param. + if len(args) != 1 { + return cmd.Help() + } + + m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) + if err != nil { + return fmt.Errorf("unable to delete S3 user: %w", err) + } + + cli, err := m.LocalClient() + if err != nil { + return err + } + + err = client.DeleteS3User(context.Background(), cli, &types.S3User{Name: args[0]}) + if err != nil { + return err + } + + return nil +} + +// s3 list command handle +func (c *cmdClientS3List) Command() *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List all existing S3 users", + RunE: c.Run, + } + + return cmd +} + +func (c *cmdClientS3List) Run(cmd *cobra.Command, args []string) error { + // Should not be called with any params + if len(args) > 1 { + return cmd.Help() + } + + m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) + if err != nil { + return fmt.Errorf("unable to list S3 users: %w", err) + } + + cli, err := m.LocalClient() + if err != nil { + return err + } + + users, err := client.ListS3Users(context.Background(), cli) + if err != nil { + return err + } + + data := make([][]string, len(users)) + for i := range users { + data[i] = []string{fmt.Sprintf("%d", i+1), users[i]} + } + + header := []string{"#", "Name"} + err = lxdCmd.RenderTable(lxdCmd.TableFormatTable, header, data, users) + if err != nil { + return err + } + + return nil +} + +func renderOutput(output string, isJson bool) error { + if isJson { + fmt.Print(output) + } else { + user := types.S3User{ + Name: gjson.Get(output, "keys.0.user").Str, + Key: gjson.Get(output, "keys.0.access_key").Str, + Secret: gjson.Get(output, "keys.0.secret_key").Str, + } + err := renderSingleS3User(user) + if err != nil { + return err + } + } + return nil +} + +func renderSingleS3User(user types.S3User) error { + data := make([][]string, 1) + data[0] = []string{user.Name, user.Key, user.Secret} + + header := []string{"Name", "Access Key", "Secret"} + err := lxdCmd.RenderTable(lxdCmd.TableFormatTable, header, data, user) + if err != nil { + return err + } + return nil +} diff --git a/microceph/cmd/microceph/main.go b/microceph/cmd/microceph/main.go index d2c49d55..5d4ddc77 100644 --- a/microceph/cmd/microceph/main.go +++ b/microceph/cmd/microceph/main.go @@ -66,9 +66,6 @@ func main() { var cmdClient = cmdClient{common: &commonCmd} app.AddCommand(cmdClient.Command()) - var cmdS3 = cmdS3{common: &commonCmd} - app.AddCommand(cmdS3.Command()) - app.InitDefaultHelpCmd() err := app.Execute() diff --git a/microceph/cmd/microceph/s3-user.go b/microceph/cmd/microceph/s3-user.go index 4d5334d1..06ab7d0f 100644 --- a/microceph/cmd/microceph/s3-user.go +++ b/microceph/cmd/microceph/s3-user.go @@ -1,271 +1 @@ package main - -import ( - "context" - "fmt" - - lxdCmd "github.com/canonical/lxd/shared/cmd" - "github.com/canonical/microceph/microceph/api/types" - "github.com/canonical/microceph/microceph/client" - "github.com/canonical/microcluster/microcluster" - "github.com/spf13/cobra" - "github.com/tidwall/gjson" -) - -type cmdS3 struct { - common *CmdControl -} - -type cmdS3Get struct { - common *CmdControl - s3 *cmdS3 - jsonOutput bool -} - -type cmdS3Create struct { - common *CmdControl - s3 *cmdS3 - accessKey string - secret string - jsonOutput bool -} - -type cmdS3Delete struct { - common *CmdControl - s3 *cmdS3 -} - -type cmdS3List struct { - common *CmdControl - s3 *cmdS3 -} - -// parent s3 command handle -func (c *cmdS3) Command() *cobra.Command { - cmd := &cobra.Command{ - Use: "s3-user", - Short: "Manage S3 users for Object storage", - } - - // Create - s3CreateCmd := cmdS3Create{common: c.common, s3: c} - cmd.AddCommand(s3CreateCmd.Command()) - - // Delete - s3DeleteCmd := cmdS3Delete{common: c.common, s3: c} - cmd.AddCommand(s3DeleteCmd.Command()) - - // Get - s3GetCmd := cmdS3Get{common: c.common, s3: c} - cmd.AddCommand(s3GetCmd.Command()) - - // List - s3ListCmd := cmdS3List{common: c.common, s3: c} - cmd.AddCommand(s3ListCmd.Command()) - - // Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706 - cmd.Args = cobra.NoArgs - cmd.Run = func(cmd *cobra.Command, args []string) { _ = cmd.Usage() } - - return cmd -} - -// s3 Get command handle -func (c *cmdS3Get) Command() *cobra.Command { - cmd := &cobra.Command{ - Use: "get ", - Short: "Fetch details of an existing S3 user", - RunE: c.Run, - } - - cmd.Flags().BoolVar(&c.jsonOutput, "json", false, "Provide output in json format") - return cmd -} - -func (c *cmdS3Get) Run(cmd *cobra.Command, args []string) error { - // Get should be called with a single name param. - if len(args) != 1 { - return cmd.Help() - } - - m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) - if err != nil { - return fmt.Errorf("unable to fetch S3 user: %w", err) - } - - cli, err := m.LocalClient() - if err != nil { - return err - } - - input := &types.S3User{Name: args[0]} - user, err := client.GetS3User(context.Background(), cli, input) - if err != nil { - return err - } - - err = renderOutput(user, c.jsonOutput) - if err != nil { - return err - } - - return nil -} - -// s3 create command handle -func (c *cmdS3Create) Command() *cobra.Command { - cmd := &cobra.Command{ - Use: "create ", - Short: "Create a new S3 user", - RunE: c.Run, - } - - cmd.Flags().StringVar(&c.accessKey, "access-key", "", "custom access-key for new S3 user.") - cmd.Flags().StringVar(&c.secret, "secret", "", "custom secret for new S3 user.") - cmd.Flags().BoolVar(&c.jsonOutput, "json", false, "Provide output in json format") - return cmd -} - -func (c *cmdS3Create) Run(cmd *cobra.Command, args []string) error { - // Get should be called with a single name param. - if len(args) != 1 { - return cmd.Help() - } - - m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) - if err != nil { - return fmt.Errorf("unable to create S3 user: %w", err) - } - - cli, err := m.LocalClient() - if err != nil { - return err - } - - // Create a user with given keys. - input := &types.S3User{ - Name: args[0], - Key: c.accessKey, - Secret: c.secret, - } - user, err := client.CreateS3User(context.Background(), cli, input) - if err != nil { - return err - } - - err = renderOutput(user, c.jsonOutput) - if err != nil { - return err - } - - return nil -} - -// s3 delete command handle -func (c *cmdS3Delete) Command() *cobra.Command { - cmd := &cobra.Command{ - Use: "delete ", - Short: "Delete an existing S3 user", - RunE: c.Run, - } - return cmd -} - -func (c *cmdS3Delete) Run(cmd *cobra.Command, args []string) error { - // Get should be called with a single name param. - if len(args) != 1 { - return cmd.Help() - } - - m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) - if err != nil { - return fmt.Errorf("unable to delete S3 user: %w", err) - } - - cli, err := m.LocalClient() - if err != nil { - return err - } - - err = client.DeleteS3User(context.Background(), cli, &types.S3User{Name: args[0]}) - if err != nil { - return err - } - - return nil -} - -// s3 list command handle -func (c *cmdS3List) Command() *cobra.Command { - cmd := &cobra.Command{ - Use: "list", - Short: "List all existing S3 users", - RunE: c.Run, - } - - return cmd -} - -func (c *cmdS3List) Run(cmd *cobra.Command, args []string) error { - // Should not be called with any params - if len(args) > 1 { - return cmd.Help() - } - - m, err := microcluster.App(context.Background(), microcluster.Args{StateDir: c.common.FlagStateDir, Verbose: c.common.FlagLogVerbose, Debug: c.common.FlagLogDebug}) - if err != nil { - return fmt.Errorf("unable to list S3 users: %w", err) - } - - cli, err := m.LocalClient() - if err != nil { - return err - } - - users, err := client.ListS3Users(context.Background(), cli) - if err != nil { - return err - } - - data := make([][]string, len(users)) - for i := range users { - data[i] = []string{fmt.Sprintf("%d", i+1), users[i]} - } - - header := []string{"#", "Name"} - err = lxdCmd.RenderTable(lxdCmd.TableFormatTable, header, data, users) - if err != nil { - return err - } - - return nil -} - -func renderOutput(output string, isJson bool) error { - if isJson { - fmt.Print(output) - } else { - user := types.S3User{ - Name: gjson.Get(output, "keys.0.user").Str, - Key: gjson.Get(output, "keys.0.access_key").Str, - Secret: gjson.Get(output, "keys.0.secret_key").Str, - } - err := renderSingleS3User(user) - if err != nil { - return err - } - } - return nil -} - -func renderSingleS3User(user types.S3User) error { - data := make([][]string, 1) - data[0] = []string{user.Name, user.Key, user.Secret} - - header := []string{"Name", "Access Key", "Secret"} - err := lxdCmd.RenderTable(lxdCmd.TableFormatTable, header, data, user) - if err != nil { - return err - } - return nil -} diff --git a/tests/scripts/actionutils.sh b/tests/scripts/actionutils.sh index 309dfb30..1f0afa6e 100755 --- a/tests/scripts/actionutils.sh +++ b/tests/scripts/actionutils.sh @@ -303,17 +303,37 @@ function free_runner_disk() { sudo docker rmi $(docker images -q) } +function install_boto3() { + # Python script dependencies + sudo apt update && sudo apt install python3-pip + sudo pip3 install boto3 +} -function testrgw() { +function testrgw_old() { set -eu sudo microceph.ceph status sudo systemctl status snap.microceph.rgw if ! microceph.radosgw-admin user list | grep -q test ; then - set -eux - sudo microceph s3-user create testUser --json > keys.json + sudo microceph.radosgw-admin user create --uid=test --display-name=test + sudo microceph.radosgw-admin key create --uid=test --key-type=s3 --access-key fooAccessKey --secret-key fooSecretKey + fi + sudo apt-get update -qq + sudo apt-get -qq install s3cmd + echo hello-radosgw > ~/test.txt + s3cmd --host localhost --host-bucket="localhost/%(bucket)" --access_key=fooAccessKey --secret_key=fooSecretKey --no-ssl mb s3://testbucket + s3cmd --host localhost --host-bucket="localhost/%(bucket)" --access_key=fooAccessKey --secret_key=fooSecretKey --no-ssl put -P ~/test.txt s3://testbucket + ( curl -s http://localhost/testbucket/test.txt | grep -F hello-radosgw ) || return -1 +} + +function testrgw() { + set -eux + sudo microceph.ceph status + sudo systemctl status snap.microceph.rgw + if ! microceph.radosgw-admin user list | grep -q test ; then + sudo microceph client s3 create testUser --json > keys.json fi sudo python3 ./scripts/appS3.py http://localhost:80 keys.json --obj-num 2 - sudo microceph s3-user delete testUser + sudo microceph client s3 delete testUser } function enable_services() {