diff --git a/.github/docker/cluster_test_vtctlbackup_sharded_clustertest_heavy/Dockerfile b/.github/docker/cluster_test_vtctlbackup_sharded_clustertest_heavy/Dockerfile new file mode 100644 index 00000000000..587c4ad8255 --- /dev/null +++ b/.github/docker/cluster_test_vtctlbackup_sharded_clustertest_heavy/Dockerfile @@ -0,0 +1,34 @@ +# DO NOT MODIFY: THIS FILE IS GENERATED USING "make generate_ci_workflows" + +ARG bootstrap_version=14 +ARG image="vitess/bootstrap:${bootstrap_version}-mysql80" + +FROM "${image}" + +USER root + +# Re-copy sources from working tree +RUN rm -rf /vt/src/vitess.io/vitess/* +COPY . /vt/src/vitess.io/vitess + +# Set the working directory +WORKDIR /vt/src/vitess.io/vitess + +# Fix permissions +RUN chown -R vitess:vitess /vt + +USER vitess + +# Set environment variables +ENV VTROOT /vt/src/vitess.io/vitess +# Set the vtdataroot such that it uses the volume mount +ENV VTDATAROOT /vt/vtdataroot + +# create the vtdataroot directory +RUN mkdir -p $VTDATAROOT + +# install goimports +RUN go install golang.org/x/tools/cmd/goimports@latest + +# sleep for 50 minutes +CMD sleep 3000 diff --git a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml index 63bd8d31f18..4812d98490e 100644 --- a/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml +++ b/.github/workflows/cluster_endtoend_ers_prs_newfeatures_heavy.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml index f259620adcb..12edc4ee4e4 100644 --- a/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml +++ b/.github/workflows/cluster_endtoend_vreplication_across_db_versions.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_basic.yml b/.github/workflows/cluster_endtoend_vreplication_basic.yml index 4bb4bfd3b88..981e8bacbcf 100644 --- a/.github/workflows/cluster_endtoend_vreplication_basic.yml +++ b/.github/workflows/cluster_endtoend_vreplication_basic.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml index 805ed44966b..8f9a32bc8d5 100644 --- a/.github/workflows/cluster_endtoend_vreplication_cellalias.yml +++ b/.github/workflows/cluster_endtoend_vreplication_cellalias.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml b/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml index 5d17d83718e..c987b1f9372 100644 --- a/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml +++ b/.github/workflows/cluster_endtoend_vreplication_migrate_vdiff2_convert_tz.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_multicell.yml b/.github/workflows/cluster_endtoend_vreplication_multicell.yml index 8d341b62646..8719d1579b7 100644 --- a/.github/workflows/cluster_endtoend_vreplication_multicell.yml +++ b/.github/workflows/cluster_endtoend_vreplication_multicell.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vreplication_v2.yml b/.github/workflows/cluster_endtoend_vreplication_v2.yml index ea3c0ddf424..b9d9151ff4d 100644 --- a/.github/workflows/cluster_endtoend_vreplication_v2.yml +++ b/.github/workflows/cluster_endtoend_vreplication_v2.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml index a104c356fa4..3f5a82fe7f5 100644 --- a/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtctlbackup_sharded_clustertest_heavy.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml index 8c32aabd2b8..c03620bfdc0 100644 --- a/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_general_heavy.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml index 6db0341aa08..6dfef58ee69 100644 --- a/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml +++ b/.github/workflows/cluster_endtoend_vtgate_vindex_heavy.yml @@ -130,6 +130,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/.github/workflows/unit_test_mariadb103.yml b/.github/workflows/unit_test_mariadb103.yml index ea13a6b46e3..31140ffdd4f 100644 --- a/.github/workflows/unit_test_mariadb103.yml +++ b/.github/workflows/unit_test_mariadb103.yml @@ -110,4 +110,8 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' timeout-minutes: 30 run: | + + # mariadb103 + export MYSQL_FLAVOR="MariaDB103" + eatmydata -- make unit_test diff --git a/.github/workflows/unit_test_mysql57.yml b/.github/workflows/unit_test_mysql57.yml index 5f1ca916056..276a31888c3 100644 --- a/.github/workflows/unit_test_mysql57.yml +++ b/.github/workflows/unit_test_mysql57.yml @@ -116,4 +116,5 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' timeout-minutes: 30 run: | + eatmydata -- make unit_test diff --git a/.github/workflows/unit_test_mysql80.yml b/.github/workflows/unit_test_mysql80.yml index c7fa0c9758a..3b38ee78cb4 100644 --- a/.github/workflows/unit_test_mysql80.yml +++ b/.github/workflows/unit_test_mysql80.yml @@ -113,4 +113,5 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' timeout-minutes: 30 run: | + eatmydata -- make unit_test diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml index 119824bf726..405fab88575 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e.yml @@ -37,162 +37,166 @@ jobs: - get_previous_release steps: - - name: Skip CI - run: | - if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then - echo "skipping CI due to the 'Skip CI' label" - exit 1 - fi - - - name: Check if workflow needs to be skipped - id: skip-workflow - run: | - skip='false' - if [[ "${{github.event.pull_request}}" == "" ]] && [[ "${{github.ref}}" != "refs/heads/main" ]] && [[ ! "${{github.ref}}" =~ ^refs/heads/release-[0-9]+\.[0-9]$ ]] && [[ ! "${{github.ref}}" =~ "refs/tags/.*" ]]; then - skip='true' - fi - echo Skip ${skip} - echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT - - - name: Check out commit's code - if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: actions/checkout@v3 - - - name: Check for changes in relevant files - if: steps.skip-workflow.outputs.skip-workflow == 'false' - uses: frouioui/paths-filter@main - id: changes - with: - token: '' - filters: | - end_to_end: - - 'go/**' - - 'go/**/*.go' - - 'test.go' - - 'Makefile' - - 'build.env' - - 'go.sum' - - 'go.mod' - - 'proto/*.proto' - - 'tools/**' - - 'config/**' - - 'bootstrap.sh' - - '.github/workflows/upgrade_downgrade_test_backups_e2e.yml' - - - name: Set up Go - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-go@v3 - with: - go-version: 1.19.4 - - - name: Set up python - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/setup-python@v4 - - - name: Tune the OS - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" - - - name: Get base dependencies - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - sudo apt-get update - sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata - sudo service mysql stop - sudo service etcd stop - sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ - sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - go mod download - - # install JUnit report formatter - go install github.com/vitessio/go-junit-report@HEAD - - wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get install -y gnupg2 - sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb - sudo apt-get update - sudo apt-get install percona-xtrabackup-24 - - # Checkout to the last release of Vitess - - name: Check out other version's code (${{ needs.get_previous_release.outputs.previous_release }}) - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/checkout@v3 - with: - ref: ${{ needs.get_previous_release.outputs.previous_release }} - - - name: Get dependencies for the last release - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - go mod download - - - name: Building last release's binaries - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - source build.env - make build - mkdir -p /tmp/vitess-build-other/ - cp -R bin /tmp/vitess-build-other/ - rm -Rf bin/* - - # Checkout to this build's commit - - name: Check out commit's code - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - uses: actions/checkout@v3 - - - name: Get dependencies for this commit - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - go mod download - - - name: Building the binaries for this commit - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - timeout-minutes: 10 - run: | - source build.env - make build - mkdir -p /tmp/vitess-build-current/ - cp -R bin /tmp/vitess-build-current/ - - # Swap binaries, use last release's VTTablet - - name: Use last release's VTTablet - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - source build.env - - rm -f $PWD/bin/vttablet - cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet - vttablet --version - - # Run test with VTTablet at version N-1 and VTBackup at version N - - name: Run backups tests (vttablet=N-1, vtbackup=N) - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - rm -rf /tmp/vtdataroot - mkdir -p /tmp/vtdataroot - set -x - source build.env - eatmydata -- go run test.go -skip-build -docker=false -print-log -follow -tag upgrade_downgrade_backups - - # Swap binaries again, use current version's VTTablet, and last release's VTBackup - - name: Use current version VTTablet, and other version VTBackup - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - source build.env - - rm -f $PWD/bin/vtbackup $PWD/bin/vttablet - cp /tmp/vitess-build-current/bin/vtbackup $PWD/bin/vtbackup - cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet - vtbackup --version - vttablet --version - - # Run test again with VTTablet at version N, and VTBackup at version N-1 - - name: Run backups tests (vttablet=N, vtbackup=N-1) - if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' - run: | - rm -rf /tmp/vtdataroot - mkdir -p /tmp/vtdataroot - set -x - source build.env - eatmydata -- go run test.go -skip-build -keep-data -docker=false -print-log -follow -tag upgrade_downgrade_backups + - name: Skip CI + run: | + if [[ "${{contains( github.event.pull_request.labels.*.name, 'Skip CI')}}" == "true" ]]; then + echo "skipping CI due to the 'Skip CI' label" + exit 1 + fi + + - name: Check if workflow needs to be skipped + id: skip-workflow + run: | + skip='false' + if [[ "${{github.event.pull_request}}" == "" ]] && [[ "${{github.ref}}" != "refs/heads/main" ]] && [[ ! "${{github.ref}}" =~ ^refs/heads/release-[0-9]+\.[0-9]$ ]] && [[ ! "${{github.ref}}" =~ "refs/tags/.*" ]]; then + skip='true' + fi + echo Skip ${skip} + echo "skip-workflow=${skip}" >> $GITHUB_OUTPUT + + - name: Check out commit's code + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: actions/checkout@v3 + + - name: Check for changes in relevant files + if: steps.skip-workflow.outputs.skip-workflow == 'false' + uses: frouioui/paths-filter@main + id: changes + with: + token: '' + filters: | + end_to_end: + - 'go/**' + - 'go/**/*.go' + - 'test.go' + - 'Makefile' + - 'build.env' + - 'go.sum' + - 'go.mod' + - 'proto/*.proto' + - 'tools/**' + - 'config/**' + - 'bootstrap.sh' + - '.github/workflows/upgrade_downgrade_test_backups_e2e.yml' + + - name: Set up Go + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-go@v3 + with: + go-version: 1.19.4 + + - name: Set up python + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/setup-python@v4 + + - name: Tune the OS + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + sudo sysctl -w net.ipv4.ip_local_port_range="22768 65535" + + - name: Get base dependencies + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + sudo apt-get update + sudo apt-get install -y mysql-server mysql-client make unzip g++ etcd curl git wget eatmydata + sudo service mysql stop + sudo service etcd stop + sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/ + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld + go mod download + + # install JUnit report formatter + go install github.com/vitessio/go-junit-report@HEAD + + wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt-get install -y gnupg2 + sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb + sudo apt-get update + sudo apt-get install percona-xtrabackup-24 + + # Checkout to the last release of Vitess + - name: Check out other version's code (${{ needs.get_previous_release.outputs.previous_release }}) + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/checkout@v3 + with: + ref: ${{ needs.get_previous_release.outputs.previous_release }} + + - name: Get dependencies for the last release + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + go mod download + + - name: Building last release's binaries + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 10 + run: | + source build.env + make build + mkdir -p /tmp/vitess-build-other/ + cp -R bin /tmp/vitess-build-other/ + rm -Rf bin/* + + # Checkout to this build's commit + - name: Check out commit's code + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + uses: actions/checkout@v3 + + - name: Get dependencies for this commit + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + go mod download + + - name: Building the binaries for this commit + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + timeout-minutes: 10 + run: | + source build.env + make build + mkdir -p /tmp/vitess-build-current/ + cp -R bin /tmp/vitess-build-current/ + + # Swap binaries, use last release's VTTablet + - name: Use last release's VTTablet + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + source build.env + + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld + cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld + vttablet --version + + # Run test with VTTablet at version N-1 and VTBackup at version N + - name: Run backups tests (vttablet=N-1, vtbackup=N) + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + rm -rf /tmp/vtdataroot + mkdir -p /tmp/vtdataroot + set -x + source build.env + eatmydata -- go run test.go -skip-build -docker=false -print-log -follow -tag upgrade_downgrade_backups + + # Swap binaries again, use current version's VTTablet (N), and last release's VTBackup (N-1) + - name: Use current version VTTablet (N), and other version VTBackup (N-1) + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + source build.env + + rm -f $PWD/bin/vtbackup $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld + cp /tmp/vitess-build-other/bin/vtbackup $PWD/bin/vtbackup + cp /tmp/vitess-build-current/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-current/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-current/bin/mysqlctld $PWD/bin/mysqlctld + vtbackup --version + vttablet --version + + # Run test again with VTTablet at version N, and VTBackup at version N-1 + - name: Run backups tests (vttablet=N, vtbackup=N-1) + if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' + run: | + rm -rf /tmp/vtdataroot + mkdir -p /tmp/vtdataroot + set -x + source build.env + eatmydata -- go run test.go -skip-build -keep-data -docker=false -print-log -follow -tag upgrade_downgrade_backups diff --git a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml index d92522c0091..b56cd853b24 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_e2e_next_release.yml @@ -164,8 +164,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vttablet --version # Run test with VTTablet at version N+1 and VTBackup at version N @@ -184,9 +186,11 @@ jobs: run: | source build.env - rm -f $PWD/bin/vtbackup $PWD/bin/vttablet - cp /tmp/vitess-build-current/bin/vtbackup $PWD/bin/vtbackup - cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + rm -f $PWD/bin/vtbackup $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld + cp /tmp/vitess-build-other/bin/vtbackup $PWD/bin/vtbackup + cp /tmp/vitess-build-current/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-current/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-current/bin/mysqlctld $PWD/bin/mysqlctld vtbackup --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual.yml b/.github/workflows/upgrade_downgrade_test_backups_manual.yml index 8d6044ae39f..d5c4ba0c928 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual.yml @@ -248,8 +248,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vttablet --version # Starting the tablets again, they will automatically start restoring the last backup. @@ -304,8 +306,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-current/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-current/bin/mysqlctld $PWD/bin/mysqlctld vttablet --version # Starting the tablets again and restoring the previous backup. diff --git a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml index 2ee113a8719..30f3e4c5a55 100644 --- a/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_backups_manual_next_release.yml @@ -251,8 +251,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vttablet --version # Starting the tablets again, they will automatically start restoring the last backup. @@ -307,8 +309,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-current/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-current/bin/mysqlctld $PWD/bin/mysqlctld vttablet --version # Starting the tablets again and restoring the next backup. diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml index 78ed23fec0b..377ee8969a2 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries.yml @@ -209,9 +209,11 @@ jobs: run: | source build.env - rm -f $PWD/bin/vtgate $PWD/bin/vttablet + rm -f $PWD/bin/vtgate $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vtgate $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtgate --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml b/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml index 3776a8891e2..d281586400c 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_queries_next_release.yml @@ -212,9 +212,11 @@ jobs: run: | source build.env - rm -f $PWD/bin/vtgate $PWD/bin/vttablet + rm -f $PWD/bin/vtgate $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vtgate $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtgate --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml index 981a6635b93..08414a3c409 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema.yml @@ -209,9 +209,11 @@ jobs: run: | source build.env - rm -f $PWD/bin/vtgate $PWD/bin/vttablet + rm -f $PWD/bin/vtgate $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vtgate $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtgate --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml b/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml index 2fb675c3bfc..1a085c06b52 100644 --- a/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml +++ b/.github/workflows/upgrade_downgrade_test_query_serving_schema_next_release.yml @@ -212,9 +212,11 @@ jobs: run: | source build.env - rm -f $PWD/bin/vtgate $PWD/bin/vttablet + rm -f $PWD/bin/vtgate $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-current/bin/vtgate $PWD/bin/vtgate cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtgate --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml index d5d024a377c..7a69dca41e4 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_new_vttablet.yml @@ -182,8 +182,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtctl --version vttablet --version diff --git a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml index 937e8d6ee3c..e39b472b13d 100644 --- a/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml +++ b/.github/workflows/upgrade_downgrade_test_reparent_old_vttablet.yml @@ -179,8 +179,10 @@ jobs: run: | source build.env - rm -f $PWD/bin/vttablet + rm -f $PWD/bin/vttablet $PWD/bin/mysqlctl $PWD/bin/mysqlctld cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttablet + cp /tmp/vitess-build-other/bin/mysqlctl $PWD/bin/mysqlctl + cp /tmp/vitess-build-other/bin/mysqlctld $PWD/bin/mysqlctld vtctl --version vttablet --version diff --git a/config/embed.go b/config/embed.go index 121fa29cee2..1228d04e69e 100644 --- a/config/embed.go +++ b/config/embed.go @@ -28,3 +28,6 @@ var MycnfMySQL57 string //go:embed mycnf/mysql80.cnf var MycnfMySQL80 string + +//go:embed init_maria_db.sql +var DefaultInitMariaDB string diff --git a/config/init_db.sql b/config/init_db.sql index 67a41d98c4b..0b9652adc68 100644 --- a/config/init_db.sql +++ b/config/init_db.sql @@ -11,6 +11,12 @@ ############################################################################### # Equivalent of mysql_secure_installation ############################################################################### +# We need to ensure that super_read_only is disabled so that we can execute +# these commands. Note that disabling it does NOT disable read_only. +# We save the current value so that we only re-enable it at the end if it was +# enabled before. +SET @original_super_read_only=IF(@@global.super_read_only=1, 'ON', 'OFF'); +SET GLOBAL super_read_only='OFF'; # Changes during the init db should not make it to the binlog. # They could potentially create errant transactions on replicas. @@ -28,23 +34,6 @@ DROP DATABASE IF EXISTS test; # Vitess defaults ############################################################################### -# Vitess-internal database. -CREATE DATABASE IF NOT EXISTS _vt; -# Note that definitions of local_metadata and shard_metadata should be the same -# as in production which is defined in go/vt/mysqlctl/metadata_tables.go. -CREATE TABLE IF NOT EXISTS _vt.local_metadata ( - name VARCHAR(255) NOT NULL, - value VARCHAR(255) NOT NULL, - db_name VARBINARY(255) NOT NULL, - PRIMARY KEY (db_name, name) - ) ENGINE=InnoDB; -CREATE TABLE IF NOT EXISTS _vt.shard_metadata ( - name VARCHAR(255) NOT NULL, - value MEDIUMBLOB NOT NULL, - db_name VARBINARY(255) NOT NULL, - PRIMARY KEY (db_name, name) - ) ENGINE=InnoDB; - # Admin user with all privileges. CREATE USER 'vt_dba'@'localhost'; GRANT ALL ON *.* TO 'vt_dba'@'localhost'; @@ -90,7 +79,16 @@ GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD GRANT SELECT, UPDATE, DELETE, DROP ON performance_schema.* TO 'vt_monitoring'@'localhost'; +# User for Orchestrator (https://github.com/openark/orchestrator). +CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; +GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD + ON *.* TO 'orc_client_user'@'%'; FLUSH PRIVILEGES; RESET SLAVE ALL; RESET MASTER; + +# add custom sql here + +# We need to set super_read_only back to what it was before +SET GLOBAL super_read_only=IFNULL(@original_super_read_only, 'OFF'); diff --git a/config/init_maria_db.sql b/config/init_maria_db.sql new file mode 100644 index 00000000000..f33c18d4072 --- /dev/null +++ b/config/init_maria_db.sql @@ -0,0 +1,106 @@ +# This file is executed immediately after mysql_install_db, +# to initialize a fresh data directory. It is mariaDB equivalent of init_db.sql. +# Since init_db.sql is for mysql which has super_read_only related stuff, and mariaDB +# does not recognize super_read_only, therefore we end up creating this file + +############################################################################### +# WARNING: This sql is *NOT* safe for production use, +# as it contains default well-known users and passwords. +# Care should be taken to change these users and passwords +# for production. +############################################################################### + +############################################################################### +# Equivalent of mysql_secure_installation +############################################################################### +# Changes during the init db should not make it to the binlog. +# They could potentially create errant transactions on replicas. +SET sql_log_bin = 0; +# Remove anonymous users. +DELETE FROM mysql.user WHERE User = ''; + +# Disable remote root access (only allow UNIX socket). +DELETE FROM mysql.user WHERE User = 'root' AND Host != 'localhost'; + +# Remove test database. +DROP DATABASE IF EXISTS test; + +############################################################################### +# Vitess defaults +############################################################################### + +# Vitess-internal database. +CREATE DATABASE IF NOT EXISTS _vt; +# Note that definitions of local_metadata and shard_metadata should be the same +# as in production which is defined in go/vt/mysqlctl/metadata_tables.go. +CREATE TABLE IF NOT EXISTS _vt.local_metadata ( + name VARCHAR(255) NOT NULL, + value VARCHAR(255) NOT NULL, + db_name VARBINARY(255) NOT NULL, + PRIMARY KEY (db_name, name) + ) ENGINE=InnoDB; +CREATE TABLE IF NOT EXISTS _vt.shard_metadata ( + name VARCHAR(255) NOT NULL, + value MEDIUMBLOB NOT NULL, + db_name VARBINARY(255) NOT NULL, + PRIMARY KEY (db_name, name) + ) ENGINE=InnoDB; + +# Admin user with all privileges. +CREATE USER 'vt_dba'@'localhost'; +GRANT ALL ON *.* TO 'vt_dba'@'localhost'; +GRANT GRANT OPTION ON *.* TO 'vt_dba'@'localhost'; + +# User for app traffic, with global read-write access. +CREATE USER 'vt_app'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_app'@'localhost'; + +# User for app debug traffic, with global read access. +CREATE USER 'vt_appdebug'@'localhost'; +GRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost'; + +# User for administrative operations that need to be executed as non-SUPER. +# Same permissions as vt_app here. +CREATE USER 'vt_allprivs'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_allprivs'@'localhost'; + +# User for slave replication connections. +CREATE USER 'vt_repl'@'%'; +GRANT REPLICATION SLAVE ON *.* TO 'vt_repl'@'%'; + +# User for Vitess VReplication (base vstreamers and vplayer). +CREATE USER 'vt_filtered'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_filtered'@'localhost'; + +# User for general MySQL monitoring. +CREATE USER 'vt_monitoring'@'localhost'; +GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD + ON *.* TO 'vt_monitoring'@'localhost'; +GRANT SELECT, UPDATE, DELETE, DROP + ON performance_schema.* TO 'vt_monitoring'@'localhost'; + +# User for Orchestrator (https://github.com/openark/orchestrator). +CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; +GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD + ON *.* TO 'orc_client_user'@'%'; +GRANT SELECT + ON _vt.* TO 'orc_client_user'@'%'; + +FLUSH PRIVILEGES; + +RESET SLAVE ALL; +RESET MASTER; + +# add custom sql here diff --git a/config/init_testserver_db.sql b/config/init_testserver_db.sql new file mode 100644 index 00000000000..5eb2cd8c5b2 --- /dev/null +++ b/config/init_testserver_db.sql @@ -0,0 +1,88 @@ +# This file is executed immediately after mysql_install_db, +# to initialize a fresh data directory. + +############################################################################### +# WARNING: This sql is *NOT* safe for production use, +# as it contains default well-known users and passwords. +# Care should be taken to change these users and passwords +# for production. +############################################################################### + +############################################################################### +# Equivalent of mysql_secure_installation +############################################################################### +# We need to ensure that read_only is disabled so that we can execute +# these commands. +SET GLOBAL read_only='OFF'; + +# Changes during the init db should not make it to the binlog. +# They could potentially create errant transactions on replicas. +SET sql_log_bin = 0; +# Remove anonymous users. +DELETE FROM mysql.user WHERE User = ''; + +# Disable remote root access (only allow UNIX socket). +DELETE FROM mysql.user WHERE User = 'root' AND Host != 'localhost'; + +# Remove test database. +DROP DATABASE IF EXISTS test; + +############################################################################### +# Vitess defaults +############################################################################### + +# Admin user with all privileges. +CREATE USER 'vt_dba'@'localhost'; +GRANT ALL ON *.* TO 'vt_dba'@'localhost'; +GRANT GRANT OPTION ON *.* TO 'vt_dba'@'localhost'; + +# User for app traffic, with global read-write access. +CREATE USER 'vt_app'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_app'@'localhost'; + +# User for app debug traffic, with global read access. +CREATE USER 'vt_appdebug'@'localhost'; +GRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost'; + +# User for administrative operations that need to be executed as non-SUPER. +# Same permissions as vt_app here. +CREATE USER 'vt_allprivs'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_allprivs'@'localhost'; + +# User for slave replication connections. +CREATE USER 'vt_repl'@'%'; +GRANT REPLICATION SLAVE ON *.* TO 'vt_repl'@'%'; + +# User for Vitess VReplication (base vstreamers and vplayer). +CREATE USER 'vt_filtered'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_filtered'@'localhost'; + +# User for general MySQL monitoring. +CREATE USER 'vt_monitoring'@'localhost'; +GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD + ON *.* TO 'vt_monitoring'@'localhost'; +GRANT SELECT, UPDATE, DELETE, DROP + ON performance_schema.* TO 'vt_monitoring'@'localhost'; + +# User for Orchestrator (https://github.com/openark/orchestrator). +CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; +GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD + ON *.* TO 'orc_client_user'@'%'; +FLUSH PRIVILEGES; + +RESET SLAVE ALL; +RESET MASTER; + +# add custom sql here diff --git a/config/init_unit_test_db.sql b/config/init_unit_test_db.sql new file mode 100644 index 00000000000..5eb2cd8c5b2 --- /dev/null +++ b/config/init_unit_test_db.sql @@ -0,0 +1,88 @@ +# This file is executed immediately after mysql_install_db, +# to initialize a fresh data directory. + +############################################################################### +# WARNING: This sql is *NOT* safe for production use, +# as it contains default well-known users and passwords. +# Care should be taken to change these users and passwords +# for production. +############################################################################### + +############################################################################### +# Equivalent of mysql_secure_installation +############################################################################### +# We need to ensure that read_only is disabled so that we can execute +# these commands. +SET GLOBAL read_only='OFF'; + +# Changes during the init db should not make it to the binlog. +# They could potentially create errant transactions on replicas. +SET sql_log_bin = 0; +# Remove anonymous users. +DELETE FROM mysql.user WHERE User = ''; + +# Disable remote root access (only allow UNIX socket). +DELETE FROM mysql.user WHERE User = 'root' AND Host != 'localhost'; + +# Remove test database. +DROP DATABASE IF EXISTS test; + +############################################################################### +# Vitess defaults +############################################################################### + +# Admin user with all privileges. +CREATE USER 'vt_dba'@'localhost'; +GRANT ALL ON *.* TO 'vt_dba'@'localhost'; +GRANT GRANT OPTION ON *.* TO 'vt_dba'@'localhost'; + +# User for app traffic, with global read-write access. +CREATE USER 'vt_app'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_app'@'localhost'; + +# User for app debug traffic, with global read access. +CREATE USER 'vt_appdebug'@'localhost'; +GRANT SELECT, SHOW DATABASES, PROCESS ON *.* TO 'vt_appdebug'@'localhost'; + +# User for administrative operations that need to be executed as non-SUPER. +# Same permissions as vt_app here. +CREATE USER 'vt_allprivs'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_allprivs'@'localhost'; + +# User for slave replication connections. +CREATE USER 'vt_repl'@'%'; +GRANT REPLICATION SLAVE ON *.* TO 'vt_repl'@'%'; + +# User for Vitess VReplication (base vstreamers and vplayer). +CREATE USER 'vt_filtered'@'localhost'; +GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, FILE, + REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, + LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, + SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER + ON *.* TO 'vt_filtered'@'localhost'; + +# User for general MySQL monitoring. +CREATE USER 'vt_monitoring'@'localhost'; +GRANT SELECT, PROCESS, SUPER, REPLICATION CLIENT, RELOAD + ON *.* TO 'vt_monitoring'@'localhost'; +GRANT SELECT, UPDATE, DELETE, DROP + ON performance_schema.* TO 'vt_monitoring'@'localhost'; + +# User for Orchestrator (https://github.com/openark/orchestrator). +CREATE USER 'orc_client_user'@'%' IDENTIFIED BY 'orc_client_user_password'; +GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD + ON *.* TO 'orc_client_user'@'%'; +FLUSH PRIVILEGES; + +RESET SLAVE ALL; +RESET MASTER; + +# add custom sql here diff --git a/config/mycnf/mysql57.cnf b/config/mycnf/mysql57.cnf index 7a8c45a187c..d1ca819ebd4 100644 --- a/config/mycnf/mysql57.cnf +++ b/config/mycnf/mysql57.cnf @@ -32,3 +32,7 @@ plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisy rpl_semi_sync_master_timeout = 1000000000000000000 rpl_semi_sync_master_wait_no_slave = 1 +# In order to protect against any errand GTIDs we will start mysql instance +# as super-read-only mode. +super-read-only + diff --git a/config/mycnf/mysql80.cnf b/config/mycnf/mysql80.cnf index 39fab576533..449fb465da2 100644 --- a/config/mycnf/mysql80.cnf +++ b/config/mycnf/mysql80.cnf @@ -28,3 +28,7 @@ plugin-load = rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisy loose_rpl_semi_sync_master_timeout = 1000000000000000000 loose_rpl_semi_sync_master_wait_no_slave = 1 +# In order to protect against any errand GTIDs we will start mysql instance +# as super-read-only mode. +super-read-only + diff --git a/config/mycnf/test-suite.cnf b/config/mycnf/test-suite.cnf index e57368a41db..d23efa54a30 100644 --- a/config/mycnf/test-suite.cnf +++ b/config/mycnf/test-suite.cnf @@ -23,3 +23,4 @@ sql_mode = STRICT_TRANS_TABLES # set a short heartbeat interval in order to detect failures quickly slave_net_timeout = 4 +super-read-only = false diff --git a/go.mod b/go.mod index b7a56cb336c..b47c71936b3 100644 --- a/go.mod +++ b/go.mod @@ -82,13 +82,13 @@ require ( golang.org/x/crypto v0.3.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.2.0 + golang.org/x/net v0.3.0 golang.org/x/oauth2 v0.2.0 - golang.org/x/sys v0.2.0 // indirect - golang.org/x/term v0.2.0 - golang.org/x/text v0.4.0 + golang.org/x/sys v0.3.0 // indirect + golang.org/x/term v0.3.0 + golang.org/x/text v0.5.0 golang.org/x/time v0.2.0 - golang.org/x/tools v0.3.0 + golang.org/x/tools v0.4.0 google.golang.org/api v0.103.0 google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472 // indirect google.golang.org/grpc v1.50.1 diff --git a/go.sum b/go.sum index 73684d6541c..6c3d4c00da0 100644 --- a/go.sum +++ b/go.sum @@ -961,8 +961,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1069,13 +1069,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1086,8 +1086,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1155,8 +1156,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go/cmd/vtbackup/vtbackup.go b/go/cmd/vtbackup/vtbackup.go index 4de11422deb..9d5e474235a 100644 --- a/go/cmd/vtbackup/vtbackup.go +++ b/go/cmd/vtbackup/vtbackup.go @@ -74,7 +74,6 @@ import ( "vitess.io/vitess/go/cmd" "vitess.io/vitess/go/exit" "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/sqlescape" "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" @@ -159,7 +158,6 @@ func main() { servenv.ParseFlags("vtbackup") servenv.Init() - ctx, cancel := context.WithCancel(context.Background()) servenv.OnClose(func() { cancel() @@ -296,6 +294,7 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back } // In initial_backup mode, just take a backup of this empty database. if initialBackup { + log.Infof("inside initialBackup creating reparent journal.") // Take a backup of this empty DB without restoring anything. // First, initialize it the way InitShardPrimary would, so this backup // produces a result that can be used to skip InitShardPrimary entirely. @@ -304,7 +303,12 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back if err := mysqld.ResetReplication(ctx); err != nil { return fmt.Errorf("can't reset replication: %v", err) } - cmds := mysqlctl.CreateReparentJournal() + // We need to switch off super-read-only before we create database. + _ = mysqld.SetSuperReadOnly(false) + defer func() { + _ = mysqld.SetSuperReadOnly(true) + }() + /*cmds := mysqlctl.CreateReparentJournal() cmds = append(cmds, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", sqlescape.EscapeID(dbName))) if err := mysqld.ExecuteSuperQueryList(ctx, cmds); err != nil { return fmt.Errorf("can't initialize database: %v", err) @@ -312,6 +316,8 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back // Execute Alter commands on reparent_journal and ignore errors cmds = mysqlctl.AlterReparentJournal() + _ = mysqld.ExecuteSuperQueryList(ctx, cmds)*/ + cmds := mysqlctl.CreateDummyDatabase() _ = mysqld.ExecuteSuperQueryList(ctx, cmds) backupParams.BackupTime = time.Now() @@ -331,7 +337,6 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back Logger: logutil.NewConsoleLogger(), Concurrency: concurrency, HookExtraEnv: extraEnv, - LocalMetadata: map[string]string{}, DeleteBeforeRestore: true, DbName: dbName, Keyspace: initKeyspace, @@ -398,6 +403,8 @@ func takeBackup(ctx context.Context, topoServer *topo.Server, backupStorage back return err } + log.Infof("primary position is: %s", primaryPos.String()) + // Remember the time when we fetched the primary position, not when we caught // up to it, so the timestamp on our backup is honest (assuming we make it // to the goal position). diff --git a/go/cmd/vtclient/vtclient_test.go b/go/cmd/vtclient/vtclient_test.go index 4711b1e0127..bb694cc0eee 100644 --- a/go/cmd/vtclient/vtclient_test.go +++ b/go/cmd/vtclient/vtclient_test.go @@ -32,6 +32,7 @@ import ( func TestVtclient(t *testing.T) { // Build the config for vttest. + var cfg vttest.Config cfg.Topology = &vttestpb.VTTestTopology{ Keyspaces: []*vttestpb.Keyspace{ diff --git a/go/cmd/vtcombo/main.go b/go/cmd/vtcombo/main.go index acbea8ff490..022fb363702 100644 --- a/go/cmd/vtcombo/main.go +++ b/go/cmd/vtcombo/main.go @@ -191,7 +191,7 @@ func main() { servenv.Init() tabletenv.Init() - + //time.Sleep(10 * time.Second) mysqld := &vtcomboMysqld{} var cnf *mysqlctl.Mycnf if *startMysql { diff --git a/go/cmd/vttablet/vttablet.go b/go/cmd/vttablet/vttablet.go index f9c43bd2a2a..c7ee81511d5 100644 --- a/go/cmd/vttablet/vttablet.go +++ b/go/cmd/vttablet/vttablet.go @@ -123,7 +123,6 @@ func main() { UpdateStream: binlog.NewUpdateStream(ts, tablet.Keyspace, tabletAlias.Cell, qsc.SchemaEngine()), VREngine: vreplication.NewEngine(config, ts, tabletAlias.Cell, mysqld, qsc.LagThrottler()), VDiffEngine: vdiff.NewEngine(config, ts, tablet), - MetadataManager: &mysqlctl.MetadataManager{}, } if err := tm.Start(tablet, config.Healthcheck.IntervalSeconds.Get()); err != nil { log.Exitf("failed to parse --tablet-path or initialize DB credentials: %v", err) diff --git a/go/flags/endtoend/r b/go/flags/endtoend/r new file mode 100755 index 00000000000..3f6abf8637d --- /dev/null +++ b/go/flags/endtoend/r @@ -0,0 +1,16 @@ +vtctlclient --help 2> vtctlclient.txt +vtorc --help 2> vtorc.txt +vtgr --help 2> vtgr.txt +vttablet --help 2> vttablet.txt +vtctld --help 2> vtctld.txt +vtctldclient --help > vtctldclient.txt +vtexplain --help 2> vtexplain.txt +vtgate --help 2> vtgate.txt +mysqlctld --help 2> mysqlctld.txt +mysqlctl --help 2> mysqlctl.txt +vtaclcheck --help > vtaclcheck.txt 2>&1 +vtbackup --help 2> vtbackup.txt +vttestserver --help 2> vttestserver.txt +vttlstest > vttlstest.txt +zkctld --help 2> zkctld.txt +zk --help 2> zk.txt diff --git a/go/flags/endtoend/vttablet.txt b/go/flags/endtoend/vttablet.txt index 1e12c2781e1..e8634345c7a 100644 --- a/go/flags/endtoend/vttablet.txt +++ b/go/flags/endtoend/vttablet.txt @@ -149,9 +149,9 @@ Usage of vttablet: --hot_row_protection_concurrent_transactions int Number of concurrent transactions let through to the txpool/MySQL for the same hot row. Should be > 1 to have enough 'ready' transactions in MySQL and benefit from a pipelining effect. (default 5) --hot_row_protection_max_global_queue_size int Global queue limit across all row (ranges). Useful to prevent that the queue can grow unbounded. (default 1000) --hot_row_protection_max_queue_size int Maximum number of BeginExecute RPCs which will be queued for the same row (range). (default 20) + --init-vt-schema-on-tablet-init EXPERIMENTAL: _vt schema is created on tablet init and not separately and/or using WithDDL (default true) --init_db_name_override string (init parameter) override the name of the db used by vttablet. Without this flag, the db name defaults to vt_ --init_keyspace string (init parameter) keyspace to use for this tablet - --init_populate_metadata (init parameter) populate metadata tables even if restore_from_backup is disabled. If restore_from_backup is enabled, metadata tables are always populated regardless of this flag. --init_shard string (init parameter) shard to use for this tablet --init_tablet_type string (init parameter) the tablet type to use for this tablet. --init_tags StringMap (init parameter) comma separated list of key:value pairs used to tag the tablet @@ -347,7 +347,7 @@ Usage of vttablet: --tx_throttler_config string The configuration of the transaction throttler as a text formatted throttlerdata.Configuration protocol buffer message (default "target_replication_lag_sec: 2\nmax_replication_lag_sec: 10\ninitial_rate: 100\nmax_increase: 1\nemergency_decrease: 0.5\nmin_duration_between_increases_sec: 40\nmax_duration_between_increases_sec: 62\nmin_duration_between_decreases_sec: 20\nspread_backlog_across_sec: 20\nage_bad_rate_after_sec: 180\nbad_rate_increase: 0.1\nmax_rate_approach_threshold: 0.9\n") --tx_throttler_healthcheck_cells strings A comma-separated list of cells. Only tabletservers running in these cells will be monitored for replication lag by the transaction throttler. --unhealthy_threshold duration replication lag after which a replica is considered unhealthy (default 2h0m0s) - --use_super_read_only Set super_read_only flag when performing planned failover. + --use_super_read_only Set super_read_only flag when performing planned failover. (default true) --v Level log level for V logs -v, --version print binary version --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging diff --git a/go/mysql/collations/integration/helpers_test.go b/go/mysql/collations/integration/helpers_test.go index d185168d9d1..c2601421bc2 100644 --- a/go/mysql/collations/integration/helpers_test.go +++ b/go/mysql/collations/integration/helpers_test.go @@ -137,7 +137,7 @@ func verifyWeightString(t *testing.T, local collations.Collation, remote *remote } func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { - res, err := conn.ExecuteFetch(query, -1, true) + res, err := conn.ExecuteFetchWithSuperReadOnlyHandling(query, -1, true) require.NoError(t, err, "failed to execute %q: %v", query, err) return res diff --git a/go/mysql/fakesqldb/server.go b/go/mysql/fakesqldb/server.go index c50a105f23e..7b3a96d33a7 100644 --- a/go/mysql/fakesqldb/server.go +++ b/go/mysql/fakesqldb/server.go @@ -23,7 +23,6 @@ import ( "os" "path" "regexp" - "runtime/debug" "strings" "sync" "testing" @@ -196,6 +195,34 @@ func New(t testing.TB) *DB { return db } +// NewWithExpectedQueries returns DB with all the queries expected at the time of vttablet Initialization +func NewWithExpectedQueries(t testing.TB) *DB { + newDb := New(t) + newDb.AddQuery("CREATE DATABASE IF NOT EXISTS _vt", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("create database if not exists `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("SET GLOBAL super_read_only='OFF'", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("SET GLOBAL read_only='OFF'", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("SET @@session.sql_log_bin = 0", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("SET GLOBAL super_read_only='ON'", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE IF NOT EXISTS _vt.local_metadata.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("ALTER TABLE _vt.vreplication .*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("ALTER TABLE _vt.local_metadata.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE IF NOT EXISTS _vt.shard_metadata.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("ALTER TABLE _vt.shard_metadata.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("DROP TABLE IF EXISTS _vt.blp_checkpoint", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE IF NOT EXISTS _vt.vreplication.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("create table if not exists _vt.resharding_journal.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("create table if not exists _vt.copy_state.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE IF NOT EXISTS _vt.schema_migrations.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("SELECT.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("ALTER TABLE _vt.schema_migrations.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE IF NOT EXISTS _vt.reparent_journal.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("CREATE TABLE if not exists _vt.schemacopy.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQueryPattern("ALTER TABLE _vt.reparent_journal.*", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + newDb.AddQuery("USE `vt_test_keyspace`", &sqltypes.Result{InsertID: 0, RowsAffected: 0}) + return newDb +} + // Name returns the name of the DB. func (db *DB) Name() string { db.mu.Lock() @@ -415,8 +442,7 @@ func (db *DB) HandleQuery(c *mysql.Conn, query string, callback func(*sqltypes.R } // Nothing matched. err := fmt.Errorf("fakesqldb:: query: '%s' is not supported on %v", query, db.name) - log.Errorf("Query not found: %s:%s", query, debug.Stack()) - + //log.Errorf("Query not found: %s:%s", query, debug.Stack()) return err } @@ -770,3 +796,20 @@ func (db *DB) MockQueriesForTable(table string, result *sqltypes.Result) { cols..., )) } + +func (db *DB) AddVTSchemaInitQueries() { + queryPatterns := []string{ + "SHOW DATABASES LIKE '_vt'", + "select database.*", + "show tables from.*", + "use _vt", + "CREATE TABLE _vt.*", + "CREATE TABLE IF NOT EXISTS _vt.*", + "ALTER TABLE _vt.*", + "show create table _vt.*", + } + result := &sqltypes.Result{} + for _, q := range queryPatterns { + db.AddQueryPattern(q, result) + } +} diff --git a/go/mysql/query.go b/go/mysql/query.go index 0107e7606bc..69c21b2429a 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -328,6 +328,98 @@ func (c *Conn) ExecuteFetchMulti(query string, maxrows int, wantfields bool) (re return res, more, err } +// ExecuteFetchWithSuperReadOnlyHandling should be used if you are executing a write query +// on a tablet that may NOT be a primary and you want to execute it regardless of +// tablet type. This function will temporarily make the mysql instance read-write and +// re-enable read-only mode after the query is executed if needed. +func (c *Conn) ExecuteFetchWithSuperReadOnlyHandling(query string, maxrows int, wantfields bool) (result *sqltypes.Result, err error) { + // Note: MariaDB does not have super_read_only but support for it is EOL in v14.0+ + turnSuperReadOnly := false + if !c.IsMariaDB() { + if err := c.WriteComQuery("SELECT @@global.super_read_only"); err != nil { + return nil, err + } + res, _, _, err := c.ReadQueryResult(1, false) + if err == nil && len(res.Rows) == 1 { + sro := res.Rows[0][0].ToString() + if sro == "1" || sro == "ON" { + turnSuperReadOnly = true + if _, err = c.ExecuteFetch("SET GLOBAL super_read_only='OFF'", 1, false); err != nil { + return nil, err + } + } + } + } + + result, _, err = c.ExecuteFetchMulti(query, maxrows, wantfields) + if turnSuperReadOnly { + if _, err := c.ExecuteFetch("SET GLOBAL super_read_only='ON'", 1, false); err != nil { + return nil, err + } + } + return result, err +} + +// ExecuteUnSetSuperReadOnly tries to set super-read-only to false only if it is currently enable +func (c *Conn) ExecuteUnSetSuperReadOnly() (result *sqltypes.Result, err error) { + // Note: MariaDB does not have super_read_only but support for it is EOL in v14.0+ + if !c.IsMariaDB() { + if err := c.WriteComQuery("SELECT @@global.super_read_only"); err != nil { + return nil, err + } + res, _, _, err := c.ReadQueryResult(1, false) + if err == nil && len(res.Rows) == 1 { + sro := res.Rows[0][0].ToString() + if sro == "1" || sro == "ON" { + if err = c.WriteComQuery("SET GLOBAL super_read_only='OFF'"); err != nil { + return nil, err + } + } + } + } + + return result, err +} + +// ExecuteSetSuperReadOnly tries to set super-read-only to true only if it is currently disable +func (c *Conn) ExecuteSetSuperReadOnly() (result *sqltypes.Result, err error) { + // Note: MariaDB does not have super_read_only but support for it is EOL in v14.0+ + if !c.IsMariaDB() { + if err := c.WriteComQuery("SELECT @@global.super_read_only"); err != nil { + return nil, err + } + res, _, _, err := c.ReadQueryResult(1, false) + if err == nil && len(res.Rows) == 1 { + sro := res.Rows[0][0].ToString() + if sro == "0" || sro == "OFF" { + if err = c.WriteComQuery("SET GLOBAL super_read_only='ON'"); err != nil { + return nil, err + } + } + } + } + + return result, err +} + +// ExecuteUnSetReadOnly tries to set read-only to false only if it is currently enable +func (c *Conn) ExecuteUnSetReadOnly() (result *sqltypes.Result, err error) { + if err := c.WriteComQuery("SELECT @@global.read_only"); err != nil { + return nil, err + } + res, _, _, err := c.ReadQueryResult(1, false) + if err == nil && len(res.Rows) == 1 { + sro := res.Rows[0][0].ToString() + if sro == "1" || sro == "ON" { + if err = c.WriteComQuery("SET GLOBAL read_only='OFF'"); err != nil { + return nil, err + } + } + } + + return result, err +} + // ExecuteFetchWithWarningCount is for fetching results and a warning count // Note: In a future iteration this should be abolished and merged into the // ExecuteFetch API. diff --git a/go/test/endtoend/backup/pitr/backup_mysqlctld_pitr_test.go b/go/test/endtoend/backup/pitr/backup_mysqlctld_pitr_test.go index f93dfa475b6..dfb869b4de2 100644 --- a/go/test/endtoend/backup/pitr/backup_mysqlctld_pitr_test.go +++ b/go/test/endtoend/backup/pitr/backup_mysqlctld_pitr_test.go @@ -138,9 +138,9 @@ func TestIncrementalBackupMysqlctld(t *testing.T) { if tc.writeBeforeBackup { backup.InsertRowOnPrimary(t, "") } - // we wait for 1 second because backups ar ewritten to a directory named after the current timestamp, - // in 1 second resolution. We want to aoid two backups that have the same pathname. Realistically this - // is only ever a problem in this endtoend test, not in production. + // we wait for 1 second because backups are written to a directory named after the current timestamp, + // in 1 second resolution. We want to avoid two backups that have the same pathname. Realistically this + // is only ever a problem in this end-to-end test, not in production. // Also, we gie the replica a chance to catch up. time.Sleep(1100 * time.Millisecond) waitForReplica(t) diff --git a/go/test/endtoend/backup/vtbackup/backup_only_test.go b/go/test/endtoend/backup/vtbackup/backup_only_test.go index 39430733e1c..5ebc2f121b3 100644 --- a/go/test/endtoend/backup/vtbackup/backup_only_test.go +++ b/go/test/endtoend/backup/vtbackup/backup_only_test.go @@ -36,7 +36,7 @@ import ( var ( vtInsertTest = ` - create table vt_insert_test ( + create table if not exists vt_insert_test ( id bigint auto_increment, msg varchar(64), primary key (id) @@ -62,12 +62,21 @@ func TestTabletInitialBackup(t *testing.T) { // Initialize the tablets initTablets(t, false, false) + _, err := getVTExecVersion("vttablet") + require.NoError(t, err) + //if ver > 15 { + //_, err := primary.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + //require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") + //_, err = replica1.VttabletProcess.QueryTablet(vtInsertTest, keyspaceName, true) + //require.ErrorContains(t, err, "The MySQL server is running with the --super-read-only option so it cannot execute this statement") + //} + // Restore the Tablets - restore(t, primary, "replica", "NOT_SERVING") - err := localCluster.VtctlclientProcess.ExecuteCommand( + restore(t, primary, "replica", "NOT_SERVING", true) + err = localCluster.VtctlclientProcess.ExecuteCommand( "TabletExternallyReparented", primary.Alias) require.Nil(t, err) - restore(t, replica1, "replica", "SERVING") + restore(t, replica1, "replica", "SERVING", false) // Run the entire backup test firstBackupTest(t, "replica") @@ -137,7 +146,7 @@ func firstBackupTest(t *testing.T, tabletType string) { require.Nil(t, err) cluster.VerifyRowsInTablet(t, replica1, keyspaceName, 2) - // eventhough we change the value of compression it won't effect + // even though we change the value of compression it won't affect // decompression since it gets its value from MANIFEST file, created // as part of backup. mysqlctl.CompressionEngineName = "lz4" @@ -145,14 +154,14 @@ func firstBackupTest(t *testing.T, tabletType string) { // now bring up the other replica, letting it restore from backup. err = localCluster.VtctlclientProcess.InitTablet(replica2, cell, keyspaceName, hostname, shardName) require.Nil(t, err) - restore(t, replica2, "replica", "SERVING") + restore(t, replica2, "replica", "SERVING", false) // Replica2 takes time to serve. Sleeping for 5 sec. time.Sleep(5 * time.Second) //check the new replica has the data cluster.VerifyRowsInTablet(t, replica2, keyspaceName, 2) // check that the restored replica has the right local_metadata - result, err := replica2.VttabletProcess.QueryTabletWithDB("select * from local_metadata", "_vt") + /*result, err := replica2.VttabletProcess.QueryTabletWithDB("select * from local_metadata", "_vt") require.Nil(t, err) require.NotNil(t, result) require.NotEmpty(t, result.Rows) @@ -163,7 +172,7 @@ func firstBackupTest(t *testing.T, tabletType string) { assert.Equal(t, "neutral", result.Rows[3][1].ToString(), "PromotionRule") } else { assert.Equal(t, "must_not", result.Rows[3][1].ToString(), "PromotionRule") - } + }*/ removeBackups(t) verifyBackupCount(t, shardKsName, 0) @@ -183,15 +192,21 @@ func vtBackup(t *testing.T, initialBackup bool, restartBeforeBackup, disableRedo if restartBeforeBackup { extraArgs = append(extraArgs, "--restart_before_backup") } + ver, err := getVTExecVersion("vtbackup") + require.NoError(t, err) if disableRedoLog { - extraArgs = append(extraArgs, "--disable-redo-log") + if ver > 15 { + extraArgs = append(extraArgs, "--disable-redo-log") + } } ctx, cancel := context.WithCancel(context.Background()) defer cancel() if !initialBackup && disableRedoLog { - go verifyDisableEnableRedoLogs(ctx, t, mysqlSocket.Name()) + if ver > 15 { + go verifyDisableEnableRedoLogs(ctx, t, mysqlSocket.Name()) + } } log.Infof("starting backup tablet %s", time.Now()) @@ -243,6 +258,7 @@ func removeBackups(t *testing.T) { func initTablets(t *testing.T, startTablet bool, initShardPrimary bool) { // Initialize tablets + for _, tablet := range []cluster.Vttablet{*primary, *replica1} { err := localCluster.VtctlclientProcess.InitTablet(&tablet, cell, keyspaceName, hostname, shardName) require.Nil(t, err) @@ -260,17 +276,22 @@ func initTablets(t *testing.T, startTablet bool, initShardPrimary bool) { } } -func restore(t *testing.T, tablet *cluster.Vttablet, tabletType string, waitForState string) { +func restore(t *testing.T, tablet *cluster.Vttablet, tabletType string, waitForState string, disableReparentShard bool) { // Erase mysql/tablet dir, then start tablet with restore enabled. log.Infof("restoring tablet %s", time.Now()) resetTabletDirectory(t, *tablet, true) - err := tablet.VttabletProcess.CreateDB(keyspaceName) + err := tablet.VttabletProcess.CreateDBWithSuperReadOnly(keyspaceName) require.Nil(t, err) // Start tablets tablet.VttabletProcess.ExtraArgs = []string{"--db-credentials-file", dbCredentialFile} + /*if disableReparentShard { + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, fmt.Sprintf("--disable_active_reparents=%t", true)) + } else { + tablet.VttabletProcess.ExtraArgs = append(tablet.VttabletProcess.ExtraArgs, fmt.Sprintf("--use_super_read_only=%t", true)) + }*/ tablet.VttabletProcess.TabletType = tabletType tablet.VttabletProcess.ServingStatus = waitForState tablet.VttabletProcess.SupportsBackup = true @@ -310,7 +331,7 @@ func tearDown(t *testing.T, initMysql bool) { _, err = tablet.VttabletProcess.QueryTablet(disableSemiSyncCommands, keyspaceName, true) require.Nil(t, err) for _, db := range []string{"_vt", "vt_insert_test"} { - _, err = tablet.VttabletProcess.QueryTablet(fmt.Sprintf("drop database if exists %s", db), keyspaceName, true) + _, err = tablet.VttabletProcess.QueryTabletWithSuperReadOnlyHandling(fmt.Sprintf("drop database if exists %s", db), keyspaceName, true) require.Nil(t, err) } } @@ -375,3 +396,14 @@ func verifyDisableEnableRedoLogs(ctx context.Context, t *testing.T, mysqlSocket } } } + +// insert should not work for any of the replicas and primary +func getVTExecVersion(binaryName string) (int, error) { + vtTabletVersion := 0 + vtTabletVersion, err := cluster.GetMajorVersion(binaryName) + if err != nil { + return 0, err + } + log.Infof("cluster.VtTabletMajorVersion: %d", vtTabletVersion) + return vtTabletVersion, nil +} diff --git a/go/test/endtoend/backup/vtbackup/main_test.go b/go/test/endtoend/backup/vtbackup/main_test.go index ce0720e77c4..5fd0b6f602c 100644 --- a/go/test/endtoend/backup/vtbackup/main_test.go +++ b/go/test/endtoend/backup/vtbackup/main_test.go @@ -22,6 +22,7 @@ import ( "os" "os/exec" "path" + "strings" "testing" "vitess.io/vitess/go/test/endtoend/cluster" @@ -89,8 +90,12 @@ func TestMain(m *testing.M) { dbCredentialFile = cluster.WriteDbCredentialToTmp(localCluster.TmpDirectory) initDb, _ := os.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) sql := string(initDb) + // Since password update is DML we need to insert it before we disable + // super-read-only therefore doing the split below. + spilltedString := strings.Split(sql, "# add custom sql here") + firstPart := spilltedString[0] + cluster.GetPasswordUpdateSQL(localCluster) + sql = firstPart + spilltedString[1] newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") - sql = sql + cluster.GetPasswordUpdateSQL(localCluster) err = os.WriteFile(newInitDBFile, []byte(sql), 0666) if err != nil { return 1, err @@ -128,10 +133,17 @@ func TestMain(m *testing.M) { } } - // Create database - for _, tablet := range []cluster.Vttablet{*primary, *replica1} { - if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { - return 1, err + ver, err := getVTExecVersion("vttablet") + if err != nil { + return 1, err + } + + if ver <= 15 { + // Create database + for _, tablet := range []cluster.Vttablet{*primary, *replica1} { + if err := tablet.VttabletProcess.CreateDBWithSuperReadOnly(keyspaceName); err != nil { + return 1, err + } } } diff --git a/go/test/endtoend/backup/vtctlbackup/backup_utils.go b/go/test/endtoend/backup/vtctlbackup/backup_utils.go index 85b0c88450d..612884e62db 100644 --- a/go/test/endtoend/backup/vtctlbackup/backup_utils.go +++ b/go/test/endtoend/backup/vtctlbackup/backup_utils.go @@ -118,8 +118,12 @@ func LaunchCluster(setupType int, streamMode string, stripes int, cDetails *Comp dbCredentialFile = cluster.WriteDbCredentialToTmp(localCluster.TmpDirectory) initDb, _ := os.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) sql := string(initDb) + // Since password update is DML we need to insert it before we disable + // super-read-only therefore doing the split below. + splitString := strings.Split(sql, "# add custom sql here") + firstPart := splitString[0] + cluster.GetPasswordUpdateSQL(localCluster) + sql = firstPart + splitString[1] newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") - sql = sql + cluster.GetPasswordUpdateSQL(localCluster) err = os.WriteFile(newInitDBFile, []byte(sql), 0666) if err != nil { return 1, err @@ -207,9 +211,9 @@ func LaunchCluster(setupType int, streamMode string, stripes int, cDetails *Comp } for _, tablet := range []cluster.Vttablet{*primary, *replica1} { - if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { + /*if err := tablet.VttabletProcess.CreateDB(keyspaceName); err != nil { return 1, err - } + }*/ if err := tablet.VttabletProcess.Setup(); err != nil { return 1, err } @@ -676,8 +680,8 @@ func restartPrimaryAndReplica(t *testing.T) { for _, tablet := range []*cluster.Vttablet{primary, replica1} { err := localCluster.VtctlclientProcess.InitTablet(tablet, cell, keyspaceName, hostname, shardName) require.Nil(t, err) - err = tablet.VttabletProcess.CreateDB(keyspaceName) - require.Nil(t, err) + //err = tablet.VttabletProcess.CreateDB(keyspaceName) + //require.Nil(t, err) err = tablet.VttabletProcess.Setup() require.Nil(t, err) } diff --git a/go/test/endtoend/cluster/cluster_process.go b/go/test/endtoend/cluster/cluster_process.go index 9cfdeee4814..d8017d1e8fd 100644 --- a/go/test/endtoend/cluster/cluster_process.go +++ b/go/test/endtoend/cluster/cluster_process.go @@ -684,7 +684,11 @@ func NewCluster(cell string, hostname string) *LocalProcessCluster { // path/to/whatever exists cluster.ReusingVTDATAROOT = true } else { - _ = createDirectory(cluster.CurrentVTDATAROOT, 0700) + err = createDirectory(cluster.CurrentVTDATAROOT, 0700) + if err != nil { + fmt.Printf("err in creating file : %s", err.Error()) + log.Infof("err in creating file : %s", err.Error()) + } } _ = os.Setenv("VTDATAROOT", cluster.CurrentVTDATAROOT) log.Infof("Created cluster on %s. ReusingVTDATAROOT=%v", cluster.CurrentVTDATAROOT, cluster.ReusingVTDATAROOT) diff --git a/go/test/endtoend/cluster/cluster_util.go b/go/test/endtoend/cluster/cluster_util.go index 1134e51d40d..9527b9000a1 100644 --- a/go/test/endtoend/cluster/cluster_util.go +++ b/go/test/endtoend/cluster/cluster_util.go @@ -123,16 +123,18 @@ func PanicHandler(t *testing.T) { // VerifyLocalMetadata Verify Local Metadata of a tablet func VerifyLocalMetadata(t *testing.T, tablet *Vttablet, ksName string, shardName string, cell string) { - qr, err := tablet.VttabletProcess.QueryTablet("select * from _vt.local_metadata", ksName, false) - require.Nil(t, err) - assert.Equal(t, fmt.Sprintf("%v", qr.Rows[0][1]), fmt.Sprintf(`BLOB("%s")`, tablet.Alias)) - assert.Equal(t, fmt.Sprintf("%v", qr.Rows[1][1]), fmt.Sprintf(`BLOB("%s.%s")`, ksName, shardName)) - assert.Equal(t, fmt.Sprintf("%v", qr.Rows[2][1]), fmt.Sprintf(`BLOB("%s")`, cell)) - if tablet.Type == "replica" { - assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("neutral")`) - } else if tablet.Type == "rdonly" { - assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("must_not")`) - } + // local metadata has been deleted in this PR // FIXME: remove this function and references + + //qr, err := tablet.VttabletProcess.QueryTablet("select * from _vt.local_metadata", ksName, false) + //require.Nil(t, err) + //assert.Equal(t, fmt.Sprintf("%v", qr.Rows[0][1]), fmt.Sprintf(`BLOB("%s")`, tablet.Alias)) + //assert.Equal(t, fmt.Sprintf("%v", qr.Rows[1][1]), fmt.Sprintf(`BLOB("%s.%s")`, ksName, shardName)) + //assert.Equal(t, fmt.Sprintf("%v", qr.Rows[2][1]), fmt.Sprintf(`BLOB("%s")`, cell)) + //if tablet.Type == "replica" { + // assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("neutral")`) + //} else if tablet.Type == "rdonly" { + // assert.Equal(t, fmt.Sprintf("%v", qr.Rows[3][1]), `BLOB("must_not")`) + //} } // ListBackups Lists back preset in shard diff --git a/go/test/endtoend/cluster/mysqlctld_process.go b/go/test/endtoend/cluster/mysqlctld_process.go index 9876dd38797..d71f2e3b1c8 100644 --- a/go/test/endtoend/cluster/mysqlctld_process.go +++ b/go/test/endtoend/cluster/mysqlctld_process.go @@ -85,7 +85,7 @@ func (mysqlctld *MysqlctldProcess) Start() error { tempProcess.Stdout = os.Stdout tempProcess.Stderr = os.Stderr - log.Infof("%v %v", strings.Join(tempProcess.Args, " ")) + log.Infof("%v", strings.Join(tempProcess.Args, " ")) err := tempProcess.Start() if err != nil { diff --git a/go/test/endtoend/cluster/vtbackup_process.go b/go/test/endtoend/cluster/vtbackup_process.go index b7beed67936..be75026bf0d 100644 --- a/go/test/endtoend/cluster/vtbackup_process.go +++ b/go/test/endtoend/cluster/vtbackup_process.go @@ -54,7 +54,6 @@ type VtbackupProcess struct { // Setup starts vtbackup process with required arguements func (vtbackup *VtbackupProcess) Setup() (err error) { - vtbackup.proc = exec.Command( vtbackup.Binary, "--topo_implementation", vtbackup.CommonArg.TopoImplementation, diff --git a/go/test/endtoend/cluster/vtctld_process.go b/go/test/endtoend/cluster/vtctld_process.go index 3656b7b3ecf..52f0a3654ef 100644 --- a/go/test/endtoend/cluster/vtctld_process.go +++ b/go/test/endtoend/cluster/vtctld_process.go @@ -107,6 +107,8 @@ func (vtctld *VtctldProcess) Setup(cell string, extraArgs ...string) (err error) } func createDirectory(dirName string, mode os.FileMode) error { + log.Infof("creating directory : %s", dirName) + fmt.Printf("creating directory : %s", dirName) if _, err := os.Stat(dirName); os.IsNotExist(err) { return os.Mkdir(dirName, mode) } diff --git a/go/test/endtoend/cluster/vttablet_process.go b/go/test/endtoend/cluster/vttablet_process.go index a5eba51f22d..0a7c624e111 100644 --- a/go/test/endtoend/cluster/vttablet_process.go +++ b/go/test/endtoend/cluster/vttablet_process.go @@ -414,6 +414,13 @@ func (vttablet *VttabletProcess) CreateDB(keyspace string) error { return err } +// CreateDBWithSuperReadOnly creates the database for keyspace +func (vttablet *VttabletProcess) CreateDBWithSuperReadOnly(keyspace string) error { + _, _ = vttablet.QueryTabletWithSuperReadOnlyHandling(fmt.Sprintf("drop database IF EXISTS vt_%s", keyspace), keyspace, false) + _, err := vttablet.QueryTabletWithSuperReadOnlyHandling(fmt.Sprintf("create database IF NOT EXISTS vt_%s", keyspace), keyspace, false) + return err +} + // QueryTablet lets you execute a query in this tablet and get the result func (vttablet *VttabletProcess) QueryTablet(query string, keyspace string, useDb bool) (*sqltypes.Result, error) { if !useDb { @@ -633,3 +640,69 @@ func VttabletProcessInstance(port, grpcPort, tabletUID int, cell, shard, keyspac return vttablet } + +// UnsetSuperReadOnly switch-off super-read-only flag in db +func (vttablet *VttabletProcess) UnsetSuperReadOnly(dbname string) error { + conn, err := vttablet.defaultConn("") + if err != nil { + log.Infof("error in getting connection object %s", err) + return err + } + defer conn.Close() + + _, err = conn.ExecuteUnSetSuperReadOnly() + return err +} + +// UnsetReadOnly switch-off read-only flag in db +func (vttablet *VttabletProcess) UnsetReadOnly(dbname string) error { + conn, err := vttablet.defaultConn("") + if err != nil { + log.Infof("error in getting connection object %s", err) + return err + } + defer conn.Close() + + _, err = conn.ExecuteUnSetReadOnly() + return err +} + +// QueryTabletWithSuperReadOnlyHandling lets you execute a query in this tablet while disabling super-read-only and get the result +// It will enable super-read-only once its done executing the query. +func (vttablet *VttabletProcess) QueryTabletWithSuperReadOnlyHandling(query string, keyspace string, useDb bool) (*sqltypes.Result, error) { + if !useDb { + keyspace = "" + } + dbParams := NewConnParams(vttablet.DbPort, vttablet.DbPassword, path.Join(vttablet.Directory, "mysql.sock"), keyspace) + conn, err := vttablet.conn(&dbParams) + if err != nil { + return nil, err + } + defer conn.Close() + return executeQueryWithSuperReadOnlyHandling(conn, query) +} + +// executeQuery will retry the query up to 10 times with a small sleep in between each try. +// This allows the tests to be more robust in the face of transient failures. It disables +// super-read-only during query execution. +func executeQueryWithSuperReadOnlyHandling(dbConn *mysql.Conn, query string) (*sqltypes.Result, error) { + var ( + err error + result *sqltypes.Result + ) + retries := 10 + retryDelay := 1 * time.Second + for i := 0; i < retries; i++ { + if i > 0 { + // We only audit from 2nd attempt and onwards, otherwise this is just too verbose. + log.Infof("Executing query %s (attempt %d of %d)", query, (i + 1), retries) + } + result, err = dbConn.ExecuteFetchWithSuperReadOnlyHandling(query, 10000, true) + if err == nil { + break + } + time.Sleep(retryDelay) + } + + return result, err +} diff --git a/go/test/endtoend/recovery/pitr/shardedpitr_test.go b/go/test/endtoend/recovery/pitr/shardedpitr_test.go index 9920e03961a..630339106b5 100644 --- a/go/test/endtoend/recovery/pitr/shardedpitr_test.go +++ b/go/test/endtoend/recovery/pitr/shardedpitr_test.go @@ -442,14 +442,15 @@ func initializeCluster(t *testing.T) { fmt.Sprintf("CREATE USER '%s'@'%%' IDENTIFIED BY '%s';", mysqlUserName, mysqlPassword), fmt.Sprintf("GRANT ALL ON *.* TO '%s'@'%%';", mysqlUserName), fmt.Sprintf("GRANT GRANT OPTION ON *.* TO '%s'@'%%';", mysqlUserName), - fmt.Sprintf("create database %s;", "vt_ks"), + //fmt.Sprintf("create database %s;", "vt_ks"), "FLUSH PRIVILEGES;", } for _, shard := range clusterInstance.Keyspaces[0].Shards { for _, tablet := range shard.Vttablets { + for _, query := range queryCmds { - _, err = tablet.VttabletProcess.QueryTablet(query, keyspace.Name, false) + _, err = tablet.VttabletProcess.QueryTabletWithSuperReadOnlyHandling(query, keyspace.Name, false) require.NoError(t, err) } diff --git a/go/test/endtoend/recovery/unshardedrecovery/recovery.go b/go/test/endtoend/recovery/unshardedrecovery/recovery.go index 68c66a7bbc0..0e675a97ca9 100644 --- a/go/test/endtoend/recovery/unshardedrecovery/recovery.go +++ b/go/test/endtoend/recovery/unshardedrecovery/recovery.go @@ -23,6 +23,7 @@ import ( "os" "os/exec" "path" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -94,13 +95,16 @@ func TestMainImpl(m *testing.M) { dbCredentialFile = cluster.WriteDbCredentialToTmp(localCluster.TmpDirectory) initDb, _ := os.ReadFile(path.Join(os.Getenv("VTROOT"), "/config/init_db.sql")) sql := string(initDb) - newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") - sql = sql + cluster.GetPasswordUpdateSQL(localCluster) + // Since password update is DML we need to insert it before we disable + // super-read-only therefore doing the split below. + splitString := strings.Split(sql, "# add custom sql here") + firstPart := splitString[0] + cluster.GetPasswordUpdateSQL(localCluster) + // https://github.com/vitessio/vitess/issues/8315 - oldAlterTableMode := ` -SET GLOBAL old_alter_table = ON; -` - sql = sql + oldAlterTableMode + oldAlterTableMode := `SET GLOBAL old_alter_table = ON;` + sql = firstPart + oldAlterTableMode + sql = sql + splitString[1] + newInitDBFile = path.Join(localCluster.TmpDirectory, "init_db_with_passwords.sql") os.WriteFile(newInitDBFile, []byte(sql), 0666) extraArgs := []string{"--db-credentials-file", dbCredentialFile} diff --git a/go/test/endtoend/reparent/emergencyreparent/ers_test.go b/go/test/endtoend/reparent/emergencyreparent/ers_test.go index 3564ba3badb..5c016967629 100644 --- a/go/test/endtoend/reparent/emergencyreparent/ers_test.go +++ b/go/test/endtoend/reparent/emergencyreparent/ers_test.go @@ -388,7 +388,7 @@ func TestERSForInitialization(t *testing.T) { clusterInstance.VtTabletExtraArgs = []string{ "--lock_tables_timeout", "5s", "--enable_semi_sync", - "--init_populate_metadata", + //"--init_populate_metadata", "--track_schema_versions=true", } diff --git a/go/test/endtoend/reparent/plannedreparent/reparent_test.go b/go/test/endtoend/reparent/plannedreparent/reparent_test.go index 72f560a9bc0..ff6a91e7bdd 100644 --- a/go/test/endtoend/reparent/plannedreparent/reparent_test.go +++ b/go/test/endtoend/reparent/plannedreparent/reparent_test.go @@ -377,9 +377,15 @@ func TestReparentDoesntHangIfPrimaryFails(t *testing.T) { // Perform a planned reparent operation, the primary will fail the // insert. The replicas should then abort right away. + ver, err := getVTExecVersion("vttablet") + require.NoError(t, err) out, err := utils.Prs(t, clusterInstance, tablets[1]) - require.Error(t, err) - assert.Contains(t, out, "primary failed to PopulateReparentJournal") + if ver <= 15 { + require.Error(t, err) + assert.Contains(t, out, "primary failed to PopulateReparentJournal") + } else { + require.NoError(t, err, "PRS should not fail.") + } } // TestCrossCellDurability tests 2 things - @@ -520,3 +526,14 @@ func rowNumberFromPosition(pos string) int { rowNum, _ := strconv.Atoi(rowNumStr) return rowNum } + +// insert should not work for any of the replicas and primary +func getVTExecVersion(binaryName string) (int, error) { + vtTabletVersion := 0 + vtTabletVersion, err := cluster.GetMajorVersion(binaryName) + if err != nil { + return 0, err + } + log.Infof("cluster.VtTabletMajorVersion: %d", vtTabletVersion) + return vtTabletVersion, nil +} diff --git a/go/test/endtoend/reparent/utils/utils.go b/go/test/endtoend/reparent/utils/utils.go index 744a3c44c2b..aa259b7700c 100644 --- a/go/test/endtoend/reparent/utils/utils.go +++ b/go/test/endtoend/reparent/utils/utils.go @@ -115,7 +115,7 @@ func setupCluster(ctx context.Context, t *testing.T, shardName string, cells []s clusterInstance.VtTabletExtraArgs = append(clusterInstance.VtTabletExtraArgs, "--lock_tables_timeout", "5s", - "--init_populate_metadata", + // "--init_populate_metadata", "--track_schema_versions=true", // disabling online-ddl for reparent tests. This is done to reduce flakiness. // All the tests in this package reparent frequently between different tablets @@ -214,7 +214,7 @@ func StartNewVTTablet(t *testing.T, clusterInstance *cluster.LocalProcessCluster clusterInstance.TmpDirectory, []string{ "--lock_tables_timeout", "5s", - "--init_populate_metadata", + //"--init_populate_metadata", "--track_schema_versions=true", "--queryserver_enable_online_ddl=false", }, diff --git a/go/test/endtoend/tabletmanager/tablet_health_test.go b/go/test/endtoend/tabletmanager/tablet_health_test.go index 19359406607..1b3f64299ef 100644 --- a/go/test/endtoend/tabletmanager/tablet_health_test.go +++ b/go/test/endtoend/tabletmanager/tablet_health_test.go @@ -104,7 +104,7 @@ func TestHealthCheck(t *testing.T) { defer replicaConn.Close() // Create database in mysql - utils.Exec(t, replicaConn, fmt.Sprintf("create database vt_%s", keyspaceName)) + //utils.Exec(t, replicaConn, fmt.Sprintf("create database vt_%s", keyspaceName)) // start vttablet process, should be in SERVING state as we already have a primary err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) diff --git a/go/test/endtoend/tabletmanager/tablet_test.go b/go/test/endtoend/tabletmanager/tablet_test.go index 0296f397f5a..cd0cbcae485 100644 --- a/go/test/endtoend/tabletmanager/tablet_test.go +++ b/go/test/endtoend/tabletmanager/tablet_test.go @@ -45,33 +45,37 @@ func TestEnsureDB(t *testing.T) { // Make it the primary. err = clusterInstance.VtctlclientProcess.ExecuteCommand("TabletExternallyReparented", tablet.Alias) - require.EqualError(t, err, "exit status 1") + require.NoError(t, err, "No error expected.") // It is still NOT_SERVING because the db is read-only. - assert.Equal(t, "NOT_SERVING", tablet.VttabletProcess.GetTabletStatus()) + assert.Equal(t, "SERVING", tablet.VttabletProcess.GetTabletStatus()) status := tablet.VttabletProcess.GetStatusDetails() - assert.Contains(t, status, "read-only") + assert.Contains(t, status, "healthy") + // With new changes we expect vttablet to be healthy and non-read-only mode the moment 'TabletExternallyReparented' happen. @rohit-nayak-ps // Switch to read-write and verify that that we go serving. - _ = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", tablet.Alias) - err = tablet.VttabletProcess.WaitForTabletStatus("SERVING") - require.NoError(t, err) + //err = clusterInstance.VtctlclientProcess.ExecuteCommand("SetReadWrite", tablet.Alias) + //require.NoError(t, err, "Not suppose to fail.") + //err = tablet.VttabletProcess.WaitForTabletStatus("SERVING") + //require.NoError(t, err) killTablets(t, tablet) } // TestLocalMetadata tests the contents of local_metadata table after vttablet startup func TestLocalMetadata(t *testing.T) { + t.Skip("Local Metadata has been removed") defer cluster.PanicHandler(t) + // This will no longer hold true since localMetadata is removed as part of this change @rohit-nayak-ps // by default tablets are started with --restore_from_backup // so metadata should exist - cluster.VerifyLocalMetadata(t, &replicaTablet, keyspaceName, shardName, cell) + //cluster.VerifyLocalMetadata(t, &replicaTablet, keyspaceName, shardName, cell) // Create new tablet rTablet := clusterInstance.NewVttabletInstance("replica", 0, "") clusterInstance.VtTabletExtraArgs = []string{ "--lock_tables_timeout", "5s", - "--init_populate_metadata", + //"--init_populate_metadata", } rTablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(rTablet.TabletUID, rTablet.MySQLPort, clusterInstance.TmpDirectory) err := rTablet.MysqlctlProcess.Start() @@ -84,7 +88,7 @@ func TestLocalMetadata(t *testing.T) { err = clusterInstance.StartVttablet(rTablet, "SERVING", false, cell, keyspaceName, hostname, shardName) require.NoError(t, err) - cluster.VerifyLocalMetadata(t, rTablet, keyspaceName, shardName, cell) + //cluster.VerifyLocalMetadata(t, rTablet, keyspaceName, shardName, cell) // Create another new tablet rTablet2 := clusterInstance.NewVttabletInstance("replica", 0, "") @@ -103,11 +107,12 @@ func TestLocalMetadata(t *testing.T) { err = clusterInstance.StartVttablet(rTablet2, "SERVING", false, cell, keyspaceName, hostname, shardName) require.NoError(t, err) - // check that tablet did _not_ get populated - qr, err := rTablet2.VttabletProcess.QueryTablet("select * from _vt.local_metadata", keyspaceName, false) - require.NoError(t, err) - require.Nil(t, qr.Rows) - + if false { // FIXME local_metedata has been deleted + // check that tablet did _not_ get populated + qr, err := rTablet2.VttabletProcess.QueryTablet("select * from _vt.local_metadata", keyspaceName, false) + require.NoError(t, err) + require.Nil(t, qr.Rows) + } // Reset the VtTabletExtraArgs and kill tablets clusterInstance.VtTabletExtraArgs = []string{} killTablets(t, rTablet, rTablet2) diff --git a/go/test/endtoend/utils/mysql.go b/go/test/endtoend/utils/mysql.go index 5bbf75ffb71..e81ae9d9045 100644 --- a/go/test/endtoend/utils/mysql.go +++ b/go/test/endtoend/utils/mysql.go @@ -114,11 +114,12 @@ func createInitSQLFile(mysqlDir, ksName string) (string, error) { return "", err } defer f.Close() - + _, _ = f.WriteString("SET GLOBAL super_read_only='OFF';") _, err = f.WriteString(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s;", ksName)) if err != nil { return "", err } + //_, _ = f.WriteString("SET GLOBAL super_read_only='ON';") return initSQLFile, nil } diff --git a/go/test/endtoend/vault/vault_test.go b/go/test/endtoend/vault/vault_test.go index da66f3a52e3..5ffd356a0f6 100644 --- a/go/test/endtoend/vault/vault_test.go +++ b/go/test/endtoend/vault/vault_test.go @@ -267,6 +267,12 @@ func initializeClusterLate(t *testing.T) { require.NoError(t, err) } + for _, tablet := range shard.Vttablets { + // remove super read-only from vttablet + tablet.VttabletProcess.UnsetReadOnly("") + } + + // TODO: Try moving this after InitPrimary. May be thats a better place. for _, tablet := range []*cluster.Vttablet{primary, replica} { for _, user := range mysqlUsers { query := fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s';", user, hostname, mysqlPassword) @@ -279,9 +285,9 @@ func initializeClusterLate(t *testing.T) { require.NoError(t, err) } } - query := fmt.Sprintf("create database %s;", dbName) + /*query := fmt.Sprintf("create database %s;", dbName) _, err = tablet.VttabletProcess.QueryTablet(query, keyspace.Name, false) - require.NoError(t, err) + require.NoError(t, err)*/ err = tablet.VttabletProcess.Setup() require.NoError(t, err) diff --git a/go/test/endtoend/vtgate/schematracker/loadkeyspace/schema_load_keyspace_test.go b/go/test/endtoend/vtgate/schematracker/loadkeyspace/schema_load_keyspace_test.go index a603bc1c89b..85f6f6a7855 100644 --- a/go/test/endtoend/vtgate/schematracker/loadkeyspace/schema_load_keyspace_test.go +++ b/go/test/endtoend/vtgate/schematracker/loadkeyspace/schema_load_keyspace_test.go @@ -54,6 +54,8 @@ var ( ) func TestBlockedLoadKeyspace(t *testing.T) { + t.Skip("this test is not valid anymore since schemacopy is being created by default and inspite of the tablet signal being setup to false") + defer cluster.PanicHandler(t) var err error diff --git a/go/test/endtoend/vtorc/readtopologyinstance/main_test.go b/go/test/endtoend/vtorc/readtopologyinstance/main_test.go index c6426021d6c..826a420fad5 100644 --- a/go/test/endtoend/vtorc/readtopologyinstance/main_test.go +++ b/go/test/endtoend/vtorc/readtopologyinstance/main_test.go @@ -106,7 +106,7 @@ func TestReadTopologyInstanceBufferable(t *testing.T) { assert.Equal(t, fmt.Sprintf("%v:%v", keyspace.Name, shard0.Name), primaryInstance.ClusterName) // insert an errant GTID in the replica - _, err = utils.RunSQL(t, "insert into vt_insert_test(id, msg) values (10173, 'test 178342')", replica, "vt_ks") + _, err = utils.RunSQLWithSuperReadOnly(t, "insert into vt_insert_test(id, msg) values (10173, 'test 178342')", replica, "vt_ks", true) require.NoError(t, err) replicaInstance, err := inst.ReadTopologyInstanceBufferable(&inst.InstanceKey{ diff --git a/go/test/endtoend/vtorc/utils/utils.go b/go/test/endtoend/vtorc/utils/utils.go index d4f23c0de70..9bb75cb723b 100644 --- a/go/test/endtoend/vtorc/utils/utils.go +++ b/go/test/endtoend/vtorc/utils/utils.go @@ -582,11 +582,29 @@ func RunSQL(t *testing.T, sql string, tablet *cluster.Vttablet, db string) (*sql defer conn.Close() // RunSQL - return execute(t, conn, sql) + return RunSQLWithSuperReadOnly(t, sql, tablet, db, false) } -func execute(t *testing.T, conn *mysql.Conn, query string) (*sqltypes.Result, error) { +// RunSQLWithSuperReadOnly is used to run a SQL statement on the given tablet with super read only set to true or false +func RunSQLWithSuperReadOnly(t *testing.T, sql string, tablet *cluster.Vttablet, db string, withSuperReadOnly bool) (*sqltypes.Result, error) { + // Get Connection + tabletParams := getMysqlConnParam(tablet, db) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + conn, err := mysql.Connect(ctx, &tabletParams) + require.Nil(t, err) + defer conn.Close() + + // RunSQL + return execute(t, conn, sql, withSuperReadOnly) +} + +func execute(t *testing.T, conn *mysql.Conn, query string, withSuperReadOnly bool) (*sqltypes.Result, error) { t.Helper() + if withSuperReadOnly { + return conn.ExecuteFetchWithSuperReadOnlyHandling(query, 1000, true) + } + return conn.ExecuteFetch(query, 1000, true) } diff --git a/go/vt/dbconfigs/dbconfigs.go b/go/vt/dbconfigs/dbconfigs.go index 5ab5e7a9356..7ec49b28598 100644 --- a/go/vt/dbconfigs/dbconfigs.go +++ b/go/vt/dbconfigs/dbconfigs.go @@ -216,12 +216,12 @@ func (dbcfgs *DBConfigs) AppDebugWithDB() Connector { return dbcfgs.makeParams(&dbcfgs.appdebugParams, true) } -// AllPrivsConnector returns connection parameters for appdebug with no dbname set. +// AllPrivsConnector returns connection parameters for all privileges with no dbname set. func (dbcfgs *DBConfigs) AllPrivsConnector() Connector { return dbcfgs.makeParams(&dbcfgs.allprivsParams, false) } -// AllPrivsWithDB returns connection parameters for appdebug with dbname set. +// AllPrivsWithDB returns connection parameters for all privileges with dbname set. func (dbcfgs *DBConfigs) AllPrivsWithDB() Connector { return dbcfgs.makeParams(&dbcfgs.allprivsParams, true) } diff --git a/go/vt/mysqlctl/backup.go b/go/vt/mysqlctl/backup.go index f0bfa34d764..f565ea1cc11 100644 --- a/go/vt/mysqlctl/backup.go +++ b/go/vt/mysqlctl/backup.go @@ -301,8 +301,6 @@ func Restore(ctx context.Context, params RestoreParams) (*BackupManifest, error) return nil, vterrors.Wrap(err, "ListBackups failed") } - metadataManager := &MetadataManager{} - if len(bhs) == 0 { // There are no backups (not even broken/incomplete ones). params.Logger.Errorf("no backup to restore on BackupStorage for directory %v. Starting up empty.", backupDir) @@ -316,10 +314,6 @@ func Restore(ctx context.Context, params RestoreParams) (*BackupManifest, error) params.Logger.Errorf("error resetting replication: %v. Continuing", err) } - if err := metadataManager.PopulateMetadataTables(params.Mysqld, params.LocalMetadata, params.DbName); err != nil { - params.Logger.Errorf("error populating metadata tables: %v. Continuing", err) - - } // Always return ErrNoBackup return nil, ErrNoBackup } @@ -380,18 +374,6 @@ func Restore(ctx context.Context, params RestoreParams) (*BackupManifest, error) return nil, vterrors.Wrap(err, "mysql_upgrade failed") } - // Add backupTime and restorePosition to LocalMetadata - params.LocalMetadata["RestoredBackupTime"] = manifest.BackupTime - params.LocalMetadata["RestorePosition"] = mysql.EncodePosition(manifest.Position) - - // Populate local_metadata before starting without --skip-networking, - // so it's there before we start announcing ourselves. - params.Logger.Infof("Restore: populating local_metadata") - err = metadataManager.PopulateMetadataTables(params.Mysqld, params.LocalMetadata, params.DbName) - if err != nil { - return nil, err - } - // The MySQL manual recommends restarting mysqld after running mysql_upgrade, // so that any changes made to system tables take effect. params.Logger.Infof("Restore: restarting mysqld after mysql_upgrade") diff --git a/go/vt/mysqlctl/backupengine.go b/go/vt/mysqlctl/backupengine.go index ca2d0f3b270..148073290d0 100644 --- a/go/vt/mysqlctl/backupengine.go +++ b/go/vt/mysqlctl/backupengine.go @@ -82,8 +82,6 @@ type RestoreParams struct { Concurrency int // Extra env variables for pre-restore and post-restore transform hooks HookExtraEnv map[string]string - // Metadata to write into database after restore. See PopulateMetadataTables - LocalMetadata map[string]string // DeleteBeforeRestore tells us whether existing data should be deleted before // restoring. This is always set to false when starting a tablet with -restore_from_backup, // but is set to true when executing a RestoreFromBackup command on an already running vttablet diff --git a/go/vt/mysqlctl/builtinbackupengine.go b/go/vt/mysqlctl/builtinbackupengine.go index 0bf09a17bf1..82055725c8f 100644 --- a/go/vt/mysqlctl/builtinbackupengine.go +++ b/go/vt/mysqlctl/builtinbackupengine.go @@ -776,7 +776,6 @@ func (be *BuiltinBackupEngine) executeRestoreFullBackup(ctx context.Context, par // The underlying mysql database is expected to be up and running. func (be *BuiltinBackupEngine) executeRestoreIncrementalBackup(ctx context.Context, params RestoreParams, bh backupstorage.BackupHandle, bm builtinBackupManifest) error { params.Logger.Infof("Restoring incremental backup to position: %v", bm.Position) - createdDir, err := be.restoreFiles(context.Background(), params, bh, bm) defer os.RemoveAll(createdDir) mysqld, ok := params.Mysqld.(*Mysqld) diff --git a/go/vt/mysqlctl/metadata_tables.go b/go/vt/mysqlctl/metadata_tables.go deleted file mode 100644 index 5ed7bb9cfe1..00000000000 --- a/go/vt/mysqlctl/metadata_tables.go +++ /dev/null @@ -1,234 +0,0 @@ -/* -Copyright 2019 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package mysqlctl - -import ( - "bytes" - "fmt" - - "context" - - "vitess.io/vitess/go/mysql" - "vitess.io/vitess/go/sqltypes" - "vitess.io/vitess/go/vt/dbconnpool" - "vitess.io/vitess/go/vt/log" -) - -// Note that definitions of local_metadata and shard_metadata should be the same -// as in testing which is defined in config/init_db.sql. -const ( - sqlCreateLocalMetadataTable = `CREATE TABLE IF NOT EXISTS _vt.local_metadata ( - name VARCHAR(255) NOT NULL, - value MEDIUMBLOB NOT NULL, - PRIMARY KEY (name) - ) ENGINE=InnoDB` - sqlCreateShardMetadataTable = `CREATE TABLE IF NOT EXISTS _vt.shard_metadata ( - name VARCHAR(255) NOT NULL, - value MEDIUMBLOB NOT NULL, - PRIMARY KEY (name) - ) ENGINE=InnoDB` - sqlUpdateLocalMetadataTable = "UPDATE _vt.local_metadata SET db_name='%s' WHERE db_name=''" - sqlUpdateShardMetadataTable = "UPDATE _vt.shard_metadata SET db_name='%s' WHERE db_name=''" -) - -var ( - sqlAlterLocalMetadataTable = []string{ - `ALTER TABLE _vt.local_metadata ADD COLUMN db_name VARBINARY(255) NOT NULL DEFAULT ''`, - `ALTER TABLE _vt.local_metadata DROP PRIMARY KEY, ADD PRIMARY KEY(name, db_name)`, - // VARCHAR(255) is not long enough to hold replication positions, hence changing to - // MEDIUMBLOB. - `ALTER TABLE _vt.local_metadata CHANGE value value MEDIUMBLOB NOT NULL`, - } - sqlAlterShardMetadataTable = []string{ - `ALTER TABLE _vt.shard_metadata ADD COLUMN db_name VARBINARY(255) NOT NULL DEFAULT ''`, - `ALTER TABLE _vt.shard_metadata DROP PRIMARY KEY, ADD PRIMARY KEY(name, db_name)`, - } -) - -// MetadataManager manages the creation and filling of the _vt.local_metadata -// and _vt.shard_metadata tables. -type MetadataManager struct{} - -// PopulateMetadataTables creates and fills the _vt.local_metadata table and -// creates the _vt.shard_metadata table. -// -// _vt.local_metadata table is a per-tablet table that is never replicated. -// This allows queries against local_metadata to return different values on -// different tablets, which is used for communicating between Vitess and -// MySQL-level tools like Orchestrator (https://github.com/openark/orchestrator). -// -// _vt.shard_metadata is a replicated table with per-shard information, but it's -// created here to make it easier to create it on databases that were running -// old version of Vitess, or databases that are getting converted to run under -// Vitess. -// -// This function is semantically equivalent to calling createMetadataTables -// followed immediately by upsertLocalMetadata. -func (m *MetadataManager) PopulateMetadataTables(mysqld MysqlDaemon, localMetadata map[string]string, dbName string) error { - log.Infof("Populating _vt.local_metadata table...") - - // Get a non-pooled DBA connection. - conn, err := mysqld.GetDbaConnection(context.TODO()) - if err != nil { - return err - } - defer conn.Close() - - // Disable replication on this session. We close the connection after using - // it, so there's no need to re-enable replication when we're done. - if _, err := conn.ExecuteFetch("SET @@session.sql_log_bin = 0", 0, false); err != nil { - return err - } - - // Create the database and table if necessary. - if err := createMetadataTables(conn, dbName); err != nil { - return err - } - - // Populate local_metadata from the passed list of values. - return upsertLocalMetadata(conn, localMetadata, dbName) -} - -// UpsertLocalMetadata adds the given metadata map to the _vt.local_metadata -// table, updating any rows that exist for a given `_vt.local_metadata.name` -// with the map value. The session that performs these upserts sets -// sql_log_bin=0, as the _vt.local_metadata table is meant to never be -// replicated. -// -// Callers are responsible for ensuring the _vt.local_metadata table exists -// before calling this function, usually by calling CreateMetadataTables at -// least once prior. -func (m *MetadataManager) UpsertLocalMetadata(mysqld MysqlDaemon, localMetadata map[string]string, dbName string) error { - log.Infof("Upserting _vt.local_metadata ...") - - conn, err := mysqld.GetDbaConnection(context.TODO()) - if err != nil { - return err - } - defer conn.Close() - - // Disable replication on this session. We close the connection after using - // it, so there's no need to re-enable replication when we're done. - if _, err := conn.ExecuteFetch("SET @@session.sql_log_bin = 0", 0, false); err != nil { - return err - } - - return upsertLocalMetadata(conn, localMetadata, dbName) -} - -func createMetadataTables(conn *dbconnpool.DBConnection, dbName string) error { - if _, err := conn.ExecuteFetch("CREATE DATABASE IF NOT EXISTS _vt", 0, false); err != nil { - return err - } - - if err := createLocalMetadataTable(conn, dbName); err != nil { - return err - } - - if err := createShardMetadataTable(conn, dbName); err != nil { - return err - } - - return nil -} - -func createLocalMetadataTable(conn *dbconnpool.DBConnection, dbName string) error { - if _, err := conn.ExecuteFetch(sqlCreateLocalMetadataTable, 0, false); err != nil { - return err - } - - for _, sql := range sqlAlterLocalMetadataTable { - if _, err := conn.ExecuteFetch(sql, 0, false); err != nil { - // Ignore "Duplicate column name 'db_name'" errors which can happen on every restart. - if merr, ok := err.(*mysql.SQLError); !ok || merr.Num != mysql.ERDupFieldName { - log.Errorf("Error executing %v: %v", sql, err) - return err - } - } - } - - sql := fmt.Sprintf(sqlUpdateLocalMetadataTable, dbName) - if _, err := conn.ExecuteFetch(sql, 0, false); err != nil { - log.Errorf("Error executing %v: %v, continuing. Please check the data in _vt.local_metadata and take corrective action.", sql, err) - } - - return nil -} - -func createShardMetadataTable(conn *dbconnpool.DBConnection, dbName string) error { - if _, err := conn.ExecuteFetch(sqlCreateShardMetadataTable, 0, false); err != nil { - return err - } - - for _, sql := range sqlAlterShardMetadataTable { - if _, err := conn.ExecuteFetch(sql, 0, false); err != nil { - // Ignore "Duplicate column name 'db_name'" errors which can happen on every restart. - if merr, ok := err.(*mysql.SQLError); !ok || merr.Num != mysql.ERDupFieldName { - log.Errorf("Error executing %v: %v", sql, err) - return err - } - } - } - - sql := fmt.Sprintf(sqlUpdateShardMetadataTable, dbName) - if _, err := conn.ExecuteFetch(sql, 0, false); err != nil { - log.Errorf("Error executing %v: %v, continuing. Please check the data in _vt.shard_metadata and take corrective action.", sql, err) - } - - return nil -} - -// upsertLocalMetadata adds the given metadata map to the _vt.local_metadata -// table, updating any rows that exist for a given `_vt.local_metadata.name` -// with the map value. The session that performs these upserts sets -// sql_log_bin=0, as the _vt.local_metadata table is meant to never be -// replicated. -// -// Callers are responsible for ensuring the _vt.local_metadata table exists -// before calling this function, usually by calling CreateMetadataTables at -// least once prior. -func upsertLocalMetadata(conn *dbconnpool.DBConnection, localMetadata map[string]string, dbName string) error { - // Populate local_metadata from the passed list of values. - if _, err := conn.ExecuteFetch("BEGIN", 0, false); err != nil { - return err - } - for name, val := range localMetadata { - nameValue := sqltypes.NewVarChar(name) - valValue := sqltypes.NewVarChar(val) - dbNameValue := sqltypes.NewVarBinary(dbName) - - queryBuf := bytes.Buffer{} - queryBuf.WriteString("INSERT INTO _vt.local_metadata (name,value, db_name) VALUES (") - nameValue.EncodeSQL(&queryBuf) - queryBuf.WriteByte(',') - valValue.EncodeSQL(&queryBuf) - queryBuf.WriteByte(',') - dbNameValue.EncodeSQL(&queryBuf) - queryBuf.WriteString(") ON DUPLICATE KEY UPDATE value = ") - valValue.EncodeSQL(&queryBuf) - - if _, err := conn.ExecuteFetch(queryBuf.String(), 0, false); err != nil { - return err - } - } - - if _, err := conn.ExecuteFetch("COMMIT", 0, false); err != nil { - return err - } - - return nil -} diff --git a/go/vt/mysqlctl/mysqld.go b/go/vt/mysqlctl/mysqld.go index bf783628801..5e5a542fa5f 100644 --- a/go/vt/mysqlctl/mysqld.go +++ b/go/vt/mysqlctl/mysqld.go @@ -1261,10 +1261,26 @@ func (mysqld *Mysqld) applyBinlogFile(binlogFile string, includeGTIDs mysql.GTID args := []string{ "--defaults-extra-file=" + cnf, } + + // We disable super_read_only, in case it is in the default MySQL startup + // parameters. We do it blindly, since this will fail on MariaDB, which doesn't + // have super_read_only This is safe, since we're restarting MySQL after the restore anyway + log.Infof("Restore: disabling super_read_only") + if err := mysqld.SetSuperReadOnly(false); err != nil { + if strings.Contains(err.Error(), strconv.Itoa(mysql.ERUnknownSystemVariable)) { + log.Warningf("Restore: server does not know about super_read_only, continuing anyway...") + } else { + log.Errorf("Restore: unexpected error while trying to set super_read_only: %v", err) + return err + } + } + mysqlCmd = exec.Command(name, args...) mysqlCmd.Dir = dir mysqlCmd.Env = env mysqlCmd.Stdin = pipe // piped from mysqlbinlog + mysqlCmd.Stdout = os.Stderr + mysqlCmd.Stderr = os.Stderr } // Run both processes, piped: if err := mysqlbinlogCmd.Start(); err != nil { @@ -1278,6 +1294,9 @@ func (mysqld *Mysqld) applyBinlogFile(binlogFile string, includeGTIDs mysql.GTID return err } if err := mysqlCmd.Wait(); err != nil { + println(mysqlCmd.Stdout) + println(mysqlCmd.Stderr) + println(mysqlCmd.Stdin) return err } return nil diff --git a/go/vt/mysqlctl/reparent.go b/go/vt/mysqlctl/reparent.go index d8a4640bc7a..e888e9ffcbc 100644 --- a/go/vt/mysqlctl/reparent.go +++ b/go/vt/mysqlctl/reparent.go @@ -45,6 +45,12 @@ func CreateReparentJournal() []string { ENGINE=InnoDB`, mysql.MaximumPositionSize)} } +// Add a dummy call to create _vt database; +// this is to test current primary position. +func CreateDummyDatabase() []string { + return []string{"CREATE DATABASE IF NOT EXISTS _dummy"} +} + // AlterReparentJournal returns the commands to execute to change // column master_alias -> primary_alias or the other way // In 13.0.0 we introduced renaming of primary_alias -> master_alias. @@ -82,6 +88,9 @@ func queryReparentJournal(timeCreatedNS int64) string { func (mysqld *Mysqld) WaitForReparentJournal(ctx context.Context, timeCreatedNS int64) error { for { qr, err := mysqld.FetchSuperQuery(ctx, queryReparentJournal(timeCreatedNS)) + if err != nil { + log.Infof("error query reparent journal %v", err) + } if err == nil && len(qr.Rows) == 1 { // we have the row, we're done return nil diff --git a/go/vt/mysqlctl/replication.go b/go/vt/mysqlctl/replication.go index e1dfee7b141..f4983f5833c 100644 --- a/go/vt/mysqlctl/replication.go +++ b/go/vt/mysqlctl/replication.go @@ -24,6 +24,7 @@ import ( "errors" "fmt" "net" + "runtime/debug" "strconv" "strings" "time" @@ -233,6 +234,7 @@ func (mysqld *Mysqld) IsReadOnly() (bool, error) { // SetReadOnly set/unset the read_only flag func (mysqld *Mysqld) SetReadOnly(on bool) error { + log.Infof(">>>>> SetReadOnly %t %s", on, debug.Stack()) query := "SET GLOBAL read_only = " if on { query += "ON" diff --git a/go/vt/servenv/exporter.go b/go/vt/servenv/exporter.go index 397be415581..d8eb4ef428d 100644 --- a/go/vt/servenv/exporter.go +++ b/go/vt/servenv/exporter.go @@ -102,6 +102,7 @@ type Exporter struct { name, label string handleFuncs map[string]*handleFunc sp *statusPage + mu sync.Mutex } // NewExporter creates a new Exporter with name as namespace. @@ -154,6 +155,8 @@ func (e *Exporter) URLPrefix() string { // url remapped from /path to /name/path. If name is empty, the request // is passed through to http.HandleFunc. func (e *Exporter) HandleFunc(url string, f func(w http.ResponseWriter, r *http.Request)) { + e.mu.Lock() + defer e.mu.Unlock() if e.name == "" { http.HandleFunc(url, f) return diff --git a/go/vt/servenv/servenv.go b/go/vt/servenv/servenv.go index 4e5d582a2ae..b113de0da9f 100644 --- a/go/vt/servenv/servenv.go +++ b/go/vt/servenv/servenv.go @@ -82,6 +82,7 @@ var ( onCloseTimeout = 10 * time.Second catchSigpipe bool maxStackSize = 64 * 1024 * 1024 + initStartTime time.Time ) // RegisterFlags installs the flags used by Init, Run, and RunDefault. @@ -101,10 +102,17 @@ func RegisterFlags() { }) } +func GetInitStartTime() time.Time { + mu.Lock() + defer mu.Unlock() + return initStartTime +} + // Init is the first phase of the server startup. func Init() { mu.Lock() defer mu.Unlock() + initStartTime = time.Now() // Ignore SIGPIPE if specified // The Go runtime catches SIGPIPE for us on all fds except stdout/stderr diff --git a/go/vt/sidecardb/flags.go b/go/vt/sidecardb/flags.go new file mode 100644 index 00000000000..38305005e23 --- /dev/null +++ b/go/vt/sidecardb/flags.go @@ -0,0 +1,35 @@ +package sidecardb + +import ( + "sync" + + "github.com/spf13/pflag" + + "vitess.io/vitess/go/vt/servenv" +) + +var InitVTSchemaOnTabletInit = true +var mu sync.Mutex + +func init() { + servenv.OnParseFor("vttablet", registerFlags) +} + +func registerFlags(fs *pflag.FlagSet) { + mu.Lock() + defer mu.Unlock() + fs.BoolVar(&InitVTSchemaOnTabletInit, "init-vt-schema-on-tablet-init", InitVTSchemaOnTabletInit, + "EXPERIMENTAL: _vt schema is created on tablet init and not separately and/or using WithDDL") +} + +func GetInitVTSchemaFlag() bool { + mu.Lock() + defer mu.Unlock() + return InitVTSchemaOnTabletInit +} + +func SetInitVTSchemaFlag(val bool) { + mu.Lock() + defer mu.Unlock() + InitVTSchemaOnTabletInit = val +} diff --git a/go/vt/sidecardb/sidecardb.go b/go/vt/sidecardb/sidecardb.go new file mode 100644 index 00000000000..c40f43b6de0 --- /dev/null +++ b/go/vt/sidecardb/sidecardb.go @@ -0,0 +1,306 @@ +package sidecardb + +import ( + "context" + "embed" + "fmt" + "runtime" + "strings" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/schemadiff" +) + +const ( + CreateVTDatabaseQuery = "create database if not exists _vt" + UseVTDatabaseQuery = "use _vt" +) + +//go:embed vtschema/* +var schemaLocation embed.FS + +type VTTable struct { + module string + path string + name string +} + +func (t *VTTable) String() string { + return fmt.Sprintf("_vt table: %s (%s)", t.name, t.module) +} + +var vtTables []*VTTable + +func init() { + // todo: twopc tables? + vtTables = []*VTTable{ + {"Online DDL", "onlineddl/schema_migrations.sql", "schema_migrations"}, + {"VTGate Schema Tracker", "schematracker/schemacopy.sql", "schemacopy"}, + {"VReplication", "vreplication/vreplication.sql", "vreplication"}, + {"VReplication", "vreplication/vreplication_log.sql", "vreplication_log"}, + {"VReplication", "vreplication/copy_state.sql", "copy_state"}, + {"VReplication", "vreplication/resharding_journal.sql", "resharding_journal"}, + {"VReplication", "vreplication/schema_version.sql", "schema_version"}, + {"VDiff", "vdiff/vdiff.sql", "vdiff"}, + {"VDiff", "vdiff/vdiff_log.sql", "vdiff_log"}, + {"VDiff", "vdiff/vdiff_table.sql", "vdiff_table"}, + {"Misc", "misc/heartbeat.sql", "heartbeat"}, + {"Misc", "misc/reparent_journal.sql", "reparent_journal"}, + } +} + +// PrintCallerDetails is a temp helper for dev debugging +func PrintCallerDetails() { + pc, _, line, ok := runtime.Caller(2) + details := runtime.FuncForPC(pc) + if ok && details != nil { + log.Infof(">>>>>>>>> called from %s:%d\n", details.Name(), line) + } +} + +type VTSchemaInit struct { + ctx context.Context + exec Exec + sroHook SetSuperReadOnlyHook + rsroHook ReSetSuperReadOnlyHook + existingTables map[string]bool +} + +// Exec is a function prototype of callback passed to Init() which will execute the specified query +type Exec func(ctx context.Context, query string, maxRows int, wantFields bool, useVT bool) (*sqltypes.Result, error) + +type SetSuperReadOnlyHook func(ctx context.Context) (needsReset bool, err error) +type ReSetSuperReadOnlyHook func(ctx context.Context) (err error) + +// Init creates or upgrades the _vt schema based on declarative schema for all _vt tables +func Init(ctx context.Context, exec Exec, sroHook SetSuperReadOnlyHook, rsroHook ReSetSuperReadOnlyHook) error { + PrintCallerDetails() + if !GetInitVTSchemaFlag() { + log.Infof("init-vt-schema-on-tablet-init NOT set, not updating _vt schema on tablet init") + return nil + } + log.Infof("init-vt-schema-on-tablet-init SET, updating _vt schema on tablet init") + si := &VTSchemaInit{ + ctx: ctx, + exec: exec, + sroHook: sroHook, + rsroHook: rsroHook, + } + + if si.sroHook != nil { + log.Infof("executing SetSuperReadOnlyHook ...") + needsReset, err := si.sroHook(ctx) + if err != nil { + log.Infof("executing SetSuperReadOnlyHook err ... %v", err) + return err + } + if needsReset { + log.Infof("executing ReSetSuperReadOnlyHook ...") + defer func() { + if err := si.rsroHook(ctx); err != nil { + log.Infof("executing ReSetSuperReadOnlyHook fail ... %v", err) + } + }() + } + } + + log.Infof("CreateVTDatabase start...") + if err := si.CreateVTDatabase(); err != nil { + return err + } + log.Infof("CreateVTDatabase end...") + + currentDatabase, err := si.setCurrentDatabase("_vt") + if err != nil { + return err + } + // nolint + defer si.setCurrentDatabase(currentDatabase) + + if err = si.loadExistingTables(); err != nil { + return err + } + + for _, table := range vtTables { + if err := si.createOrUpgradeTable(table); err != nil { + return err + } + } + log.Flush() + return nil +} + +func (si *VTSchemaInit) CreateVTDatabase() error { + if si.ctx.Err() != nil { + log.Infof("context error CreateVTDatabase ... %v", si.ctx.Err()) + } + rs, err := si.exec(si.ctx, "SHOW DATABASES LIKE '_vt'", 2, false, false) + if err != nil { + log.Infof("error CreateVTDatabase ... %v", err) + return err + } + + switch len(rs.Rows) { + case 0: + _, err := si.exec(si.ctx, CreateVTDatabaseQuery, 1, false, false) + if err != nil { + return err + } + log.Infof("Created _vt database") + case 1: + log.Infof("_vt database already exists, not an error") + //break + default: + return fmt.Errorf("found too many rows for _vt: %d", len(rs.Rows)) + } + return nil +} + +// sets db of correct connection to dbName and returns current db +func (si *VTSchemaInit) setCurrentDatabase(dbName string) (string, error) { + rs, err := si.exec(si.ctx, "select database()", 1, false, false) + if err != nil { + return "", err + } + if rs == nil || rs.Rows == nil { // we get this in tests + return "", nil + } + currentDB := rs.Rows[0][0].ToString() + log.Infof("current db is %s", currentDB) + _, err = si.exec(si.ctx, fmt.Sprintf("use %s", dbName), 1000, false, false) + if err != nil { + return "", err + } + return currentDB, nil +} + +// gets existing schema of table +func (si *VTSchemaInit) getCurrentSchema(tableName string) (string, error) { + var currentTableSchema string + showCreateTableSQL := "show create table _vt.%s" + rs, err := si.exec(si.ctx, fmt.Sprintf(showCreateTableSQL, tableName), 1, false, false) + if err != nil { + log.Errorf("Error showing _vt table %s: %+v", tableName, err) + return "", err + } + if len(rs.Rows) > 0 { + currentTableSchema = rs.Rows[0][1].ToString() + //log.Infof("current schema %s", currentTableSchema) + } + return currentTableSchema, nil +} + +// hack to remove an extra DEFAULT CHARSET which we get from "show create table" +func stripCharset(schema string) string { + ind := strings.Index(schema, "DEFAULT CHARSET") + if ind <= 0 { + return schema + } + return schema[:ind] +} + +// finds diff that needs to be applied to current schema to get the desired one. Will be an empty string if they match +func (si *VTSchemaInit) findTableSchemaDiff(current, desired string) (string, error) { + // temp hack so we don't get a spurious alter just because of the charset + current = stripCharset(current) + hints := &schemadiff.DiffHints{} + diff, err := schemadiff.DiffCreateTablesQueries(current, desired, hints) + if err != nil { + return "", err + } + + tableAlterSQL := diff.CanonicalStatementString() + if strings.Contains(tableAlterSQL, "ALTER") { + log.Infof("alter sql %s", tableAlterSQL) + log.Infof("current schema %s", current) + + } else { + tableAlterSQL = strings.Replace(tableAlterSQL, "CREATE TABLE", "CREATE TABLE IF NOT EXISTS", 1) + } + + return tableAlterSQL, nil +} + +// expects that we are already in the _vt database +func (si *VTSchemaInit) createOrUpgradeTable(table *VTTable) error { + + var desiredTableSchema string + ctx := si.ctx + bytes, err := schemaLocation.ReadFile(fmt.Sprintf("vtschema/%s", table.path)) + if err != nil { + return err + } + desiredTableSchema = string(bytes) + + var tableAlterSQL string + tableExists := si.tableExists(table.name) + if tableExists { + //log.Infof("table exists %s", table.name) + currentTableSchema, err := si.getCurrentSchema(table.name) + if err != nil { + return err + } + + tableAlterSQL, err = si.findTableSchemaDiff(currentTableSchema, desiredTableSchema) + if err != nil { + return err + } + + } else { + //log.Infof("table %s not found", table.name) + tableAlterSQL = desiredTableSchema + } + + if strings.TrimSpace(tableAlterSQL) != "" { + //log.Infof("tableAlterSQL is %s", tableAlterSQL) + _, err = si.exec(ctx, tableAlterSQL, 1, false, true) + if err != nil { + if strings.Contains(err.Error(), "already exists") { //todo: improve check for existing table + return nil + } + log.Errorf("Error altering _vt table %s: %+v", table, err) + return err + } + newTableSchema, err := si.getCurrentSchema(table.name) + if err != nil { + return err + } + tableAlterSQL2, err := si.findTableSchemaDiff(newTableSchema, desiredTableSchema) + if err != nil { + return err + } + if tableAlterSQL2 != "" { + _ = fmt.Errorf("table alter did not work, desired schema is %s but current schema is %s: %s", + desiredTableSchema, newTableSchema, tableAlterSQL) + log.Error(err) + } + if tableExists { + log.Infof("Updated _vt table %s: %s", table, tableAlterSQL) + } else { + log.Infof("Created _vt table %s", table) + } + return nil + } + log.Infof("Table %s was already correct", table.name) + return nil +} + +// is table already in _vt? +func (si *VTSchemaInit) tableExists(tableName string) bool { + _, ok := si.existingTables[tableName] + return ok +} + +// load existing tables from _vt +func (si *VTSchemaInit) loadExistingTables() error { + si.existingTables = make(map[string]bool) + rs, err := si.exec(si.ctx, "show tables from _vt", 1000, false, false) + if err != nil { + return err + } + for _, row := range rs.Rows { + si.existingTables[row[0].ToString()] = true + } + return nil +} diff --git a/go/vt/sidecardb/vtschema/misc/heartbeat.sql b/go/vt/sidecardb/vtschema/misc/heartbeat.sql new file mode 100644 index 00000000000..9168a0c05c4 --- /dev/null +++ b/go/vt/sidecardb/vtschema/misc/heartbeat.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS _vt.heartbeat +( + keyspaceShard VARBINARY(256) NOT NULL, + tabletUid INT UNSIGNED NOT NULL, + ts BIGINT UNSIGNED NOT NULL, + PRIMARY KEY (`keyspaceShard`) +) engine = InnoDB diff --git a/go/vt/sidecardb/vtschema/misc/reparent_journal.sql b/go/vt/sidecardb/vtschema/misc/reparent_journal.sql new file mode 100644 index 00000000000..bbd05785730 --- /dev/null +++ b/go/vt/sidecardb/vtschema/misc/reparent_journal.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS _vt.reparent_journal +( + `time_created_ns` bigint(20) unsigned NOT NULL, + `action_name` varbinary(250) NOT NULL, + `primary_alias` varbinary(32) NOT NULL, + `replication_position` varbinary(64000) DEFAULT NULL, + + PRIMARY KEY (`time_created_ns`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/onlineddl/schema_migrations.sql b/go/vt/sidecardb/vtschema/onlineddl/schema_migrations.sql new file mode 100644 index 00000000000..7dcca8a59fd --- /dev/null +++ b/go/vt/sidecardb/vtschema/onlineddl/schema_migrations.sql @@ -0,0 +1,66 @@ +CREATE TABLE _vt.schema_migrations +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `migration_uuid` varchar(64) NOT NULL, + `keyspace` varchar(256) NOT NULL, + `shard` varchar(255) NOT NULL, + `mysql_schema` varchar(128) NOT NULL, + `mysql_table` varchar(128) NOT NULL, + `migration_statement` text NOT NULL, + `strategy` varchar(128) NOT NULL, + `options` varchar(8192) NOT NULL, + `added_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `requested_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ready_timestamp` timestamp NULL DEFAULT NULL, + `started_timestamp` timestamp NULL DEFAULT NULL, + `liveness_timestamp` timestamp NULL DEFAULT NULL, + `completed_timestamp` timestamp NULL DEFAULT NULL, + `cleanup_timestamp` timestamp NULL DEFAULT NULL, + `migration_status` varchar(128) NOT NULL, + `log_path` varchar(1024) NOT NULL, + `artifacts` text NOT NULL, + `retries` int unsigned NOT NULL DEFAULT '0', + `tablet` varchar(128) NOT NULL DEFAULT '', + `tablet_failure` tinyint unsigned NOT NULL DEFAULT '0', + `progress` float NOT NULL DEFAULT '0', + `migration_context` varchar(1024) NOT NULL DEFAULT '', + `ddl_action` varchar(16) NOT NULL DEFAULT '', + `message` text NOT NULL, + `eta_seconds` bigint NOT NULL DEFAULT '-1', + `rows_copied` bigint unsigned NOT NULL DEFAULT '0', + `table_rows` bigint NOT NULL DEFAULT '0', + `added_unique_keys` int unsigned NOT NULL DEFAULT '0', + `removed_unique_keys` int unsigned NOT NULL DEFAULT '0', + `log_file` varchar(1024) NOT NULL DEFAULT '', + `retain_artifacts_seconds` bigint NOT NULL DEFAULT '0', + `postpone_completion` tinyint unsigned NOT NULL DEFAULT '0', + `removed_unique_key_names` text NOT NULL, + `dropped_no_default_column_names` text NOT NULL, + `expanded_column_names` text NOT NULL, + `revertible_notes` text NOT NULL, + `allow_concurrent` tinyint unsigned NOT NULL DEFAULT '0', + `reverted_uuid` varchar(64) NOT NULL DEFAULT '', + `is_view` tinyint unsigned NOT NULL DEFAULT '0', + `ready_to_complete` tinyint unsigned NOT NULL DEFAULT '0', + `stowaway_table` tinytext NOT NULL, + `vitess_liveness_indicator` bigint NOT NULL DEFAULT '0', + `user_throttle_ratio` float NOT NULL DEFAULT '0', + `special_plan` text NOT NULL, + `last_throttled_timestamp` timestamp NULL DEFAULT NULL, + `component_throttled` tinytext NOT NULL, + `cancelled_timestamp` timestamp NULL DEFAULT NULL, + `postpone_launch` tinyint unsigned NOT NULL DEFAULT '0', + `stage` text NOT NULL, + `cutover_attempts` int unsigned NOT NULL DEFAULT '0', + `is_immediate_operation` tinyint unsigned NOT NULL DEFAULT '0', + `reviewed_timestamp` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uuid_idx` (`migration_uuid`), + KEY `keyspace_shard_idx` (`keyspace`(64), `shard`(64)), + KEY `status_idx` (`migration_status`, `liveness_timestamp`), + KEY `cleanup_status_idx` (`cleanup_timestamp`, `migration_status`), + KEY `tablet_failure_idx` (`tablet_failure`, `migration_status`, `retries`), + KEY `table_complete_idx` (`migration_status`, `keyspace`(64), `mysql_table`(64), `completed_timestamp`), + KEY `migration_context_idx` (`migration_context`(64)), + KEY `reverted_uuid_idx` (`reverted_uuid`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/schematracker/schemacopy.sql b/go/vt/sidecardb/vtschema/schematracker/schemacopy.sql new file mode 100644 index 00000000000..14274aa8abe --- /dev/null +++ b/go/vt/sidecardb/vtschema/schematracker/schemacopy.sql @@ -0,0 +1,12 @@ +CREATE TABLE _vt.schemacopy +( + `table_schema` varchar(64) NOT NULL, + `table_name` varchar(64) NOT NULL, + `column_name` varchar(64) NOT NULL, + `ordinal_position` bigint unsigned NOT NULL, + `character_set_name` varchar(32) DEFAULT NULL, + `collation_name` varchar(32) DEFAULT NULL, + `data_type` varchar(64) NOT NULL, + `column_key` varchar(3) NOT NULL, + PRIMARY KEY (`table_schema`, `table_name`, `ordinal_position`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vdiff/vdiff.sql b/go/vt/sidecardb/vtschema/vdiff/vdiff.sql new file mode 100644 index 00000000000..4eb2ee0c925 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vdiff/vdiff.sql @@ -0,0 +1,20 @@ +CREATE TABLE _vt.vdiff +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `vdiff_uuid` varchar(64) NOT NULL, + `workflow` varbinary(1024) DEFAULT NULL, + `keyspace` varbinary(256) DEFAULT NULL, + `shard` varchar(255) NOT NULL, + `db_name` varbinary(1024) DEFAULT NULL, + `state` varbinary(64) DEFAULT NULL, + `options` json DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `started_at` timestamp NULL DEFAULT NULL, + `liveness_timestamp` timestamp NULL DEFAULT NULL, + `completed_at` timestamp NULL DEFAULT NULL, + `last_error` varbinary(512) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uuid_idx` (`vdiff_uuid`), + KEY `state` (`state`), + KEY `ks_wf_idx` (`keyspace`(64), `workflow`(64)) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vdiff/vdiff_log.sql b/go/vt/sidecardb/vtschema/vdiff/vdiff_log.sql new file mode 100644 index 00000000000..d72f28900ea --- /dev/null +++ b/go/vt/sidecardb/vtschema/vdiff/vdiff_log.sql @@ -0,0 +1,8 @@ +CREATE TABLE _vt.vdiff_log +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `vdiff_id` int(11) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `message` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vdiff/vdiff_table.sql b/go/vt/sidecardb/vtschema/vdiff/vdiff_table.sql new file mode 100644 index 00000000000..affbc8671a9 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vdiff/vdiff_table.sql @@ -0,0 +1,14 @@ +CREATE TABLE _vt.vdiff_table +( + `vdiff_id` varchar(64) NOT NULL, + `table_name` varbinary(128) NOT NULL, + `state` varbinary(64) DEFAULT NULL, + `lastpk` varbinary(2000) DEFAULT NULL, + `table_rows` bigint(20) NOT NULL DEFAULT '0', + `rows_compared` bigint(20) NOT NULL DEFAULT '0', + `mismatch` tinyint(1) NOT NULL DEFAULT '0', + `report` json DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`vdiff_id`, `table_name`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vreplication/copy_state.sql b/go/vt/sidecardb/vtschema/vreplication/copy_state.sql new file mode 100644 index 00000000000..e7a7908f307 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vreplication/copy_state.sql @@ -0,0 +1,9 @@ +CREATE TABLE _vt.copy_state +( + `id` bigint unsigned NOT NULL AUTO_INCREMENT, + `vrepl_id` int NOT NULL, + `table_name` varbinary(128) NOT NULL, + `lastpk` varbinary(2000) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `vrepl_id` (`vrepl_id`,`table_name`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vreplication/resharding_journal.sql b/go/vt/sidecardb/vtschema/vreplication/resharding_journal.sql new file mode 100644 index 00000000000..4289aa4d916 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vreplication/resharding_journal.sql @@ -0,0 +1,7 @@ +CREATE TABLE _vt.resharding_journal +( + `id` bigint NOT NULL, + `db_name` varbinary(255) DEFAULT NULL, + `val` blob, + PRIMARY KEY (`id`) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vreplication/schema_version.sql b/go/vt/sidecardb/vtschema/vreplication/schema_version.sql new file mode 100644 index 00000000000..8bb271aa3b1 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vreplication/schema_version.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS _vt.schema_version +( + id INT NOT NULL AUTO_INCREMENT, + pos VARBINARY(10000) NOT NULL, + time_updated BIGINT(20) NOT NULL, + ddl BLOB DEFAULT NULL, + schemax LONGBLOB NOT NULL, + PRIMARY KEY (id) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vreplication/vreplication.sql b/go/vt/sidecardb/vtschema/vreplication/vreplication.sql new file mode 100644 index 00000000000..31d4548af1f --- /dev/null +++ b/go/vt/sidecardb/vtschema/vreplication/vreplication.sql @@ -0,0 +1,26 @@ +CREATE TABLE _vt.vreplication +( + `id` int NOT NULL AUTO_INCREMENT, + `workflow` varbinary(1000) DEFAULT NULL, + `source` mediumblob NOT NULL, + `pos` varbinary(10000) NOT NULL, + `stop_pos` varbinary(10000) DEFAULT NULL, + `max_tps` bigint NOT NULL, + `max_replication_lag` bigint NOT NULL, + `cell` varbinary(1000) DEFAULT NULL, + `tablet_types` varbinary(100) DEFAULT NULL, + `time_updated` bigint NOT NULL, + `transaction_timestamp` bigint NOT NULL, + `state` varbinary(100) NOT NULL, + `message` varbinary(1000) DEFAULT NULL, + `db_name` varbinary(255) NOT NULL, + `rows_copied` bigint NOT NULL DEFAULT '0', + `tags` varbinary(1024) NOT NULL DEFAULT '', + `time_heartbeat` bigint NOT NULL DEFAULT '0', + `workflow_type` int NOT NULL DEFAULT '0', + `time_throttled` bigint NOT NULL DEFAULT '0', + `component_throttled` varchar(255) NOT NULL DEFAULT '', + `workflow_sub_type` int NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `workflow_idx` (`workflow`(64)) +) ENGINE = InnoDB diff --git a/go/vt/sidecardb/vtschema/vreplication/vreplication_log.sql b/go/vt/sidecardb/vtschema/vreplication/vreplication_log.sql new file mode 100644 index 00000000000..94421edd8d8 --- /dev/null +++ b/go/vt/sidecardb/vtschema/vreplication/vreplication_log.sql @@ -0,0 +1,12 @@ +CREATE TABLE _vt.vreplication_log +( + `id` bigint NOT NULL AUTO_INCREMENT, + `vrepl_id` int NOT NULL, + `type` varbinary(256) NOT NULL, + `state` varbinary(100) NOT NULL, + `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `message` text NOT NULL, + `count` bigint NOT NULL DEFAULT '1', + PRIMARY KEY (`id`) +) ENGINE = InnoDB diff --git a/go/vt/topotools/tablet.go b/go/vt/topotools/tablet.go index af6f4b3c3c6..9f6bd2a87f2 100644 --- a/go/vt/topotools/tablet.go +++ b/go/vt/topotools/tablet.go @@ -65,6 +65,7 @@ func ConfigureTabletHook(hk *hook.Hook, tabletAlias *topodatapb.TabletAlias) { // // If successful, the updated tablet record is returned. func ChangeType(ctx context.Context, ts *topo.Server, tabletAlias *topodatapb.TabletAlias, newType topodatapb.TabletType, PrimaryTermStartTime *vttime.Time) (*topodatapb.Tablet, error) { + log.Infof("inside topotools change type...") var result *topodatapb.Tablet // Always clear out the primary timestamp if not primary. if newType != topodatapb.TabletType_PRIMARY { diff --git a/go/vt/vtadmin/api_authz_test.go b/go/vt/vtadmin/api_authz_test.go index 45d3e443c6e..628e290c78b 100644 --- a/go/vt/vtadmin/api_authz_test.go +++ b/go/vt/vtadmin/api_authz_test.go @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/vt/sidecardb" "vitess.io/vitess/go/vt/topo/topoproto" "vitess.io/vitess/go/vt/vtadmin" "vitess.io/vitess/go/vt/vtadmin/cluster" @@ -44,6 +45,8 @@ import ( ) func TestCreateKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -68,12 +71,14 @@ func TestCreateKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -93,6 +98,7 @@ func TestCreateKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -113,6 +119,8 @@ func TestCreateKeyspace(t *testing.T) { } func TestCreateShard(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -137,12 +145,14 @@ func TestCreateShard(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -163,6 +173,7 @@ func TestCreateShard(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -184,6 +195,8 @@ func TestCreateShard(t *testing.T) { } func TestDeleteKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -208,12 +221,14 @@ func TestDeleteKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -233,6 +248,7 @@ func TestDeleteKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -253,6 +269,8 @@ func TestDeleteKeyspace(t *testing.T) { } func TestDeleteShards(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -277,12 +295,14 @@ func TestDeleteShards(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -307,6 +327,7 @@ func TestDeleteShards(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -332,6 +353,8 @@ func TestDeleteShards(t *testing.T) { } func TestDeleteTablet(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -356,12 +379,14 @@ func TestDeleteTablet(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -382,6 +407,7 @@ func TestDeleteTablet(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -403,6 +429,8 @@ func TestDeleteTablet(t *testing.T) { } func TestEmergencyFailoverShard(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -427,12 +455,14 @@ func TestEmergencyFailoverShard(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -453,6 +483,7 @@ func TestEmergencyFailoverShard(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -474,6 +505,8 @@ func TestEmergencyFailoverShard(t *testing.T) { } func TestFindSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -503,10 +536,12 @@ func TestFindSchema(t *testing.T) { require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -526,10 +561,12 @@ func TestFindSchema(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -548,10 +585,12 @@ func TestFindSchema(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -573,6 +612,8 @@ func TestFindSchema(t *testing.T) { } func TestGetBackups(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -603,12 +644,14 @@ func TestGetBackups(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -623,6 +666,7 @@ func TestGetBackups(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -637,6 +681,7 @@ func TestGetBackups(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -652,6 +697,8 @@ func TestGetBackups(t *testing.T) { } func TestGetCellInfos(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -682,12 +729,14 @@ func TestGetCellInfos(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -704,6 +753,7 @@ func TestGetCellInfos(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -720,6 +770,7 @@ func TestGetCellInfos(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -737,6 +788,8 @@ func TestGetCellInfos(t *testing.T) { } func TestGetCellsAliases(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -767,12 +820,14 @@ func TestGetCellsAliases(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -787,6 +842,7 @@ func TestGetCellsAliases(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -801,6 +857,7 @@ func TestGetCellsAliases(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -816,6 +873,8 @@ func TestGetCellsAliases(t *testing.T) { } func TestGetClusters(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -840,12 +899,14 @@ func TestGetClusters(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthenticated", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() var actor *rbac.Actor @@ -859,6 +920,7 @@ func TestGetClusters(t *testing.T) { }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -872,6 +934,7 @@ func TestGetClusters(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -887,6 +950,8 @@ func TestGetClusters(t *testing.T) { } func TestGetGates(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -916,10 +981,12 @@ func TestGetGates(t *testing.T) { require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -937,10 +1004,12 @@ func TestGetGates(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -959,10 +1028,12 @@ func TestGetGates(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -982,6 +1053,8 @@ func TestGetGates(t *testing.T) { } func TestGetKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1006,12 +1079,14 @@ func TestGetKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -1029,6 +1104,7 @@ func TestGetKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -1047,6 +1123,8 @@ func TestGetKeyspace(t *testing.T) { } func TestGetKeyspaces(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1077,12 +1155,14 @@ func TestGetKeyspaces(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -1097,6 +1177,7 @@ func TestGetKeyspaces(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -1118,6 +1199,7 @@ func TestGetKeyspaces(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -1140,6 +1222,8 @@ func TestGetKeyspaces(t *testing.T) { } func TestGetSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1163,10 +1247,12 @@ func TestGetSchema(t *testing.T) { require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1188,10 +1274,12 @@ func TestGetSchema(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1214,6 +1302,8 @@ func TestGetSchema(t *testing.T) { } func TestGetSchemas(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1243,10 +1333,12 @@ func TestGetSchemas(t *testing.T) { require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1264,10 +1356,12 @@ func TestGetSchemas(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1292,10 +1386,12 @@ func TestGetSchemas(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1321,6 +1417,8 @@ func TestGetSchemas(t *testing.T) { } func TestGetShardReplicationPositions(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1351,12 +1449,14 @@ func TestGetShardReplicationPositions(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -1371,6 +1471,7 @@ func TestGetShardReplicationPositions(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -1392,6 +1493,7 @@ func TestGetShardReplicationPositions(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -1414,6 +1516,8 @@ func TestGetShardReplicationPositions(t *testing.T) { } func TestGetSrvVSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1438,12 +1542,14 @@ func TestGetSrvVSchema(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -1461,6 +1567,7 @@ func TestGetSrvVSchema(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -1479,6 +1586,8 @@ func TestGetSrvVSchema(t *testing.T) { } func TestGetSrvVSchemas(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1509,12 +1618,14 @@ func TestGetSrvVSchemas(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -1529,6 +1640,7 @@ func TestGetSrvVSchemas(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -1550,6 +1662,7 @@ func TestGetSrvVSchemas(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -1572,6 +1685,8 @@ func TestGetSrvVSchemas(t *testing.T) { } func TestGetTablet(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1596,12 +1711,14 @@ func TestGetTablet(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -1621,6 +1738,7 @@ func TestGetTablet(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -1641,6 +1759,8 @@ func TestGetTablet(t *testing.T) { } func TestGetTablets(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1671,12 +1791,14 @@ func TestGetTablets(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -1691,6 +1813,7 @@ func TestGetTablets(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -1712,6 +1835,7 @@ func TestGetTablets(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -1734,6 +1858,8 @@ func TestGetTablets(t *testing.T) { } func TestGetVSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1758,12 +1884,14 @@ func TestGetVSchema(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -1781,6 +1909,7 @@ func TestGetVSchema(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -1799,6 +1928,8 @@ func TestGetVSchema(t *testing.T) { } func TestGetVSchemas(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1829,12 +1960,14 @@ func TestGetVSchemas(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -1849,6 +1982,7 @@ func TestGetVSchemas(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -1870,6 +2004,7 @@ func TestGetVSchemas(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -1892,6 +2027,8 @@ func TestGetVSchemas(t *testing.T) { } func TestGetVtctlds(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -1921,10 +2058,12 @@ func TestGetVtctlds(t *testing.T) { require.NoError(t, err, "failed to reify authorization rules: %+v", opts.RBAC.Rules) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1942,10 +2081,12 @@ func TestGetVtctlds(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1964,10 +2105,12 @@ func TestGetVtctlds(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -1987,6 +2130,8 @@ func TestGetVtctlds(t *testing.T) { } func TestGetWorkflow(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2011,12 +2156,14 @@ func TestGetWorkflow(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2035,6 +2182,7 @@ func TestGetWorkflow(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2054,6 +2202,8 @@ func TestGetWorkflow(t *testing.T) { } func TestGetWorkflows(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2084,12 +2234,14 @@ func TestGetWorkflows(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -2104,6 +2256,7 @@ func TestGetWorkflows(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -2118,6 +2271,7 @@ func TestGetWorkflows(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -2133,6 +2287,8 @@ func TestGetWorkflows(t *testing.T) { } func TestPingTablet(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2157,12 +2313,14 @@ func TestPingTablet(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2182,6 +2340,7 @@ func TestPingTablet(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2202,6 +2361,8 @@ func TestPingTablet(t *testing.T) { } func TestPlannedFailoverShard(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2226,12 +2387,14 @@ func TestPlannedFailoverShard(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2252,6 +2415,7 @@ func TestPlannedFailoverShard(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2273,6 +2437,8 @@ func TestPlannedFailoverShard(t *testing.T) { } func TestRefreshState(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2297,12 +2463,14 @@ func TestRefreshState(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2322,6 +2490,7 @@ func TestRefreshState(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2342,6 +2511,8 @@ func TestRefreshState(t *testing.T) { } func TestRefreshTabletReplicationSource(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2366,12 +2537,14 @@ func TestRefreshTabletReplicationSource(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2391,6 +2564,7 @@ func TestRefreshTabletReplicationSource(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2411,6 +2585,8 @@ func TestRefreshTabletReplicationSource(t *testing.T) { } func TestReloadSchemas(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2441,12 +2617,14 @@ func TestReloadSchemas(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "unauthorized"} @@ -2466,6 +2644,7 @@ func TestReloadSchemas(t *testing.T) { }) t.Run("partial access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-other"} @@ -2484,6 +2663,7 @@ func TestReloadSchemas(t *testing.T) { }) t.Run("full access", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed-all"} @@ -2503,6 +2683,8 @@ func TestReloadSchemas(t *testing.T) { } func TestRunHealthCheck(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2527,12 +2709,14 @@ func TestRunHealthCheck(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2552,6 +2736,7 @@ func TestRunHealthCheck(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2572,6 +2757,8 @@ func TestRunHealthCheck(t *testing.T) { } func TestSetReadOnly(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2596,12 +2783,14 @@ func TestSetReadOnly(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2621,6 +2810,7 @@ func TestSetReadOnly(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2641,6 +2831,8 @@ func TestSetReadOnly(t *testing.T) { } func TestSetReadWrite(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2665,12 +2857,14 @@ func TestSetReadWrite(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2690,6 +2884,7 @@ func TestSetReadWrite(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2710,6 +2905,8 @@ func TestSetReadWrite(t *testing.T) { } func TestStartReplication(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2734,12 +2931,14 @@ func TestStartReplication(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2759,6 +2958,7 @@ func TestStartReplication(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2779,6 +2979,8 @@ func TestStartReplication(t *testing.T) { } func TestStopReplication(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2803,12 +3005,14 @@ func TestStopReplication(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2828,6 +3032,7 @@ func TestStopReplication(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2848,6 +3053,8 @@ func TestStopReplication(t *testing.T) { } func TestTabletExternallyPromoted(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2872,12 +3079,14 @@ func TestTabletExternallyPromoted(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2897,6 +3106,7 @@ func TestTabletExternallyPromoted(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2917,6 +3127,8 @@ func TestTabletExternallyPromoted(t *testing.T) { } func TestVTExplain(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -2941,12 +3153,14 @@ func TestVTExplain(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -2964,6 +3178,7 @@ func TestVTExplain(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -2982,6 +3197,8 @@ func TestVTExplain(t *testing.T) { } func TestValidateKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -3006,12 +3223,14 @@ func TestValidateKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -3029,6 +3248,7 @@ func TestValidateKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -3047,6 +3267,8 @@ func TestValidateKeyspace(t *testing.T) { } func TestValidateSchemaKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -3071,12 +3293,14 @@ func TestValidateSchemaKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -3094,6 +3318,7 @@ func TestValidateSchemaKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} @@ -3112,6 +3337,8 @@ func TestValidateSchemaKeyspace(t *testing.T) { } func TestValidateVersionKeyspace(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -3136,12 +3363,14 @@ func TestValidateVersionKeyspace(t *testing.T) { api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } }) t.Run("unauthorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "other"} @@ -3159,6 +3388,7 @@ func TestValidateVersionKeyspace(t *testing.T) { }) t.Run("authorized actor", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() actor := &rbac.Actor{Name: "allowed"} diff --git a/go/vt/vtadmin/api_test.go b/go/vt/vtadmin/api_test.go index b707f2036aa..99812ab81bc 100644 --- a/go/vt/vtadmin/api_test.go +++ b/go/vt/vtadmin/api_test.go @@ -32,6 +32,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "vitess.io/vitess/go/vt/sidecardb" + _flag "vitess.io/vitess/go/internal/flag" "vitess.io/vitess/go/test/utils" "vitess.io/vitess/go/vt/topo" @@ -4600,7 +4602,11 @@ func TestGetWorkflows(t *testing.T) { } } -func TestVTExplain(t *testing.T) { +func TestVTExplain2(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + t.Parallel() tests := []struct { @@ -4826,6 +4832,9 @@ func TestVTExplain(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() t.Parallel() toposerver := memorytopo.NewServer("c0_cell1") diff --git a/go/vt/vtadmin/testutil/authztestgen/template.go b/go/vt/vtadmin/testutil/authztestgen/template.go index 518d710fb3f..1a834e571c4 100644 --- a/go/vt/vtadmin/testutil/authztestgen/template.go +++ b/go/vt/vtadmin/testutil/authztestgen/template.go @@ -49,6 +49,7 @@ import ( "vitess.io/vitess/go/vt/vtadmin" "vitess.io/vitess/go/vt/vtadmin/cluster" "vitess.io/vitess/go/vt/vtadmin/rbac" + "vitess.io/vitess/go/vt/sidecardb" "vitess.io/vitess/go/vt/vtadmin/testutil" "vitess.io/vitess/go/vt/vtadmin/vtctldclient/fakevtctldclient" @@ -63,6 +64,8 @@ import ( {{ range .Tests }} func Test{{ .Method }}(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() opts := vtadmin.Options{ @@ -90,6 +93,7 @@ func Test{{ .Method }}(t *testing.T) { {{ if not .SerializeCases }} api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } @@ -99,10 +103,12 @@ func Test{{ .Method }}(t *testing.T) { {{ with $test := . -}} {{ range .Cases }} t.Run("{{ .Name }}", func(t *testing.T) { + sidecardb.SetInitVTSchemaFlag(false) t.Parallel() {{ if $test.SerializeCases }} api := vtadmin.NewAPI(testClusters(t), opts) t.Cleanup(func() { + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() if err := api.Close(); err != nil { t.Logf("api did not close cleanly: %s", err.Error()) } diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index 767217b442b..dd27d381d1a 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -126,6 +126,10 @@ func CreateTablet( if err := tm.ChangeType(ctx, topodatapb.TabletType_PRIMARY /* semi-sync */, false); err != nil { return fmt.Errorf("TabletExternallyReparented failed on primary %v: %v", topoproto.TabletAliasString(alias), err) } + /*log.Infof("setting super read only to false for test purpose %v", topoproto.TabletAliasString(alias)) + if err := tm.MysqlDaemon.SetReadOnly(false); err != nil { + return fmt.Errorf("failed on set super read only on %v: %v", topoproto.TabletAliasString(alias), err) + }*/ } controller.AddStatusHeader() controller.AddStatusPart() diff --git a/go/vt/vtctl/grpcvtctldserver/endtoend/init_shard_primary_test.go b/go/vt/vtctl/grpcvtctldserver/endtoend/init_shard_primary_test.go index 19a580c451c..d327f302930 100644 --- a/go/vt/vtctl/grpcvtctldserver/endtoend/init_shard_primary_test.go +++ b/go/vt/vtctl/grpcvtctldserver/endtoend/init_shard_primary_test.go @@ -52,12 +52,7 @@ func TestInitShardPrimary(t *testing.T) { tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ "FAKE RESET ALL REPLICATION", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", + "CREATE DATABASE IF NOT EXISTS _dummy", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } @@ -119,12 +114,7 @@ func TestInitShardPrimaryNoFormerPrimary(t *testing.T) { tablet1.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ "FAKE RESET ALL REPLICATION", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", + "CREATE DATABASE IF NOT EXISTS _dummy", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } diff --git a/go/vt/vtctl/grpcvtctldserver/server.go b/go/vt/vtctl/grpcvtctldserver/server.go index 1093924537e..8a84bed2b40 100644 --- a/go/vt/vtctl/grpcvtctldserver/server.go +++ b/go/vt/vtctl/grpcvtctldserver/server.go @@ -1920,7 +1920,7 @@ func (s *VtctldServer) GetVersion(ctx context.Context, req *vtctldatapb.GetVersi return nil, err } - version, err := getVersionFromTablet(tablet.Addr()) + version, err := GetVersionFunc()(tablet.Addr()) if err != nil { return nil, err } @@ -4416,8 +4416,21 @@ var getVersionFromTabletDebugVars = func(tabletAddr string) (string, error) { return version, nil } +var versionFuncMu sync.Mutex var getVersionFromTablet = getVersionFromTabletDebugVars +func SetVersionFunc(versionFunc func(string) (string, error)) { + versionFuncMu.Lock() + defer versionFuncMu.Unlock() + getVersionFromTablet = versionFunc +} + +func GetVersionFunc() func(string) (string, error) { + versionFuncMu.Lock() + defer versionFuncMu.Unlock() + return getVersionFromTablet +} + // helper method to asynchronously get and diff a version func (s *VtctldServer) diffVersion(ctx context.Context, primaryVersion string, primaryAlias *topodatapb.TabletAlias, alias *topodatapb.TabletAlias, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() diff --git a/go/vt/vtctl/grpcvtctldserver/server_test.go b/go/vt/vtctl/grpcvtctldserver/server_test.go index 2e3bf21c822..05ac69768e8 100644 --- a/go/vt/vtctl/grpcvtctldserver/server_test.go +++ b/go/vt/vtctl/grpcvtctldserver/server_test.go @@ -21,10 +21,13 @@ import ( "errors" "fmt" "io" + "os" "sort" "testing" "time" + _flag "vitess.io/vitess/go/internal/flag" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" @@ -11227,7 +11230,7 @@ func TestValidateVersionKeyspace(t *testing.T) { "primary:0": "version1", "replica:0": "version1", } - getVersionFromTablet = testutil.MockGetVersionFromTablet(addrVersionMap) + SetVersionFunc(testutil.MockGetVersionFromTablet(addrVersionMap)) }, shouldErr: false, }, @@ -11247,7 +11250,7 @@ func TestValidateVersionKeyspace(t *testing.T) { "primary:0": "version1", "replica:0": "version2", } - getVersionFromTablet = testutil.MockGetVersionFromTablet(addrVersionMap) + SetVersionFunc(testutil.MockGetVersionFromTablet(addrVersionMap)) }, shouldErr: false, }, @@ -11339,7 +11342,7 @@ func TestValidateVersionShard(t *testing.T) { "primary:0": "version1", "replica:0": "version1", } - getVersionFromTablet = testutil.MockGetVersionFromTablet(addrVersionMap) + SetVersionFunc(testutil.MockGetVersionFromTablet(addrVersionMap)) }, shouldErr: false, }, @@ -11357,7 +11360,7 @@ func TestValidateVersionShard(t *testing.T) { "primary:0": "version1", "replica:0": "version2", } - getVersionFromTablet = testutil.MockGetVersionFromTablet(addrVersionMap) + SetVersionFunc(testutil.MockGetVersionFromTablet(addrVersionMap)) }, shouldErr: false, }, @@ -11924,3 +11927,7 @@ func TestValidateShard(t *testing.T) { }) } } +func TestMain(m *testing.M) { + _flag.ParseFlagsForTest() + os.Exit(m.Run()) +} diff --git a/go/vt/vtexplain/vtexplain_test.go b/go/vt/vtexplain/vtexplain_test.go index 8145c59b44d..64cb39b54de 100644 --- a/go/vt/vtexplain/vtexplain_test.go +++ b/go/vt/vtexplain/vtexplain_test.go @@ -24,13 +24,16 @@ import ( "strings" "testing" + querypb "vitess.io/vitess/go/vt/proto/query" + + "vitess.io/vitess/go/vt/sidecardb" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv/tabletenvtest" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" "vitess.io/vitess/go/vt/key" - querypb "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/proto/topodata" "vitess.io/vitess/go/vt/topo" ) @@ -133,6 +136,10 @@ func runTestCase(testcase, mode string, opts *Options, topts *testopts, t *testi } func TestExplain(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + tabletenvtest.LoadTabletEnvFlags() type test struct { @@ -171,6 +178,10 @@ func TestExplain(t *testing.T) { } func TestErrors(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + vte := initTest(ModeMulti, defaultTestOpts(), &testopts{}, t) tests := []struct { @@ -208,6 +219,10 @@ func TestErrors(t *testing.T) { } func TestJSONOutput(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + vte := initTest(ModeMulti, defaultTestOpts(), &testopts{}, t) sql := "select 1 from user where id = 1" explains, err := vte.Run(sql) @@ -296,6 +311,10 @@ func testShardInfo(ks, start, end string, primaryServing bool, t *testing.T) *to } func TestUsingKeyspaceShardMap(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + tests := []struct { testcase string ShardRangeMap map[string]map[string]*topo.ShardInfo @@ -354,6 +373,7 @@ func TestInit(t *testing.T) { }` schema := "create table table_missing_primary_vindex (id int primary key)" _, err := Init(vschema, schema, "", defaultTestOpts()) + require.Error(t, err) require.Contains(t, err.Error(), "missing primary col vindex") } diff --git a/go/vt/vtexplain/vtexplain_vtgate.go b/go/vt/vtexplain/vtexplain_vtgate.go index 2a53d1f68ae..a4287377c4b 100644 --- a/go/vt/vtexplain/vtexplain_vtgate.go +++ b/go/vt/vtexplain/vtexplain_vtgate.go @@ -75,7 +75,7 @@ func (vte *VTExplain) initVtgateExecutor(vSchemaStr, ksShardMapStr string, opts vte.vtgateExecutor = vtgate.NewExecutor(context.Background(), vte.explainTopo, vtexplainCell, resolver, opts.Normalize, false, streamSize, cache.DefaultConfig, schemaTracker, false, opts.PlannerVersion) queryLogBufferSize := 10 - vtgate.QueryLogger = streamlog.New("VTGate", queryLogBufferSize) + vtgate.SetQueryLogger(streamlog.New("VTGate", queryLogBufferSize)) return nil } diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index ee94946e5c1..d7fb6b2983b 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -105,6 +105,7 @@ var _ queryservice.QueryService = (*explainTablet)(nil) func (vte *VTExplain) newTablet(opts *Options, t *topodatapb.Tablet) *explainTablet { db := fakesqldb.New(nil) + //db := fakesqldb.NewWithExpectedQueries(nil) config := tabletenv.NewCurrentConfig() config.TrackSchemaVersions = false @@ -502,7 +503,8 @@ func (t *explainTablet) HandleQuery(c *mysql.Conn, query string, callback func(* if result != nil { return callback(result) } - switch sqlparser.Preview(query) { + var tmp = sqlparser.Preview(query) + switch tmp { case sqlparser.StmtSelect: // Parse the select statement to figure out the table and columns // that were referenced so that the synthetic response has the @@ -692,6 +694,10 @@ func (t *explainTablet) HandleQuery(c *mysql.Conn, query string, callback func(* result = &sqltypes.Result{ RowsAffected: 1, } + case sqlparser.StmtUse: + result = &sqltypes.Result{} + case sqlparser.StmtDDL: + result = &sqltypes.Result{} default: return fmt.Errorf("unsupported query %s", query) } diff --git a/go/vt/vtexplain/vtexplain_vttablet_test.go b/go/vt/vtexplain/vtexplain_vttablet_test.go index 8fd28d07adf..639fe91b5da 100644 --- a/go/vt/vtexplain/vtexplain_vttablet_test.go +++ b/go/vt/vtexplain/vtexplain_vttablet_test.go @@ -23,12 +23,18 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "vitess.io/vitess/go/vt/sidecardb" + "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) func TestRun(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + testVSchema := ` { "test_keyspace": { @@ -78,6 +84,10 @@ create table t2 ( } func TestParseSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + testSchema := ` create table t1 ( id bigint(20) unsigned not null default 123, diff --git a/go/vt/vtgate/querylog.go b/go/vt/vtgate/querylog.go index 13b1d689642..33361e79421 100644 --- a/go/vt/vtgate/querylog.go +++ b/go/vt/vtgate/querylog.go @@ -18,6 +18,7 @@ package vtgate import ( "net/http" + "sync" "vitess.io/vitess/go/streamlog" ) @@ -33,11 +34,18 @@ var ( QueryzHandler = "/debug/queryz" // QueryLogger enables streaming logging of queries - QueryLogger *streamlog.StreamLogger + QueryLogger *streamlog.StreamLogger + queryLoggerMu sync.Mutex ) +func SetQueryLogger(logger *streamlog.StreamLogger) { + queryLoggerMu.Lock() + defer queryLoggerMu.Unlock() + QueryLogger = logger +} + func initQueryLogger(vtg *VTGate) error { - QueryLogger = streamlog.New("VTGate", queryLogBufferSize) + SetQueryLogger(streamlog.New("VTGate", queryLogBufferSize)) QueryLogger.ServeLogs(QueryLogHandler, streamlog.GetFormatter(QueryLogger)) http.HandleFunc(QueryLogzHandler, func(w http.ResponseWriter, r *http.Request) { diff --git a/go/vt/vtgate/vschemaacl/vschemaacl.go b/go/vt/vtgate/vschemaacl/vschemaacl.go index 83837245a4c..5345d1437fc 100644 --- a/go/vt/vtgate/vschemaacl/vschemaacl.go +++ b/go/vt/vtgate/vschemaacl/vschemaacl.go @@ -18,6 +18,7 @@ package vschemaacl import ( "strings" + "sync" "github.com/spf13/pflag" @@ -35,6 +36,8 @@ var ( // ddlACL contains a set of allowed usernames acl map[string]struct{} + + initMu sync.Mutex ) // RegisterSchemaACLFlags installs log flags on the given FlagSet. @@ -54,6 +57,8 @@ func init() { // Init parses the users option and sets allowAll / acl accordingly func Init() { + initMu.Lock() + defer initMu.Unlock() acl = make(map[string]struct{}) allowAll = false diff --git a/go/vt/vttablet/endtoend/main_test.go b/go/vt/vttablet/endtoend/main_test.go index a809e7e42ae..4d9f5002635 100644 --- a/go/vt/vttablet/endtoend/main_test.go +++ b/go/vt/vttablet/endtoend/main_test.go @@ -75,7 +75,7 @@ func TestMain(m *testing.M) { fmt.Fprintf(os.Stderr, "could not launch mysql: %v\n", err) return 1 } - err := cluster.Execute(procSQL, "vttest") + err := cluster.ExecuteWithSuperReadOnly(procSQL, "vttest") if err != nil { fmt.Fprintf(os.Stderr, "%v", err) return 1 @@ -96,6 +96,7 @@ func TestMain(m *testing.M) { fmt.Fprintf(os.Stderr, "%v", err) return 1 } + cluster.UnsetReadOnly("") return m.Run() }() os.Exit(exitCode) diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index 181dce93c3c..c12a381efc3 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -159,8 +159,6 @@ func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.L // Try to restore. Depending on the reason for failure, we may be ok. // If we're not ok, return an error and the tm will log.Fatalf, // causing the process to be restarted and the restore retried. - // Record local metadata values based on the original type. - localMetadata := tm.getLocalMetadataValues(originalType) keyspace := tablet.Keyspace keyspaceInfo, err := tm.TopoServer.GetKeyspace(ctx, keyspace) @@ -184,7 +182,6 @@ func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.L Logger: logger, Concurrency: restoreConcurrency, HookExtraEnv: tm.hookExtraEnv(), - LocalMetadata: localMetadata, DeleteBeforeRestore: deleteBeforeRestore, DbName: topoproto.TabletDbName(tablet), Keyspace: keyspace, @@ -209,11 +206,7 @@ func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.L } if !ok { params.Logger.Infof("Attempting to restore, but mysqld already contains data. Assuming vttablet was just restarted.") - // (NOTE:@ajm188) the legacy behavior is to always populate the metadata - // tables in this branch. Since tm.MetadataManager could be nil, we - // create a new instance for use here. - metadataManager := &mysqlctl.MetadataManager{} - return metadataManager.PopulateMetadataTables(params.Mysqld, params.LocalMetadata, params.DbName) + return nil //todo: is this ok? } // We should not become primary after restore, because that would incorrectly // start a new primary term, and it's likely our data dir will be out of date. @@ -308,7 +301,7 @@ func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.L params.Logger.Infof("Restore: will set tablet type to DRAINED as this is a point in time recovery") originalType = topodatapb.TabletType_DRAINED } - params.Logger.Infof("Restore: changing tablet type to %v", originalType) + params.Logger.Infof("Restore: changing tablet type to %v for %s", originalType, tm.tabletAlias.String()) // Change type back to original type if we're ok to serve. return tm.tmState.ChangeTabletType(ctx, originalType, DBActionNone) } diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index fcbfd3e974f..9768504ead4 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -38,7 +38,7 @@ import ( topodatapb "vitess.io/vitess/go/vt/proto/topodata" ) -var setSuperReadOnly bool +var setSuperReadOnly = true var disableReplicationManager bool func registerReplicationFlags(fs *pflag.FlagSet) { @@ -304,7 +304,9 @@ func (tm *TabletManager) ResetReplication(ctx context.Context) error { // InitPrimary enables writes and returns the replication position. func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string, error) { - log.Infof("InitPrimary") + log.Infof("InitPrimary with semiSync as %t", semiSync) + //time.Sleep(10 * time.Second) + //tmpCtx := context.TODO() if err := tm.lock(ctx); err != nil { return "", err } @@ -326,17 +328,18 @@ func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string // we need to insert something in the binlogs, so we can get the // current position. Let's just use the mysqlctl.CreateReparentJournal commands. - cmds := mysqlctl.CreateReparentJournal() + cmds := mysqlctl.CreateDummyDatabase() if err := tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds); err != nil { return "", err } // Execute ALTER statement on reparent_journal table and ignore errors - cmds = mysqlctl.AlterReparentJournal() - _ = tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds) + //cmds = mysqlctl.AlterReparentJournal() + //_ = tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds) // get the current replication position pos, err := tm.MysqlDaemon.PrimaryPosition() + log.Infof("current primary position is %s", mysql.EncodePosition(pos)) if err != nil { return "", err } @@ -348,7 +351,14 @@ func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string return "", err } - // Enforce semi-sync after changing the tablet)type to PRIMARY. Otherwise, the + // get the current replication position + /*pos, err := tm.MysqlDaemon.PrimaryPosition() + log.Infof("current primary position is %s", mysql.EncodePosition(pos)) + if err != nil { + return "", err + }*/ + + // Enforce semi-sync after changing the tablet-type to PRIMARY. Otherwise, the // primary will hang while trying to create the database. if err := tm.fixSemiSync(topodatapb.TabletType_PRIMARY, convertBoolToSemiSyncAction(semiSync)); err != nil { return "", err @@ -359,21 +369,22 @@ func (tm *TabletManager) InitPrimary(ctx context.Context, semiSync bool) (string // PopulateReparentJournal adds an entry into the reparent_journal table. func (tm *TabletManager) PopulateReparentJournal(ctx context.Context, timeCreatedNS int64, actionName string, primaryAlias *topodatapb.TabletAlias, position string) error { - log.Infof("PopulateReparentJournal: action: %v parent: %v position: %v", actionName, primaryAlias, position) + log.Infof("PopulateReparentJournal: action: %v parent: %v position: %v timeCreatedNS: %d actionName: %s primaryAlias: %s", + actionName, primaryAlias, position, timeCreatedNS, actionName, primaryAlias) pos, err := mysql.DecodePosition(position) if err != nil { return err } - cmds := mysqlctl.CreateReparentJournal() + /*cmds := mysqlctl.CreateReparentJournal() if err := tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds); err != nil { return err } // Execute ALTER statement on reparent_journal table and ignore errors cmds = mysqlctl.AlterReparentJournal() - _ = tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds) + _ = tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds)*/ - cmds = []string{mysqlctl.PopulateReparentJournal(timeCreatedNS, actionName, topoproto.TabletAliasString(primaryAlias), pos)} + cmds := []string{mysqlctl.PopulateReparentJournal(timeCreatedNS, actionName, topoproto.TabletAliasString(primaryAlias), pos)} return tm.MysqlDaemon.ExecuteSuperQueryList(ctx, cmds) } @@ -381,7 +392,7 @@ func (tm *TabletManager) PopulateReparentJournal(ctx context.Context, timeCreate // InitReplica sets replication primary and position, and waits for the // reparent_journal table entry up to context timeout func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.TabletAlias, position string, timeCreatedNS int64, semiSync bool) error { - log.Infof("InitReplica: parent: %v position: %v", parent, position) + log.Infof("InitReplica: parent: %v position: %v timeCreatedNS: %d semisync: %t", parent, position, timeCreatedNS, semiSync) if err := tm.lock(ctx); err != nil { return err } @@ -391,6 +402,7 @@ func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.Tab // is used on the old primary when using InitShardPrimary with // -force, and the new primary is different from the old primary. if tm.Tablet().Type == topodatapb.TabletType_PRIMARY { + log.Infof("InitReplica is for primary ...") if err := tm.changeTypeLocked(ctx, topodatapb.TabletType_REPLICA, DBActionNone, convertBoolToSemiSyncAction(semiSync)); err != nil { return err } @@ -400,11 +412,12 @@ func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.Tab if err != nil { return err } + log.Infof("decoding position %s", pos.String()) ti, err := tm.TopoServer.GetTablet(ctx, parent) if err != nil { return err } - + log.Infof("setReplicationStopped") tm.replManager.setReplicationStopped(false) // If using semi-sync, we need to enable it before connecting to primary. @@ -418,13 +431,16 @@ func (tm *TabletManager) InitReplica(ctx context.Context, parent *topodatapb.Tab return err } + log.Infof("SetReplicationPosition to %s", position) if err := tm.MysqlDaemon.SetReplicationPosition(ctx, pos); err != nil { return err } - if err := tm.MysqlDaemon.SetReplicationSource(ctx, ti.Tablet.MysqlHostname, int(ti.Tablet.MysqlPort), false /* stopReplicationBefore */, true /* stopReplicationAfter */); err != nil { + log.Infof("SetReplicationSource to %s", ti.Tablet.Alias.String()) + if err := tm.MysqlDaemon.SetReplicationSource(ctx, ti.Tablet.MysqlHostname, int(ti.Tablet.MysqlPort), false /* stopReplicationBefore */, true /* startReplicationAfter */); err != nil { return err } + log.Infof("WaitForReparentJournal to %s", position) // wait until we get the replicated row, or our context times out return tm.MysqlDaemon.WaitForReparentJournal(ctx, timeCreatedNS) } @@ -512,6 +528,7 @@ func (tm *TabletManager) demotePrimary(ctx context.Context, revertPartialFailure } defer func() { if finalErr != nil && revertPartialFailure && !wasReadOnly { + log.Info(">>>>> setting readonly to false...") // setting read_only OFF will also set super_read_only OFF if it was set if err := tm.MysqlDaemon.SetReadOnly(false); err != nil { log.Warningf("SetReadOnly(false) failed during revert: %v", err) @@ -607,7 +624,7 @@ func (tm *TabletManager) ResetReplicationParameters(ctx context.Context) error { // SetReplicationSource sets replication primary, and waits for the // reparent_journal table entry up to context timeout func (tm *TabletManager) SetReplicationSource(ctx context.Context, parentAlias *topodatapb.TabletAlias, timeCreatedNS int64, waitPosition string, forceStartReplication bool, semiSync bool) error { - log.Infof("SetReplicationSource: parent: %v position: %v force: %v semiSync: %v", parentAlias, waitPosition, forceStartReplication, semiSync) + log.Infof("SetReplicationSource: parent: %v position: %s force: %v semiSync: %v timeCreatedNS: %d", parentAlias, waitPosition, forceStartReplication, semiSync, timeCreatedNS) if err := tm.lock(ctx); err != nil { return err } @@ -737,6 +754,7 @@ func (tm *TabletManager) setReplicationSourceLocked(ctx context.Context, parentA // GTID-based replication position or a Vitess reparent journal entry, // or both. if shouldbeReplicating { + log.Infof("should be replicating %s %d", waitPosition, timeCreatedNS) if waitPosition != "" { pos, err := mysql.DecodePosition(waitPosition) if err != nil { diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 4e9cdce7e2f..ffedc38b716 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -84,8 +84,7 @@ var ( skipBuildInfoTags = "/.*/" initTags flagutil.StringMapValue - initPopulateMetadata bool - initTimeout = 1 * time.Minute + initTimeout = 1 * time.Minute ) func registerInitFlags(fs *pflag.FlagSet) { @@ -96,8 +95,6 @@ func registerInitFlags(fs *pflag.FlagSet) { fs.StringVar(&initDbNameOverride, "init_db_name_override", initDbNameOverride, "(init parameter) override the name of the db used by vttablet. Without this flag, the db name defaults to vt_") fs.StringVar(&skipBuildInfoTags, "vttablet_skip_buildinfo_tags", skipBuildInfoTags, "comma-separated list of buildinfo tags to skip from merging with --init_tags. each tag is either an exact match or a regular expression of the form '/regexp/'.") fs.Var(&initTags, "init_tags", "(init parameter) comma separated list of key:value pairs used to tag the tablet") - - fs.BoolVar(&initPopulateMetadata, "init_populate_metadata", initPopulateMetadata, "(init parameter) populate metadata tables even if restore_from_backup is disabled. If restore_from_backup is enabled, metadata tables are always populated regardless of this flag.") fs.DurationVar(&initTimeout, "init_timeout", initTimeout, "(init parameter) timeout to use for the init phase.") } @@ -150,11 +147,6 @@ type TabletManager struct { VREngine *vreplication.Engine VDiffEngine *vdiff.Engine - // MetadataManager manages the local metadata tables for a tablet. It - // exists, and is exported, to support swapping a nil pointer in test code, - // in which case metadata creation/population is skipped. - MetadataManager *mysqlctl.MetadataManager - // tmState manages the TabletManager state. tmState *tmState @@ -216,9 +208,9 @@ func BuildTabletFromInput(alias *topodatapb.TabletAlias, port, grpcPort int32, d if err != nil { return nil, err } - log.Infof("Using detected machine hostname: %v, to change this, fix your machine network configuration or override it with --tablet_hostname.", hostname) + log.Infof("Using detected machine hostname: %v, to change this, fix your machine network configuration or override it with --tablet_hostname. Tablet %s", hostname, alias.String()) } else { - log.Infof("Using hostname: %v from --tablet_hostname flag.", hostname) + log.Infof("Using hostname: %v from --tablet_hostname flag. Tablet %s", hostname, alias.String()) } if initKeyspace == "" || initShard == "" { @@ -343,6 +335,10 @@ func mergeTags(a, b map[string]string) map[string]string { // Start starts the TabletManager. func (tm *TabletManager) Start(tablet *topodatapb.Tablet, healthCheckInterval time.Duration) error { + defer func() { + log.Infof("TabletManager Start took ~%d ms", time.Since(servenv.GetInitStartTime()).Milliseconds()) + }() + log.Infof("TabletManager Start") tm.DBConfigs.DBName = topoproto.TabletDbName(tablet) tm.replManager = newReplManager(tm.BatchCtx, tm, healthCheckInterval) tm.tabletAlias = tablet.Alias @@ -408,12 +404,13 @@ func (tm *TabletManager) Start(tablet *topodatapb.Tablet, healthCheckInterval ti // of updating the tablet state and initializing replication. return nil } - + log.Infof("calling initializeReplication") // We should be re-read the tablet from tabletManager and use the type specified there. // We shouldn't use the base tablet type directly, since the type could have changed to PRIMARY // earlier in tm.checkPrimaryShip code. _, err = tm.initializeReplication(ctx, tm.Tablet().Type) tm.tmState.Open() + log.Infof("TabletManager End") return err } @@ -729,7 +726,6 @@ func (tm *TabletManager) initTablet(ctx context.Context) error { } func (tm *TabletManager) handleRestore(ctx context.Context) (bool, error) { - tablet := tm.Tablet() // Sanity check for inconsistent flags if tm.Cnf == nil && restoreFromBackup { return false, fmt.Errorf("you cannot enable --restore_from_backup without a my.cnf file") @@ -762,23 +758,6 @@ func (tm *TabletManager) handleRestore(ctx context.Context) (bool, error) { return true, nil } - // optionally populate metadata records - if initPopulateMetadata { - localMetadata := tm.getLocalMetadataValues(tablet.Type) - if tm.Cnf != nil { // we are managing mysqld - // we'll use batchCtx here because we are still initializing and can't proceed unless this succeeds - if err := tm.MysqlDaemon.Wait(ctx, tm.Cnf); err != nil { - return false, err - } - } - - if tm.MetadataManager != nil { - err := tm.MetadataManager.PopulateMetadataTables(tm.MysqlDaemon, localMetadata, topoproto.TabletDbName(tablet)) - if err != nil { - return false, vterrors.Wrap(err, "failed to --init_populate_metadata") - } - } - } return false, nil } diff --git a/go/vt/vttablet/tabletmanager/tm_state.go b/go/vt/vttablet/tabletmanager/tm_state.go index da43cbf9a25..d269bea2831 100644 --- a/go/vt/vttablet/tabletmanager/tm_state.go +++ b/go/vt/vttablet/tabletmanager/tm_state.go @@ -68,17 +68,16 @@ type tmState struct { // Because mu can be held for long, we publish the current state // of these variables into displayState, which can be accessed // more freely even while tmState is busy transitioning. - mu sync.Mutex - isOpen bool - isOpening bool - isResharding bool - isInSrvKeyspace bool - isShardServing map[topodatapb.TabletType]bool - tabletControls map[topodatapb.TabletType]bool - deniedTables map[topodatapb.TabletType][]string - tablet *topodatapb.Tablet - isPublishing bool - hasCreatedMetadataTables bool + mu sync.Mutex + isOpen bool + isOpening bool + isResharding bool + isInSrvKeyspace bool + isShardServing map[topodatapb.TabletType]bool + tabletControls map[topodatapb.TabletType]bool + deniedTables map[topodatapb.TabletType][]string + tablet *topodatapb.Tablet + isPublishing bool // displayState contains the current snapshot of the internal state // and has its own mutex. @@ -99,6 +98,7 @@ func newTMState(tm *TabletManager, tablet *topodatapb.Tablet) *tmState { } func (ts *tmState) Open() { + log.Infof("Calling taState.Open()") ts.mu.Lock() defer ts.mu.Unlock() if ts.isOpen { @@ -182,7 +182,7 @@ func (ts *tmState) RefreshFromTopoInfo(ctx context.Context, shardInfo *topo.Shar func (ts *tmState) ChangeTabletType(ctx context.Context, tabletType topodatapb.TabletType, action DBAction) error { ts.mu.Lock() defer ts.mu.Unlock() - log.Infof("Changing Tablet Type: %v", tabletType) + log.Infof("Changing Tablet Type: %v for %s", tabletType, ts.tablet.Alias.String()) if tabletType == topodatapb.TabletType_PRIMARY { PrimaryTermStartTime := logutil.TimeToProto(time.Now()) @@ -254,6 +254,7 @@ func (ts *tmState) UpdateTablet(update func(tablet *topodatapb.Tablet)) { } func (ts *tmState) updateLocked(ctx context.Context) error { + log.Infof("Calling taState.updateLocked()") span, ctx := trace.NewSpan(ctx, "tmState.update") defer span.Finish() ts.publishForDisplay() @@ -336,33 +337,6 @@ func (ts *tmState) updateLocked(ctx context.Context) error { return returnErr } -func (ts *tmState) populateLocalMetadataLocked() { - if ts.tm.MetadataManager == nil { - return - } - - if ts.isOpening && !initPopulateMetadata { - return - } - - localMetadata := ts.tm.getLocalMetadataValues(ts.tablet.Type) - dbName := topoproto.TabletDbName(ts.tablet) - - if !ts.hasCreatedMetadataTables { - if err := ts.tm.MetadataManager.PopulateMetadataTables(ts.tm.MysqlDaemon, localMetadata, dbName); err != nil { - log.Errorf("PopulateMetadataTables(%v) failed: %v", localMetadata, err) - return - } - - ts.hasCreatedMetadataTables = true - return - } - - if err := ts.tm.MetadataManager.UpsertLocalMetadata(ts.tm.MysqlDaemon, localMetadata, dbName); err != nil { - log.Errorf("UpsertMetadataTables(%v) failed: %v", localMetadata, err) - } -} - func (ts *tmState) canServe(tabletType topodatapb.TabletType) string { if !topo.IsRunningQueryService(tabletType) { return fmt.Sprintf("not a serving tablet type(%v)", tabletType) diff --git a/go/vt/vttablet/tabletmanager/vreplication/engine_test.go b/go/vt/vttablet/tabletmanager/vreplication/engine_test.go index 97c7c4a6267..3079d044465 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/engine_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/engine_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + "vitess.io/vitess/go/vt/withddl" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -468,6 +470,7 @@ func TestWaitForPosCancel(t *testing.T) { } func TestCreateDBAndTable(t *testing.T) { + withddl.EnableWithDDLForTests = true defer func() { globalStats = &vrStats{} }() defer deleteTablet(addTablet(100)) diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go index e55341d8b65..98eb8e702cc 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go @@ -27,6 +27,8 @@ import ( "testing" "time" + "vitess.io/vitess/go/vt/withddl" + "github.com/spyzhov/ajson" "github.com/stretchr/testify/require" @@ -141,7 +143,7 @@ func TestHeartbeatFrequencyFlag(t *testing.T) { func TestVReplicationTimeUpdated(t *testing.T) { ctx := context.Background() defer deleteTablet(addTablet(100)) - + withddl.EnableWithDDLForTests = true execStatements(t, []string{ "create table t1(id int, val varbinary(128), primary key(id))", fmt.Sprintf("create table %s.t1(id int, val varbinary(128), primary key(id))", vrepldb), diff --git a/go/vt/vttablet/tabletserver/health_streamer.go b/go/vt/vttablet/tabletserver/health_streamer.go index ea9701faf40..a7c52bd07fd 100644 --- a/go/vt/vttablet/tabletserver/health_streamer.go +++ b/go/vt/vttablet/tabletserver/health_streamer.go @@ -23,6 +23,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/sidecardb" + "github.com/spf13/pflag" "vitess.io/vitess/go/vt/servenv" @@ -405,6 +407,10 @@ func (hs *healthStreamer) reload() error { } func (hs *healthStreamer) InitSchemaLocked(conn *connpool.DBConn) (bool, error) { + + if sidecardb.GetInitVTSchemaFlag() { // _vt schema should be the desired one by now + return true, nil + } for _, query := range mysql.VTDatabaseInit { _, err := conn.Exec(hs.ctx, query, 1, false) if err != nil { diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index 8833588352f..b6676de615b 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -1548,6 +1548,7 @@ func initQueryExecutorTestDB(db *fakesqldb.DB) { "varchar|int64"), "Innodb_rows_read|0", )) + db.AddVTSchemaInitQueries() } func getTestTableFields() []*querypb.Field { diff --git a/go/vt/vttablet/tabletserver/repltracker/writer_test.go b/go/vt/vttablet/tabletserver/repltracker/writer_test.go index f678381ec2b..d00d5af5ba8 100644 --- a/go/vt/vttablet/tabletserver/repltracker/writer_test.go +++ b/go/vt/vttablet/tabletserver/repltracker/writer_test.go @@ -21,6 +21,8 @@ import ( "testing" "time" + "vitess.io/vitess/go/vt/sidecardb" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -40,12 +42,15 @@ var ( ) func TestCreateSchema(t *testing.T) { + oldInitVTSchemaOnTabletInit := sidecardb.GetInitVTSchemaFlag() + sidecardb.SetInitVTSchemaFlag(false) + defer func() { sidecardb.SetInitVTSchemaFlag(oldInitVTSchemaOnTabletInit) }() + db := fakesqldb.New(t) defer db.Close() tw := newTestWriter(db, mockNowFunc) defer tw.Close() writes.Reset() - db.OrderMatters() upsert := fmt.Sprintf("INSERT INTO %s.heartbeat (ts, tabletUid, keyspaceShard) VALUES (%d, %d, '%s') ON DUPLICATE KEY UPDATE ts=VALUES(ts), tabletUid=VALUES(tabletUid)", "_vt", now.UnixNano(), tw.tabletAlias.Uid, tw.keyspaceShard) diff --git a/go/vt/vttablet/tabletserver/schema/engine.go b/go/vt/vttablet/tabletserver/schema/engine.go index d4e1ab1f951..b0fe3d1be8d 100644 --- a/go/vt/vttablet/tabletserver/schema/engine.go +++ b/go/vt/vttablet/tabletserver/schema/engine.go @@ -21,9 +21,13 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "sync" "time" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/sidecardb" + "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/dbconnpool" "vitess.io/vitess/go/vt/schema" @@ -124,24 +128,98 @@ func (se *Engine) InitDBConfig(cp dbconfigs.Connector) { se.cp = cp } +func syncVTDatabase(ctx context.Context, conn *dbconnpool.DBConnection, dbaConn *dbconnpool.DBConnection, isPrimary bool) error { + log.Infof("In syncVTDatabase") + defer func(start time.Time) { + // we will leave this log + log.Infof("syncVTDatabase took %d ms", time.Since(start).Milliseconds()) + }(time.Now()) + var exec sidecardb.Exec = func(ctx context.Context, query string, maxRows int, wantFields bool, useVT bool) (*sqltypes.Result, error) { + if useVT { + _, err := conn.ExecuteFetch(sidecardb.UseVTDatabaseQuery, maxRows, wantFields) + if err != nil { + return nil, err + } + } + return conn.ExecuteFetch(query, maxRows, wantFields) + } + var rsroHook sidecardb.ReSetSuperReadOnlyHook = func(ctx context.Context) (err error) { + log.Infof("resetting hook for super read only...") + if _, err := dbaConn.ExecuteFetch("SET GLOBAL super_read_only='ON'", 1, false); err != nil { + log.Infof("Not able to set super_read_only user... This can cause errant GTIDs in future.") + return err + } + return nil + } + var sroHook sidecardb.SetSuperReadOnlyHook = func(ctx context.Context) (needsReset bool, err error) { + if !dbaConn.IsMariaDB() { + if err := dbaConn.WriteComQuery("SELECT @@global.super_read_only"); err != nil { + log.Infof("Not able to select super_read_only.") + return false, err + } + res, _, _, err := dbaConn.ReadQueryResult(1, false) + if err == nil && len(res.Rows) == 1 { + sro := res.Rows[0][0].ToString() + var needsReset = false + if sro == "1" || sro == "ON" { + needsReset = true + } + needsReset = needsReset && !isPrimary + if _, err = dbaConn.ExecuteFetch("SET GLOBAL read_only='OFF'", 1, false); err != nil { + return false, err + } + return needsReset, nil + } + } + return false, nil + } + log.Infof("before sidecardb.Init") + if err := sidecardb.Init(ctx, exec, sroHook, rsroHook); err != nil { + log.Error(err) + return err + } + log.Infof("syncVTDatabase done") + return nil +} + // EnsureConnectionAndDB ensures that we can connect to mysql. // If tablet type is primary and there is no db, then the database is created. // This function can be called before opening the Engine. func (se *Engine) EnsureConnectionAndDB(tabletType topodatapb.TabletType) error { + log.Infof("inside EnsureConnectionAndDB with TabletType %v", tabletType) ctx := tabletenv.LocalContext() - conn, err := dbconnpool.NewDBConnection(ctx, se.env.Config().DB.AppWithDB()) + conn, err := dbconnpool.NewDBConnection(ctx, se.env.Config().DB.AllPrivsWithDB()) + if err != nil { + log.Infof("error inside EnsureConnectionAndDB %v", err) + } if err == nil { - conn.Close() + log.Infof("inside EnsureConnectionAndDB with TabletType %v...", tabletType) se.dbCreationFailed = false + dbaConn, err := dbconnpool.NewDBConnection(ctx, se.env.Config().DB.DbaConnector()) + if err != nil { + log.Info("Not able to get connection with all privileges...") + return err + } + defer dbaConn.Close() + if tabletType == topodatapb.TabletType_PRIMARY { + // FIXME: without the --read-only check below many tests fail. Need to verify if the check needs to + // be permanent or if the tests need to change + if err := syncVTDatabase(ctx, conn, dbaConn, true); err != nil && !strings.Contains(err.Error(), "--read-only") { + return err + } + } + conn.Close() return nil } if tabletType != topodatapb.TabletType_PRIMARY { + log.Info("returning error...") return err } if merr, isSQLErr := err.(*mysql.SQLError); !isSQLErr || merr.Num != mysql.ERBadDb { + log.Info("returning sql error...") return err } - + log.Info("It is primary...") // We are primary and db is not found. Let's create it. // We use allprivs instead of DBA because we want db create to fail if we're read-only. conn, err = dbconnpool.NewDBConnection(ctx, se.env.Config().DB.AllPrivsConnector()) @@ -149,7 +227,17 @@ func (se *Engine) EnsureConnectionAndDB(tabletType topodatapb.TabletType) error return err } defer conn.Close() - + dbaConn, err := dbconnpool.NewDBConnection(ctx, se.env.Config().DB.DbaConnector()) + if err != nil { + log.Info("Not able to get connection with all privileges...") + return err + } + defer dbaConn.Close() + _, err = dbaConn.ExecuteFetch("SET GLOBAL read_only='OFF'", 1, false) + if err != nil { + log.Errorf("Error trying to switch off read-only for DB.") + return err + } dbname := se.env.Config().DB.DBName _, err = conn.ExecuteFetch(fmt.Sprintf("create database if not exists `%s`", dbname), 1, false) if err != nil { @@ -160,9 +248,12 @@ func (se *Engine) EnsureConnectionAndDB(tabletType topodatapb.TabletType) error } return err } - log.Infof("db %v created", dbname) se.dbCreationFailed = false + // creates _vt schema, the first time the database is created + if err := syncVTDatabase(ctx, conn, dbaConn, tabletType == topodatapb.TabletType_PRIMARY); err != nil { + return err + } return nil } diff --git a/go/vt/vttablet/tabletserver/state_manager.go b/go/vt/vttablet/tabletserver/state_manager.go index 60d3aaa3792..625d2188272 100644 --- a/go/vt/vttablet/tabletserver/state_manager.go +++ b/go/vt/vttablet/tabletserver/state_manager.go @@ -22,6 +22,8 @@ import ( "sync" "time" + "vitess.io/vitess/go/vt/servenv" + "google.golang.org/protobuf/proto" "vitess.io/vitess/go/sync2" @@ -598,6 +600,9 @@ func (sm *stateManager) setTimeBomb() chan struct{} { // setState changes the state and logs the event. func (sm *stateManager) setState(tabletType topodatapb.TabletType, state servingState) { + defer func() { + log.Infof("Tablet Init took %d ms", time.Since(servenv.GetInitStartTime()).Milliseconds()) + }() sm.mu.Lock() defer sm.mu.Unlock() if tabletType == topodatapb.TabletType_UNKNOWN { diff --git a/go/vt/vttablet/tabletserver/tabletserver_test.go b/go/vt/vttablet/tabletserver/tabletserver_test.go index 61f9c411000..05f01fd5150 100644 --- a/go/vt/vttablet/tabletserver/tabletserver_test.go +++ b/go/vt/vttablet/tabletserver/tabletserver_test.go @@ -58,6 +58,7 @@ import ( func TestTabletServerHealthz(t *testing.T) { db, tsv := setupTabletServerTest(t, "") + defer tsv.StopService() defer db.Close() @@ -2232,6 +2233,7 @@ func setupTabletServerTest(t *testing.T, keyspaceName string) (*fakesqldb.DB, *T func setupTabletServerTestCustom(t *testing.T, config *tabletenv.TabletConfig, keyspaceName string) (*fakesqldb.DB, *TabletServer) { db := setupFakeDB(t) + db.AddVTSchemaInitQueries() tsv := NewTabletServer("TabletServerTest", config, memorytopo.NewServer(""), &topodatapb.TabletAlias{}) require.Equal(t, StateNotConnected, tsv.sm.State()) dbcfgs := newDBConfigs(db) diff --git a/go/vt/vttablet/tabletserver/tx_engine.go b/go/vt/vttablet/tabletserver/tx_engine.go index 8d425003ac3..4e1ceeeb1eb 100644 --- a/go/vt/vttablet/tabletserver/tx_engine.go +++ b/go/vt/vttablet/tabletserver/tx_engine.go @@ -192,7 +192,7 @@ func (te *TxEngine) transition(state txEngineState) { func (te *TxEngine) Close() { log.Infof("TxEngine - started Close. Acquiring stateLock lock") te.stateLock.Lock() - log.Infof("TxEngine - arcquired stateLock") + log.Infof("TxEngine - acquired stateLock") defer func() { te.state = NotServing te.stateLock.Unlock() diff --git a/go/vt/vttablet/tabletserver/vstreamer/main_flaky_test.go b/go/vt/vttablet/tabletserver/vstreamer/main_flaky_test.go index 8d2afeaaaa4..d476868cff2 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/main_flaky_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/main_flaky_test.go @@ -40,7 +40,6 @@ var ( func TestMain(m *testing.M) { _flag.ParseFlagsForTest() ignoreKeyspaceShardInFieldAndRowEvents = true - exitCode := func() int { var err error env, err = testenv.Init() diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_flaky_test.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_flaky_test.go index 1eaec093040..98db6f49f17 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_flaky_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_flaky_test.go @@ -268,6 +268,7 @@ func TestVersion(t *testing.T) { defer engine.Close() execStatements(t, []string{ + "create database if not exists _vt", "create table _vt.schema_version(id int, pos varbinary(10000), time_updated bigint(20), ddl varchar(10000), schemax blob, primary key(id))", }) defer execStatements(t, []string{ diff --git a/go/vt/vttest/environment.go b/go/vt/vttest/environment.go index f58d9d48944..89fd44bf434 100644 --- a/go/vt/vttest/environment.go +++ b/go/vt/vttest/environment.go @@ -146,7 +146,7 @@ func (env *LocalTestEnv) BinaryPath(binary string) string { func (env *LocalTestEnv) MySQLManager(mycnf []string, snapshot string) (MySQLManager, error) { return &Mysqlctl{ Binary: env.BinaryPath("mysqlctl"), - InitFile: path.Join(os.Getenv("VTROOT"), "config/init_db.sql"), + InitFile: path.Join(os.Getenv("VTROOT"), "config/init_testserver_db.sql"), Directory: env.TmpPath, Port: env.PortForProtocol("mysql", ""), MyCnf: append(env.DefaultMyCnf, mycnf...), diff --git a/go/vt/vttest/local_cluster.go b/go/vt/vttest/local_cluster.go index ce8d16ec075..4400b8c1e40 100644 --- a/go/vt/vttest/local_cluster.go +++ b/go/vt/vttest/local_cluster.go @@ -481,7 +481,7 @@ func (db *LocalCluster) loadSchema(shouldRunDatabaseMigrations bool) error { } for _, dbname := range db.shardNames(kpb) { - if err := db.Execute(cmds, dbname); err != nil { + if err := db.ExecuteWithSuperReadOnly(cmds, dbname); err != nil { return err } } @@ -509,7 +509,7 @@ func (db *LocalCluster) createDatabases() error { sql = append(sql, fmt.Sprintf("create database `%s`", dbname)) } } - return db.Execute(sql, "") + return db.ExecuteWithSuperReadOnly(sql, "") } // Execute runs a series of SQL statements on the MySQL instance backing @@ -540,6 +540,34 @@ func (db *LocalCluster) Execute(sql []string, dbname string) error { return err } +// ExecuteWithSuperReadOnly runs a series of SQL statements with super-read-only permission +// on the MySQL instance backing this local cluster. This is provided for debug/introspection purposes; +// normal cluster access should be performed through the Vitess GRPC interface. +func (db *LocalCluster) ExecuteWithSuperReadOnly(sql []string, dbname string) error { + params := db.mysql.Params(dbname) + conn, err := mysql.Connect(context.Background(), ¶ms) + if err != nil { + return err + } + defer conn.Close() + + _, err = conn.ExecuteFetch("START TRANSACTION", 0, false) + if err != nil { + return err + } + + for _, cmd := range sql { + log.Infof("Execute(%s): \"%s\"", dbname, cmd) + _, err := conn.ExecuteFetchWithSuperReadOnlyHandling(cmd, 0, false) + if err != nil { + return err + } + } + + _, err = conn.ExecuteFetch("COMMIT", 0, false) + return err +} + // Query runs a SQL query on the MySQL instance backing this local cluster and returns // its result. This is provided for debug/introspection purposes; // normal cluster access should be performed through the Vitess GRPC interface. @@ -696,3 +724,15 @@ func LoadSQLFile(filename, sourceroot string) ([]string, error) { return sql, nil } + +func (db *LocalCluster) UnsetReadOnly(dbname string) error { + params := db.mysql.Params(dbname) + conn, err := mysql.Connect(context.Background(), ¶ms) + if err != nil { + return err + } + defer conn.Close() + + _, err = conn.ExecuteUnSetSuperReadOnly() + return err +} diff --git a/go/vt/vttest/mysqlctl.go b/go/vt/vttest/mysqlctl.go index 8eaa8c65f61..2b33fc33e56 100644 --- a/go/vt/vttest/mysqlctl.go +++ b/go/vt/vttest/mysqlctl.go @@ -25,6 +25,8 @@ import ( "strings" "time" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/vt/mysqlctl" ) @@ -97,7 +99,7 @@ func (ctl *Mysqlctl) Start() error { cmd.Env = append(cmd.Env, os.Environ()...) cmd.Env = append(cmd.Env, ctl.Env...) cmd.Env = append(cmd.Env, fmt.Sprintf("EXTRA_MY_CNF=%s", myCnf)) - + log.Infof("cmd.Env %+v", cmd.Env) _, err := cmd.Output() return err } diff --git a/go/vt/withddl/withddl.go b/go/vt/withddl/withddl.go index 15c78509777..18b69aa68ea 100644 --- a/go/vt/withddl/withddl.go +++ b/go/vt/withddl/withddl.go @@ -23,12 +23,16 @@ import ( "context" "fmt" + "vitess.io/vitess/go/vt/sidecardb" + "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/sqlparser" ) +var EnableWithDDLForTests bool + const QueryToTriggerWithDDL = "SELECT _vt_no_such_column__init_schema FROM _vt.vreplication LIMIT 1" // WithDDL allows you to execute statements against @@ -63,10 +67,17 @@ func (wd *WithDDL) DDLs() []string { // func(query string, maxrows int, wantfields bool) (*sqltypes.Result, error) // func(ctx context.Context, query string, maxrows int, wantfields bool) (*sqltypes.Result, error) func (wd *WithDDL) Exec(ctx context.Context, query string, fQuery any, fDDL any) (*sqltypes.Result, error) { + execQuery, err := wd.unify(ctx, fQuery) if err != nil { return nil, err } + + // if we are using the new schema init logic AND we are not running withddl unit tests + if sidecardb.GetInitVTSchemaFlag() && !EnableWithDDLForTests { + return execQuery(query) + } + execDDL, err := wd.unify(ctx, fDDL) if err != nil { return nil, err @@ -75,6 +86,7 @@ func (wd *WithDDL) Exec(ctx context.Context, query string, fQuery any, fDDL any) if err == nil { return qr, nil } + if !wd.isSchemaError(err) { return nil, err } diff --git a/go/vt/withddl/withddl_test.go b/go/vt/withddl/withddl_test.go index 6a36dd14992..2c343708f01 100644 --- a/go/vt/withddl/withddl_test.go +++ b/go/vt/withddl/withddl_test.go @@ -22,6 +22,8 @@ import ( "os" "testing" + "vitess.io/vitess/go/vt/sidecardb" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -40,6 +42,8 @@ func TestExec(t *testing.T) { conn, err := mysql.Connect(ctx, &connParams) require.NoError(t, err) defer conn.Close() + _, err = conn.ExecuteUnSetSuperReadOnly() + require.NoError(t, err) _, err = conn.ExecuteFetch("create database t", 10000, true) require.NoError(t, err) defer conn.ExecuteFetch("drop database t", 10000, true) // nolint:errcheck @@ -205,6 +209,8 @@ func TestExecIgnore(t *testing.T) { conn, err := mysql.Connect(ctx, &connParams) require.NoError(t, err) defer conn.Close() + _, err = conn.ExecuteUnSetSuperReadOnly() + require.NoError(t, err) _, err = conn.ExecuteFetch("create database t", 10000, true) require.NoError(t, err) defer conn.ExecuteFetch("drop database t", 10000, true) // nolint:errcheck @@ -237,6 +243,9 @@ func TestDifferentExecFunctions(t *testing.T) { conn, err := mysql.Connect(ctx, &connParams) require.NoError(t, err) defer conn.Close() + _, err = conn.ExecuteUnSetSuperReadOnly() + require.NoError(t, err) + defer conn.ExecuteFetch("drop database t", 10000, true) // nolint:errcheck execconn, err := mysql.Connect(ctx, &connParams) @@ -278,6 +287,10 @@ func TestMain(m *testing.M) { tabletenvtest.LoadTabletEnvFlags() tabletenv.Init() + if sidecardb.GetInitVTSchemaFlag() { + EnableWithDDLForTests = true + } + exitCode := func() int { // Launch MySQL. // We need a Keyspace in the topology, so the DbName is set. diff --git a/go/vt/wrangler/reparent.go b/go/vt/wrangler/reparent.go index bcf942fd6d4..b108ab35b81 100644 --- a/go/vt/wrangler/reparent.go +++ b/go/vt/wrangler/reparent.go @@ -114,7 +114,7 @@ func (wr *Wrangler) EmergencyReparentShard(ctx context.Context, keyspace, shard // and updates it's tablet record in the topo. Updating the shard record is handled // by the new primary tablet func (wr *Wrangler) TabletExternallyReparented(ctx context.Context, newPrimaryAlias *topodatapb.TabletAlias) error { - + log.Infof("enter wrangler.TabletExternallyReparented") tabletInfo, err := wr.ts.GetTablet(ctx, newPrimaryAlias) if err != nil { log.Warningf("TabletExternallyReparented: failed to read tablet record for %v: %v", newPrimaryAlias, err) @@ -165,5 +165,6 @@ func (wr *Wrangler) TabletExternallyReparented(ctx context.Context, newPrimaryAl } event.DispatchUpdate(ev, "finished") } + log.Infof("exit wrangler.TabletExternallyReparented") return nil } diff --git a/go/vt/wrangler/testlib/emergency_reparent_shard_test.go b/go/vt/wrangler/testlib/emergency_reparent_shard_test.go index 014029504a9..e7fa3159733 100644 --- a/go/vt/wrangler/testlib/emergency_reparent_shard_test.go +++ b/go/vt/wrangler/testlib/emergency_reparent_shard_test.go @@ -91,9 +91,6 @@ func TestEmergencyReparentShard(t *testing.T) { newPrimary.FakeMysqlDaemon.WaitPrimaryPositions = append(newPrimary.FakeMysqlDaemon.WaitPrimaryPositions, newPrimary.FakeMysqlDaemon.CurrentSourceFilePosition) newPrimary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ "STOP SLAVE IO_THREAD", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.FakeMysqlDaemon.PromoteResult = mysql.Position{ @@ -238,9 +235,6 @@ func TestEmergencyReparentShardPrimaryElectNotBest(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) diff --git a/go/vt/wrangler/testlib/planned_reparent_shard_test.go b/go/vt/wrangler/testlib/planned_reparent_shard_test.go index 50e27926cdd..391c4dcb46a 100644 --- a/go/vt/wrangler/testlib/planned_reparent_shard_test.go +++ b/go/vt/wrangler/testlib/planned_reparent_shard_test.go @@ -82,9 +82,6 @@ func TestPlannedReparentShardNoPrimaryProvided(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -201,9 +198,6 @@ func TestPlannedReparentShardNoError(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -326,12 +320,7 @@ func TestPlannedReparentInitialization(t *testing.T) { }, } newPrimary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", + "CREATE DATABASE IF NOT EXISTS _dummy", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -430,9 +419,6 @@ func TestPlannedReparentShardWaitForPositionFail(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -544,9 +530,6 @@ func TestPlannedReparentShardWaitForPositionTimeout(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -640,9 +623,6 @@ func TestPlannedReparentShardRelayLogError(t *testing.T) { }, } primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } primary.StartActionLoop(t, wr) @@ -721,9 +701,6 @@ func TestPlannedReparentShardRelayLogErrorStartReplication(t *testing.T) { }, } primary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } primary.StartActionLoop(t, wr) @@ -822,9 +799,6 @@ func TestPlannedReparentShardPromoteReplicaFail(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } newPrimary.StartActionLoop(t, wr) @@ -901,9 +875,6 @@ func TestPlannedReparentShardPromoteReplicaFail(t *testing.T) { "RESET SLAVE ALL", "FAKE SET MASTER", "START SLAVE", - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } oldPrimary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ @@ -959,9 +930,6 @@ func TestPlannedReparentShardSamePrimary(t *testing.T) { }, } oldPrimary.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ - "CREATE DATABASE IF NOT EXISTS _vt", - "SUBCREATE TABLE IF NOT EXISTS _vt.reparent_journal", - "ALTER TABLE _vt.reparent_journal CHANGE COLUMN master_alias primary_alias VARBINARY(32) NOT NULL", "SUBINSERT INTO _vt.reparent_journal (time_created_ns, action_name, primary_alias, replication_position) VALUES", } oldPrimary.StartActionLoop(t, wr) diff --git a/test/templates/cluster_endtoend_test.tpl b/test/templates/cluster_endtoend_test.tpl index 6095d0a1b79..72e74e16d76 100644 --- a/test/templates/cluster_endtoend_test.tpl +++ b/test/templates/cluster_endtoend_test.tpl @@ -163,6 +163,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql80.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_in_core_file=OFF innodb_buffer_pool_load_at_startup=OFF diff --git a/test/templates/cluster_endtoend_test_mysql57.tpl b/test/templates/cluster_endtoend_test_mysql57.tpl index f0a3f4f4f1e..ff2b2eca981 100644 --- a/test/templates/cluster_endtoend_test_mysql57.tpl +++ b/test/templates/cluster_endtoend_test_mysql57.tpl @@ -175,6 +175,7 @@ jobs: # Increase our open file descriptor limit as we could hit this ulimit -n 65536 cat <<-EOF>>./config/mycnf/mysql57.cnf + innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_load_at_startup=OFF innodb_buffer_pool_size=64M diff --git a/test/templates/unit_test.tpl b/test/templates/unit_test.tpl index e7fced8c093..14abab652d4 100644 --- a/test/templates/unit_test.tpl +++ b/test/templates/unit_test.tpl @@ -141,4 +141,8 @@ jobs: if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.unit_tests == 'true' timeout-minutes: 30 run: | + {{if (eq .Platform "mariadb103")}} + # mariadb103 + export MYSQL_FLAVOR="MariaDB103" + {{end}} eatmydata -- make unit_test