Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SwitchTraffic should switch everything when no tablet_types provided #10434

Merged
merged 6 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
19 changes: 11 additions & 8 deletions go/test/endtoend/vreplication/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,17 @@ func (vc *VitessCluster) AddShards(t testing.TB, cells []*Cell, keyspace *Keyspa
tablets = append(tablets, tablet)
dbProcesses = append(dbProcesses, proc)
}
for i := 0; i < numRdonly; i++ {
log.Infof("Adding RdOnly tablet")
tablet, proc, err := vc.AddTablet(t, cell, keyspace, shard, "rdonly", tabletID+tabletIndex)
require.NoError(t, err)
require.NotNil(t, tablet)
tabletIndex++
tablets = append(tablets, tablet)
dbProcesses = append(dbProcesses, proc)
// Only create RDONLY tablets in the default cell
if cell.Name == cluster.DefaultCell {
for i := 0; i < numRdonly; i++ {
log.Infof("Adding RdOnly tablet")
tablet, proc, err := vc.AddTablet(t, cell, keyspace, shard, "rdonly", tabletID+tabletIndex)
require.NoError(t, err)
require.NotNil(t, tablet)
tabletIndex++
tablets = append(tablets, tablet)
dbProcesses = append(dbProcesses, proc)
}
}

for ind, proc := range dbProcesses {
Expand Down
36 changes: 30 additions & 6 deletions go/test/endtoend/vreplication/resharding_workflows_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ const (
)

var (
targetTab1, targetTab2, targetReplicaTab1 *cluster.VttabletProcess
sourceReplicaTab, sourceTab *cluster.VttabletProcess
targetTab1, targetTab2, targetReplicaTab1, targetRdonlyTab1 *cluster.VttabletProcess
sourceTab, sourceReplicaTab, sourceRdonlyTab *cluster.VttabletProcess

lastOutput string
currentWorkflowType wrangler.VReplicationWorkflowType
Expand Down Expand Up @@ -148,12 +148,16 @@ func tstWorkflowReverseWrites(t *testing.T) {
require.NoError(t, tstWorkflowAction(t, workflowActionReverseTraffic, "primary", ""))
}

// tstWorkflowSwitchReadsAndWrites tests that SwitchWrites w/o any user provided --tablet_types
// value switches all traffic
func tstWorkflowSwitchReadsAndWrites(t *testing.T) {
require.NoError(t, tstWorkflowAction(t, workflowActionSwitchTraffic, "replica,rdonly,primary", ""))
require.NoError(t, tstWorkflowAction(t, workflowActionSwitchTraffic, "", ""))
}

// tstWorkflowReversesReadsAndWrites tests that SwitchWrites w/o any user provided --tablet_types
// value switches all traffic in reverse
func tstWorkflowReverseReadsAndWrites(t *testing.T) {
require.NoError(t, tstWorkflowAction(t, workflowActionReverseTraffic, "replica,rdonly,primary", ""))
require.NoError(t, tstWorkflowAction(t, workflowActionReverseTraffic, "", ""))
}

func tstWorkflowComplete(t *testing.T) error {
Expand Down Expand Up @@ -237,6 +241,10 @@ func getCurrentState(t *testing.T) string {
// but CI currently fails on creating multiple clusters even after the previous ones are torn down

func TestBasicV2Workflows(t *testing.T) {
defaultRdonly = 1
defer func() {
defaultRdonly = 0
}()
vc = setupCluster(t)
defer vtgateConn.Close()
defer vc.TearDown(t)
Expand Down Expand Up @@ -549,9 +557,11 @@ func testRestOfWorkflow(t *testing.T) {

tstWorkflowSwitchReadsAndWrites(t)
validateReadsRouteToTarget(t, "replica")
validateReadsRoute(t, "rdonly", targetRdonlyTab1)
validateWritesRouteToTarget(t)
waitForLowLag(t, keyspace, "wf1_reverse")
tstWorkflowReverseReadsAndWrites(t)
validateReadsRoute(t, "rdonly", sourceRdonlyTab)
validateReadsRouteToSource(t, "replica")
validateWritesRouteToSource(t)

Expand All @@ -563,6 +573,7 @@ func testRestOfWorkflow(t *testing.T) {
// fully switch and complete
waitForLowLag(t, "customer", "wf1")
tstWorkflowSwitchReadsAndWrites(t)
validateReadsRoute(t, "rdonly", targetRdonlyTab1)
validateReadsRouteToTarget(t, "replica")
validateWritesRouteToTarget(t)

Expand All @@ -588,13 +599,15 @@ func setupCluster(t *testing.T) *VitessCluster {
require.NotNil(t, vtgate)
vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.primary", "product", "0"), 1)
vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", "product", "0"), 2)
vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", "product", "0"), 1)

vtgateConn = getConnection(t, vc.ClusterConfig.hostname, vc.ClusterConfig.vtgateMySQLPort)
verifyClusterHealth(t, vc)
insertInitialData(t)

sourceReplicaTab = vc.Cells[defaultCell.Name].Keyspaces["product"].Shards["0"].Tablets["zone1-101"].Vttablet
sourceTab = vc.Cells[defaultCell.Name].Keyspaces["product"].Shards["0"].Tablets["zone1-100"].Vttablet
sourceReplicaTab = vc.Cells[defaultCell.Name].Keyspaces["product"].Shards["0"].Tablets["zone1-101"].Vttablet
sourceRdonlyTab = vc.Cells[defaultCell.Name].Keyspaces["product"].Shards["0"].Tablets["zone1-102"].Vttablet

return vc
}
Expand All @@ -616,10 +629,17 @@ func setupCustomerKeyspace(t *testing.T) {
if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", "customer", "80-"), 2); err != nil {
t.Fatal(err)
}
if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", "customer", "-80"), 1); err != nil {
t.Fatal(err)
}
if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", "customer", "80-"), 1); err != nil {
t.Fatal(err)
}
custKs := vc.Cells[defaultCell.Name].Keyspaces["customer"]
targetTab1 = custKs.Shards["-80"].Tablets["zone1-200"].Vttablet
targetTab2 = custKs.Shards["80-"].Tablets["zone1-300"].Vttablet
targetReplicaTab1 = custKs.Shards["-80"].Tablets["zone1-201"].Vttablet
targetRdonlyTab1 = custKs.Shards["-80"].Tablets["zone1-202"].Vttablet
}

func TestSwitchReadsWritesInAnyOrder(t *testing.T) {
Expand Down Expand Up @@ -742,14 +762,18 @@ func createAdditionalCustomerShards(t *testing.T, shards string) {
if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.replica", ksName, shardName), 2); err != nil {
require.NoError(t, err)
}
if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.rdonly", ksName, shardName), 1); err != nil {
require.NoError(t, err)
}
}
custKs := vc.Cells[defaultCell.Name].Keyspaces[ksName]
targetTab2 = custKs.Shards["80-c0"].Tablets["zone1-600"].Vttablet
targetTab1 = custKs.Shards["40-80"].Tablets["zone1-500"].Vttablet
targetReplicaTab1 = custKs.Shards["-40"].Tablets["zone1-401"].Vttablet

sourceReplicaTab = custKs.Shards["-80"].Tablets["zone1-201"].Vttablet
sourceTab = custKs.Shards["-80"].Tablets["zone1-200"].Vttablet
sourceReplicaTab = custKs.Shards["-80"].Tablets["zone1-201"].Vttablet
sourceRdonlyTab = custKs.Shards["-80"].Tablets["zone1-202"].Vttablet
}

func tstApplySchemaOnlineDDL(t *testing.T, sql string, keyspace string) {
Expand Down
23 changes: 19 additions & 4 deletions go/vt/vtctl/vtctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2340,7 +2340,7 @@ func commandVRWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla
const defaultMaxReplicationLagAllowed = defaultWaitTime

cells := subFlags.String("cells", "", "Cell(s) or CellAlias(es) (comma-separated) to replicate from.")
tabletTypes := subFlags.String("tablet_types", "in_order:REPLICA,PRIMARY", "Source tablet types to replicate from (e.g. PRIMARY, REPLICA, RDONLY). Defaults to --vreplication_tablet_type parameter value for the tablet, which has the default value of in_order:REPLICA,PRIMARY.")
tabletTypes := subFlags.String("tablet_types", "in_order:REPLICA,PRIMARY", "Source tablet types to replicate from (e.g. PRIMARY, REPLICA, RDONLY). Defaults to --vreplication_tablet_type parameter value for the tablet, which has the default value of in_order:REPLICA,PRIMARY. Note: SwitchTraffic overrides this default and uses in_order:RDONLY,REPLICA,PRIMARY to switch all traffic by default.")
dryRun := subFlags.Bool("dry_run", false, "Does a dry run of SwitchReads and only reports the actions to be taken. --dry_run is only supported for SwitchTraffic, ReverseTraffic and Complete.")
timeout := subFlags.Duration("timeout", defaultWaitTime, "Specifies the maximum time to wait, in seconds, for vreplication to catch up on primary migrations. The migration will be cancelled on a timeout. --timeout is only supported for SwitchTraffic and ReverseTraffic.")
reverseReplication := subFlags.Bool("reverse_replication", true, "Also reverse the replication (default true). --reverse_replication is only supported for SwitchTraffic.")
Expand Down Expand Up @@ -2499,9 +2499,12 @@ func commandVRWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla
vrwp.TabletTypes = *tabletTypes
case vReplicationWorkflowActionSwitchTraffic, vReplicationWorkflowActionReverseTraffic:
vrwp.Cells = *cells
vrwp.TabletTypes = *tabletTypes
if vrwp.TabletTypes == "" {
vrwp.TabletTypes = "in_order:REPLICA,PRIMARY"
if userPassedFlag(subFlags, "tablet_types") {
vrwp.TabletTypes = *tabletTypes
} else {
// When no tablet types are specified we are supposed to switch all traffic so
// we override the normal default for tablet_types.
vrwp.TabletTypes = "in_order:RDONLY,REPLICA,PRIMARY"
}
vrwp.Timeout = *timeout
vrwp.EnableReverseReplication = *reverseReplication
Expand Down Expand Up @@ -4276,3 +4279,15 @@ func PrintAllCommands(logger logutil.Logger) {
logger.Printf("\n")
}
}

// userPassedFlag returns true if the flag name given was provided
// as a command-line argument by the user.
func userPassedFlag(flags *flag.FlagSet, name string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

passed := false
flags.Visit(func(f *flag.Flag) {
if f.Name == name {
passed = true
}
})
return passed
}