Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions internal/cmd/branch/vtctld/refresh_state_by_shard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package vtctld

import (
"fmt"

"github.com/planetscale/cli/internal/cmdutil"
ps "github.com/planetscale/planetscale-go/planetscale"
"github.com/spf13/cobra"
)

// RefreshStateByShardCmd reloads tablet records for all tablets in a shard via vtctld.
func RefreshStateByShardCmd(ch *cmdutil.Helper) *cobra.Command {
var flags struct {
keyspace string
shard string
cells []string
}

cmd := &cobra.Command{
Use: "refresh-state-by-shard <database> <branch>",
Short: "Reload tablet records for all tablets in a shard",
Long: "Reload the tablet record for all tablets in a shard via vtctld, " +
"optionally limited to the specified cells.",
Args: cmdutil.RequiredArgs("database", "branch"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
database, branch := args[0], args[1]

if flags.keyspace == "" {
return fmt.Errorf("keyspace is required")
}
if flags.shard == "" {
return fmt.Errorf("shard is required")
}

client, err := ch.Client()
if err != nil {
return err
}

end := ch.Printer.PrintProgress(
fmt.Sprintf("Refreshing tablet state for %s/%s on %s…",
flags.keyspace, flags.shard,
progressTarget(ch.Config.Organization, database, branch)))
defer end()

data, err := client.Vtctld.RefreshStateByShard(ctx, &ps.VtctldRefreshStateByShardRequest{
Organization: ch.Config.Organization,
Database: database,
Branch: branch,
Keyspace: flags.keyspace,
Shard: flags.shard,
Cells: flags.cells,
})
if err != nil {
return cmdutil.HandleError(err)
}

end()
return ch.Printer.PrettyPrintJSON(data)
},
}

cmd.Flags().StringVar(&flags.keyspace, "keyspace", "", "Keyspace name")
cmd.Flags().StringVar(&flags.shard, "shard", "", "Shard name (e.g. \"-\" for unsharded)")
cmd.Flags().StringSliceVar(&flags.cells, "cells", nil, "Cells to refresh (comma-separated)")
cmd.MarkFlagRequired("keyspace")
cmd.MarkFlagRequired("shard")

return cmd
}
61 changes: 61 additions & 0 deletions internal/cmd/branch/vtctld/refresh_state_by_shard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package vtctld

import (
"bytes"
"context"
"encoding/json"
"testing"

qt "github.com/frankban/quicktest"

"github.com/planetscale/cli/internal/cmdutil"
"github.com/planetscale/cli/internal/config"
"github.com/planetscale/cli/internal/mock"
"github.com/planetscale/cli/internal/printer"
ps "github.com/planetscale/planetscale-go/planetscale"
)

func TestRefreshStateByShard(t *testing.T) {
c := qt.New(t)

org := "my-org"
db := "my-db"
branch := "my-branch"

svc := &mock.VtctldService{
RefreshStateByShardFn: func(ctx context.Context, req *ps.VtctldRefreshStateByShardRequest) (json.RawMessage, error) {
c.Assert(req.Organization, qt.Equals, org)
c.Assert(req.Database, qt.Equals, db)
c.Assert(req.Branch, qt.Equals, branch)
c.Assert(req.Keyspace, qt.Equals, "commerce")
c.Assert(req.Shard, qt.Equals, "-")
c.Assert(req.Cells, qt.DeepEquals, []string{"zone1"})
return json.RawMessage(`{}`), nil
},
}

var buf bytes.Buffer
format := printer.JSON
p := printer.NewPrinter(&format)
p.SetResourceOutput(&buf)

ch := &cmdutil.Helper{
Printer: p,
Config: &config.Config{Organization: org},
Client: func() (*ps.Client, error) {
return &ps.Client{
Vtctld: svc,
}, nil
},
}

cmd := RefreshStateByShardCmd(ch)
cmd.SetArgs([]string{db, branch})
cmd.Flags().Set("keyspace", "commerce")
cmd.Flags().Set("shard", "-")
cmd.Flags().Set("cells", "zone1")

err := cmd.Execute()
c.Assert(err, qt.IsNil)
c.Assert(svc.RefreshStateByShardFnInvoked, qt.IsTrue)
}
1 change: 1 addition & 0 deletions internal/cmd/branch/vtctld/vtctld.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func VtctldCmd(ch *cmdutil.Helper) *cobra.Command {
cmd.AddCommand(GetRoutingRulesCmd(ch))
cmd.AddCommand(GetShardCmd(ch))
cmd.AddCommand(SetShardTabletControlCmd(ch))
cmd.AddCommand(RefreshStateByShardCmd(ch))
cmd.AddCommand(ListTabletsCmd(ch))
cmd.AddCommand(StartWorkflowCmd(ch))
cmd.AddCommand(StopWorkflowCmd(ch))
Expand Down
8 changes: 8 additions & 0 deletions internal/mock/vtctld_general.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ type VtctldService struct {
SetShardTabletControlFn func(context.Context, *ps.VtctldSetShardTabletControlRequest) (json.RawMessage, error)
SetShardTabletControlFnInvoked bool

RefreshStateByShardFn func(context.Context, *ps.VtctldRefreshStateByShardRequest) (json.RawMessage, error)
RefreshStateByShardFnInvoked bool

ListTabletsFn func(context.Context, *ps.ListBranchTabletsRequest) ([]*ps.TabletGroup, error)
ListTabletsFnInvoked bool

Expand Down Expand Up @@ -70,6 +73,11 @@ func (s *VtctldService) SetShardTabletControl(ctx context.Context, req *ps.Vtctl
return s.SetShardTabletControlFn(ctx, req)
}

func (s *VtctldService) RefreshStateByShard(ctx context.Context, req *ps.VtctldRefreshStateByShardRequest) (json.RawMessage, error) {
s.RefreshStateByShardFnInvoked = true
return s.RefreshStateByShardFn(ctx, req)
}

func (s *VtctldService) ListTablets(ctx context.Context, req *ps.ListBranchTabletsRequest) ([]*ps.TabletGroup, error) {
s.ListTabletsFnInvoked = true
return s.ListTabletsFn(ctx, req)
Expand Down