-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Downgrade problem from v20 in semi-sync plugin #16357
Changes from all commits
3bcd6c6
73d2627
caec7d6
56787f9
f71e5e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
name: Semi Sync Upgrade Downgrade Testing | ||
on: | ||
push: | ||
pull_request: | ||
|
||
concurrency: | ||
group: format('{0}-{1}', ${{ github.ref }}, 'Semi Sync Upgrade Downgrade Testing') | ||
Comment on lines
+1
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we also have that test on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. I thought about this too, but it seemed like we won't be making any more changes to semi-sync config on main. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can add a workflow to main, but it isn't all that necessary in my opinion. But we can always add a test similar to this on main too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like we probably should, we already have the code for the test, running a new workflow won't be very expensive, and will only increase our test coverage. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, I'll open a PR against main that adds a similar check there 👍 Edit: Here is the PR for the test on main - #16372 |
||
cancel-in-progress: true | ||
|
||
permissions: read-all | ||
|
||
jobs: | ||
upgrade_downgrade_test_e2e: | ||
timeout-minutes: 60 | ||
name: Run Semi Sync Upgrade Downgrade Test | ||
runs-on: gh-hosted-runners-16cores-1 | ||
|
||
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@v4 | ||
with: | ||
fetch-depth: 0 | ||
|
||
- name: Set output with latest release branch | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' | ||
id: output-previous-release-ref | ||
run: | | ||
previous_release_ref=$(./tools/get_previous_release.sh ${{github.base_ref}} ${{github.ref}}) | ||
echo $previous_release_ref | ||
echo "previous_release_ref=${previous_release_ref}" >> $GITHUB_OUTPUT | ||
|
||
- name: Check for changes in relevant files | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' | ||
uses: dorny/paths-filter@v3.0.1 | ||
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_semi_sync.yml' | ||
|
||
- name: Set up Go | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: 1.22.5 | ||
|
||
- name: Set up python | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' | ||
uses: actions/setup-python@v5 | ||
|
||
- 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 percona-release enable-only tools | ||
sudo apt-get update | ||
sudo apt-get install -y percona-xtrabackup-80 | ||
|
||
# Checkout to the last release of Vitess | ||
- name: Check out other version's code (${{ steps.output-previous-release-ref.outputs.previous_release_ref }}) | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ steps.output-previous-release-ref.outputs.previous_release_ref }} | ||
|
||
- 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 | ||
NOVTADMINBUILD=1 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@v4 | ||
|
||
- 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 | ||
NOVTADMINBUILD=1 make build | ||
mkdir -p /tmp/vitess-build-current/ | ||
cp -R bin /tmp/vitess-build-current/ | ||
|
||
# Copy last releases vttablet | ||
- name: Copy last release's VTTablet | ||
if: steps.skip-workflow.outputs.skip-workflow == 'false' && steps.changes.outputs.end_to_end == 'true' | ||
run: | | ||
source build.env | ||
|
||
cp /tmp/vitess-build-other/bin/vttablet $PWD/bin/vttabletold | ||
vttabletold --version | ||
|
||
- name: Run semi sync tests | ||
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 | ||
go test -v -count=1 -run="" ./go/test/endtoend/reparent/semisync -alsologtostderr | ||
frouioui marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
Copyright 2024 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 semisync | ||
frouioui marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"vitess.io/vitess/go/mysql" | ||
"vitess.io/vitess/go/test/endtoend/cluster" | ||
"vitess.io/vitess/go/test/endtoend/reparent/utils" | ||
) | ||
|
||
func TestSemiSyncUpgradeDowngrade(t *testing.T) { | ||
defer cluster.PanicHandler(t) | ||
clusterInstance := utils.SetupReparentCluster(t, "semi_sync") | ||
defer utils.TeardownCluster(clusterInstance) | ||
tablets := clusterInstance.Keyspaces[0].Shards[0].Vttablets | ||
|
||
// Verify that replication is running as intended. | ||
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) | ||
|
||
replica := tablets[1] | ||
// Verify we are using the correct vttablet version. | ||
verifyVttabletVersion(t, replica, 20) | ||
// Check the plugin loaded in vttablet. | ||
require.EqualValues(t, mysql.SemiSyncTypeMaster, semiSyncExtensionLoaded(t, replica)) | ||
|
||
t.Run("Downgrade to v19", func(t *testing.T) { | ||
// change vttablet binary and downgrade it. | ||
changeVttabletBinary(t, replica, "vttabletold") | ||
// Verify we are using the older vttablet version. | ||
verifyVttabletVersion(t, replica, 19) | ||
// Verify that replication is running as intended. | ||
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) | ||
// Check the plugin loaded in vttablet. | ||
require.EqualValues(t, mysql.SemiSyncTypeMaster, semiSyncExtensionLoaded(t, replica)) | ||
}) | ||
|
||
t.Run("Upgrade to v19", func(t *testing.T) { | ||
// change vttablet binary and downgrade it. | ||
changeVttabletBinary(t, replica, "vttablet") | ||
// Verify we are using the older vttablet version. | ||
verifyVttabletVersion(t, replica, 20) | ||
// Verify that replication is running as intended. | ||
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) | ||
// Check the plugin loaded in vttablet. | ||
require.EqualValues(t, mysql.SemiSyncTypeMaster, semiSyncExtensionLoaded(t, replica)) | ||
}) | ||
|
||
t.Run("Change the semi-sync plugin", func(t *testing.T) { | ||
// Change MySQL plugins loaded. | ||
utils.RunSQLs(context.Background(), t, []string{ | ||
`SET GLOBAL READ_ONLY=OFF`, | ||
`STOP REPLICA;`, | ||
`UNINSTALL PLUGIN rpl_semi_sync_master;`, | ||
`UNINSTALL PLUGIN rpl_semi_sync_slave;`, | ||
`INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';`, | ||
`INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';`, | ||
`START REPLICA;`, | ||
}, replica) | ||
// Check the plugin loaded in vttablet. | ||
require.EqualValues(t, mysql.SemiSyncTypeSource, semiSyncExtensionLoaded(t, replica)) | ||
// Verify that replication is running as intended. | ||
utils.ConfirmReplication(t, tablets[0], []*cluster.Vttablet{tablets[1], tablets[2], tablets[3]}) | ||
}) | ||
} | ||
|
||
// semiSyncExtensionLoaded checks if the semisync extension has been loaded. | ||
// It should work for both MariaDB and MySQL. | ||
func semiSyncExtensionLoaded(t *testing.T, replica *cluster.Vttablet) mysql.SemiSyncType { | ||
qr := utils.RunSQL(context.Background(), t, `SHOW VARIABLES LIKE 'rpl_semi_sync_%_enabled'`, replica) | ||
for _, row := range qr.Rows { | ||
if row[0].ToString() == "rpl_semi_sync_source_enabled" { | ||
return mysql.SemiSyncTypeSource | ||
} | ||
if row[0].ToString() == "rpl_semi_sync_master_enabled" { | ||
return mysql.SemiSyncTypeMaster | ||
} | ||
} | ||
return mysql.SemiSyncTypeOff | ||
} | ||
|
||
func changeVttabletBinary(t *testing.T, replica *cluster.Vttablet, binary string) { | ||
t.Helper() | ||
err := replica.VttabletProcess.TearDown() | ||
require.NoError(t, err) | ||
replica.VttabletProcess.Binary = binary | ||
err = replica.VttabletProcess.Setup() | ||
require.NoError(t, err) | ||
} | ||
|
||
func verifyVttabletVersion(t *testing.T, replica *cluster.Vttablet, version int) { | ||
t.Helper() | ||
verGot, err := cluster.GetMajorVersion(replica.VttabletProcess.Binary) | ||
require.NoError(t, err) | ||
require.EqualValues(t, version, verGot) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remember to mark this new workflow as
required
when we merge this.