github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachtest/namespace_upgrade.go (about)

     1  // Copyright 2020 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package main
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"time"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/util/retry"
    19  )
    20  
    21  func registerNamespaceUpgrade(r *testRegistry) {
    22  	r.Add(testSpec{
    23  		Name:  "version/namespace-upgrade",
    24  		Owner: OwnerSQLSchema,
    25  		// This test is a regression test designed to test for #49092.
    26  		// It drops objects from the 19.2 node after the 20.1 node joins the
    27  		// cluster, and also drops/adds objects in each of the states before, during
    28  		// and after the migration, making sure results are as we expect.
    29  		MinVersion: "v20.1.0",
    30  		Cluster:    makeClusterSpec(3),
    31  		Run: func(ctx context.Context, t *test, c *cluster) {
    32  			predV, err := PredecessorVersion(r.buildVersion)
    33  			if err != nil {
    34  				t.Fatal(err)
    35  			}
    36  			runNamespaceUpgrade(ctx, t, c, predV)
    37  		},
    38  	})
    39  }
    40  
    41  func createTableStep(node int, table string) versionStep {
    42  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    43  		db := u.conn(ctx, t, node)
    44  		_, err := db.ExecContext(ctx,
    45  			fmt.Sprintf(`CREATE TABLE %s (a INT)`, table))
    46  		if err != nil {
    47  			t.Fatal(err)
    48  		}
    49  	}
    50  }
    51  
    52  func createDBStep(node int, name string) versionStep {
    53  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    54  		db := u.conn(ctx, t, node)
    55  		_, err := db.ExecContext(ctx,
    56  			fmt.Sprintf(`CREATE DATABASE %s`, name))
    57  		if err != nil {
    58  			t.Fatal(err)
    59  		}
    60  	}
    61  }
    62  
    63  func dropTableStep(node int, table string) versionStep {
    64  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    65  		db := u.conn(ctx, t, node)
    66  		_, err := db.ExecContext(ctx,
    67  			fmt.Sprintf(`DROP TABLE %s`, table))
    68  		if err != nil {
    69  			t.Fatal(err)
    70  		}
    71  	}
    72  }
    73  
    74  func dropDBStep(node int, name string) versionStep {
    75  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    76  		db := u.conn(ctx, t, node)
    77  		_, err := db.ExecContext(ctx,
    78  			fmt.Sprintf(`DROP DATABASE %s`, name))
    79  		if err != nil {
    80  			t.Fatal(err)
    81  		}
    82  	}
    83  }
    84  
    85  func renameDBStep(node int, oldDB string, newDB string) versionStep {
    86  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    87  		db := u.conn(ctx, t, node)
    88  		_, err := db.ExecContext(ctx,
    89  			fmt.Sprintf(`ALTER DATABASE %s RENAME TO %s`, oldDB, newDB))
    90  		if err != nil {
    91  			t.Fatal(err)
    92  		}
    93  	}
    94  }
    95  
    96  func renameTableStep(node int, oldTable string, newTable string) versionStep {
    97  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
    98  		db := u.conn(ctx, t, node)
    99  		_, err := db.ExecContext(ctx,
   100  			fmt.Sprintf(`ALTER TABLE %s RENAME TO %s`, oldTable, newTable))
   101  		if err != nil {
   102  			t.Fatal(err)
   103  		}
   104  	}
   105  }
   106  
   107  func truncateTableStep(node int, table string) versionStep {
   108  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
   109  		db := u.conn(ctx, t, node)
   110  		_, err := db.ExecContext(ctx,
   111  			fmt.Sprintf(`TRUNCATE %s`, table))
   112  		if err != nil {
   113  			t.Fatal(err)
   114  		}
   115  	}
   116  }
   117  
   118  func showDatabasesStep(node int) versionStep {
   119  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
   120  		db := u.conn(ctx, t, node)
   121  		_, err := db.ExecContext(ctx,
   122  			`SHOW DATABASES`)
   123  		if err != nil {
   124  			t.Fatal(err)
   125  		}
   126  	}
   127  }
   128  
   129  func changeMigrationSetting(node int, enable bool) versionStep {
   130  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
   131  		db := u.conn(ctx, t, node)
   132  		_, err := db.ExecContext(ctx, `SET CLUSTER SETTING testing.system_namespace_migration.enabled = $1`, enable)
   133  		if err != nil {
   134  			t.Fatal(err)
   135  		}
   136  	}
   137  }
   138  
   139  func verifyNoOrphanedOldEntries(node int) versionStep {
   140  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
   141  		db := u.conn(ctx, t, node)
   142  		// Check that there are no rows in namespace that aren't in namespace2,
   143  		// except for the old entry for namespace (descriptor 2) which we don't
   144  		//copy.
   145  		row := db.QueryRowContext(ctx,
   146  			`SELECT count(*) FROM [2 AS namespace] WHERE id != 2 AND id NOT IN (SELECT id FROM [30 as namespace2])`)
   147  		var count int
   148  		if err := row.Scan(&count); err != nil {
   149  			t.Fatal(err)
   150  		}
   151  		if count != 0 {
   152  			t.Fatal("unexpected entries found in namespace but not in namespace2")
   153  		}
   154  	}
   155  
   156  }
   157  
   158  func uploadAndStart(nodes nodeListOption, v string) versionStep {
   159  	return func(ctx context.Context, t *test, u *versionUpgradeTest) {
   160  		// Put and start the binary.
   161  		args := u.uploadVersion(ctx, t, nodes, v)
   162  		// NB: can't start sequentially since cluster already bootstrapped.
   163  		u.c.Start(ctx, t, nodes, args, startArgsDontEncrypt, roachprodArgOption{"--sequential=false"})
   164  	}
   165  }
   166  
   167  func runNamespaceUpgrade(ctx context.Context, t *test, c *cluster, predecessorVersion string) {
   168  	roachNodes := c.All()
   169  	// An empty string means that the cockroach binary specified by flag
   170  	// `cockroach` will be used.
   171  	const mainVersion = ""
   172  	u := newVersionUpgradeTest(c,
   173  		uploadAndStart(roachNodes, predecessorVersion),
   174  		waitForUpgradeStep(roachNodes),
   175  		preventAutoUpgradeStep(1),
   176  
   177  		// Make some objects on node 1.
   178  		createTableStep(1, "a"),
   179  		createTableStep(1, "todrop"),
   180  		createTableStep(1, "torename"),
   181  		createTableStep(1, "totruncate"),
   182  		createDBStep(1, "foo"),
   183  		createDBStep(1, "todrop"),
   184  		createDBStep(1, "torename"),
   185  
   186  		// Upgrade Node 3.
   187  		binaryUpgradeStep(c.Node(3), mainVersion),
   188  
   189  		// Disable the migration. We'll re-enable it later.
   190  		changeMigrationSetting(3, false),
   191  
   192  		// Drop the objects on node 1, which is still on the old version.
   193  		dropTableStep(1, "a"),
   194  		dropDBStep(1, "foo"),
   195  
   196  		// Verify that the new node can still run SHOW DATABASES.
   197  		showDatabasesStep(3),
   198  		// Verify that the new node can recreate the dropped objects.
   199  		createTableStep(3, "a"),
   200  		createDBStep(3, "foo"),
   201  
   202  		// Drop the objects on node 1 again, which is still on the old version.
   203  		dropTableStep(1, "a"),
   204  		dropDBStep(1, "foo"),
   205  
   206  		// Upgrade the other 2 nodes.
   207  		binaryUpgradeStep(c.Node(1), mainVersion),
   208  		binaryUpgradeStep(c.Node(2), mainVersion),
   209  
   210  		// Finalize upgrade.
   211  		allowAutoUpgradeStep(1),
   212  
   213  		waitForUpgradeStep(roachNodes),
   214  
   215  		// After finalization, but before upgrade, add a table, drop a table,
   216  		// rename a table, and truncate a table.
   217  		createTableStep(1, "fresh"),
   218  		createDBStep(1, "fresh"),
   219  		dropTableStep(1, "todrop"),
   220  		dropDBStep(1, "todrop"),
   221  		renameTableStep(1, "torename", "new"),
   222  		renameDBStep(1, "torename", "new"),
   223  		truncateTableStep(1, "totruncate"),
   224  
   225  		// Re-enable the migration.
   226  		changeMigrationSetting(1, true),
   227  
   228  		// Wait for the migration to finish.
   229  		func(ctx context.Context, t *test, u *versionUpgradeTest) {
   230  			t.l.Printf("waiting for cluster to finish namespace migration\n")
   231  
   232  			for _, i := range roachNodes {
   233  				err := retry.ForDuration(30*time.Second, func() error {
   234  					db := u.conn(ctx, t, i)
   235  					// This is copied from pkg/sqlmigrations/migrations.go. We don't
   236  					// export it just for this test because it feels unnecessary.
   237  					const systemNamespaceMigrationName = "upgrade system.namespace post-20.1-finalization"
   238  					var complete bool
   239  					if err := db.QueryRowContext(ctx,
   240  						`SELECT crdb_internal.completed_migrations() @> ARRAY[$1::string]`,
   241  						systemNamespaceMigrationName,
   242  					).Scan(&complete); err != nil {
   243  						t.Fatal(err)
   244  					}
   245  					if !complete {
   246  						return fmt.Errorf("%d: migration not complete", i)
   247  					}
   248  					return nil
   249  				})
   250  				if err != nil {
   251  					t.Fatal(err)
   252  				}
   253  			}
   254  		},
   255  
   256  		// Verify that there are no remaining entries that only live in the old
   257  		// namespace table.
   258  		verifyNoOrphanedOldEntries(1),
   259  
   260  		// Verify that the cluster can run SHOW DATABASES and re-use the names.
   261  		showDatabasesStep(3),
   262  		createTableStep(1, "a"),
   263  		createDBStep(1, "foo"),
   264  		createTableStep(1, "torename"),
   265  		createDBStep(1, "torename"),
   266  		createTableStep(1, "todrop"),
   267  		createDBStep(1, "todrop"),
   268  
   269  		verifyNoOrphanedOldEntries(1),
   270  	)
   271  	u.run(ctx, t)
   272  
   273  }