Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d1f6f8f
feat(replication): prepare pxc-mysql job to accept replication
nouseforaname Jun 9, 2026
5d7bade
feat(replication): init pxc-replicator spec file
nouseforaname Jun 9, 2026
613385f
chore: add test setup helper
nouseforaname Jun 10, 2026
7fc1b2d
chore: create the instances on the same network
nouseforaname Jun 10, 2026
779e21a
feat(replication): wip client implementation
nouseforaname Jun 10, 2026
9f4ac12
feat(repl): add dumper to get initial backup
nouseforaname Jun 16, 2026
497a3ea
feat(repl): enable restores via mysql
nouseforaname Jun 16, 2026
e73c6e1
chore(tests): ser server id on testinstances
nouseforaname Jun 17, 2026
6b714c4
chore(clean) remove some obsolete code fragments, add logging
nouseforaname Jun 17, 2026
6ee7890
chore(fix): used wrong logger call
nouseforaname Jun 17, 2026
b849675
chore: don't drop currently unneded values from state response
nouseforaname Jun 17, 2026
a2efa0e
chore: make close and log error public so it can be used in tests
nouseforaname Jun 17, 2026
c2934a1
chore: improve test container setup
nouseforaname Jun 17, 2026
51b3aae
chore: finalize tests for e2e golden path
nouseforaname Jun 17, 2026
c391e05
feat(repl): add config structs for replication setup
nouseforaname Jun 17, 2026
117756c
chore: go mod vendor && init go.mod // go.sum
nouseforaname Jun 17, 2026
1d09c72
chore(test): add helper and optimize sql statements
nouseforaname Jun 19, 2026
c450ef2
chore(refactor): add wrapper around dumper
nouseforaname Jun 19, 2026
84d8748
chore: track time values as time.Time
nouseforaname Jun 19, 2026
0a93bef
chore: remove ugly constants
nouseforaname Jun 19, 2026
c0dffcd
wip: add more tests
nouseforaname Jun 19, 2026
4891d9a
chore: add TODO note about connection settings
nouseforaname Jun 17, 2026
9f76762
chore: add version check between source and host
nouseforaname Jun 22, 2026
78462dc
chore(test): add option to start instances with tls
nouseforaname Jun 22, 2026
af6ccba
feat(repl): enable tls connections & replication enabled check
nouseforaname Jun 24, 2026
2280371
add ai generated package godocs
nouseforaname Jun 24, 2026
2a78777
chore: formatting
nouseforaname Jun 24, 2026
729de86
chore: update deps
nouseforaname Jun 25, 2026
871ab36
chore: fix bugs in parsing replication state
nouseforaname Jun 25, 2026
567148f
chore(cleanup): small cleanup
nouseforaname Jun 25, 2026
e7e175a
chore: update tests
nouseforaname Jun 25, 2026
3592804
feat(replicator): add entrypoint / main
nouseforaname Jun 26, 2026
d224d85
chore: cleanup & small refactor
nouseforaname Jun 26, 2026
d2984b8
chore: split out dumpPath from dataPath. data path will be used to sh…
nouseforaname Jun 26, 2026
94a31ae
enable parallel tests by not reusing name
nouseforaname Jun 26, 2026
16df4e0
chore(refactor): better naminng, minor bugs
nouseforaname Jun 29, 2026
7809db2
feat(replication): finish configuration for pxc-replicator
nouseforaname Jun 29, 2026
7cb7798
chore: remove json tags, add yaml tags
nouseforaname Jun 29, 2026
07e0f19
chore: clean imports and use go available in pxc-release
nouseforaname Jun 29, 2026
6ac1cf7
feat(repl): create user if not present
nouseforaname Jul 1, 2026
e3f16ff
chore: make the template easier to read
nouseforaname Jul 1, 2026
e0ca363
feat(repl): only take source backups if necessary
nouseforaname Jul 2, 2026
925b51a
feat(repl): clean not required backups
nouseforaname Jul 2, 2026
6b54ee7
fix(repl): badly rendered certs
nouseforaname Jul 2, 2026
d70873f
chore(repl): add packaging script
nouseforaname Jul 2, 2026
839a107
chore(repl): fix linter issues
nouseforaname Jul 2, 2026
e645f79
add example manifests
nouseforaname Jul 3, 2026
6da083c
chore(repl): minor job updates/improvements
nouseforaname Jul 3, 2026
cde015a
chore: refactor db.Open use
nouseforaname Jul 6, 2026
dad679a
bug: return early on error
nouseforaname Jul 6, 2026
bb9a380
chore: linter warnings
nouseforaname Jul 6, 2026
e69382e
chore: add tests for stringers
nouseforaname Jul 6, 2026
63d748a
chore: generate go docs via ai
nouseforaname Jul 6, 2026
1fdba47
bug: apparently gtid can have multiple ranges
nouseforaname Jul 6, 2026
70d9c77
chore: fix test parallel flakes
nouseforaname Jul 13, 2026
abe8530
chore: test updates
nouseforaname Jul 16, 2026
334fa41
chore: use host arch for test containers in compile
nouseforaname Jul 16, 2026
c3a00e7
clean: remove expectation
nouseforaname Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 6 additions & 4 deletions jobs/pxc-mysql/spec
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ provides:
- port
- pxc_enabled
- mysql_version
- tls.client.ca

- name: internal-mysql-database
type: internal-database
- name: mysql-backup-user-creds
Expand All @@ -67,15 +69,13 @@ provides:
- mysql_socket

properties:

pxc_enabled:
description: 'Used for disabling the job. Useful if co-locating the cf-mysql release mysql job and migrating'
default: true
disable_persistent_storage_safety_check:
description: 'pre-start checks that /var/vcap/store is a persistent volume to prevent accidentally running the database on an ephemeral disk. This can be used to disable this check for test or bosh-lite situations'
default: false


# Admin Users
admin_username:
description: 'Username for the MySQL server admin user'
Expand All @@ -100,7 +100,9 @@ properties:
default: 'mysql-backup'
mysql_backup_password:
description: 'Optional. Password for mysql-backup user'

mysql_backup_allowed_remote_hosts:
default: localhost
description: 'Optional. Host from where the backup user is allowed to connect. % for all remote hosts.'
mysql_socket:
description: Location of the mysql socket for connecting locally
default: '/var/vcap/sys/run/pxc-mysql/mysqld.sock'
Expand Down Expand Up @@ -388,4 +390,4 @@ properties:
kernel.vm.swappiness:
description: "Configure Linux vm.swappiness"
# https://docs.kernel.org/admin-guide/sysctl/vm.html#swappiness
# https://www.percona.com/blog/mysql-101-linux-tuning-for-mysql/
# https://www.percona.com/blog/mysql-101-linux-tuning-for-mysql/
14 changes: 7 additions & 7 deletions jobs/pxc-mysql/templates/db_init.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ DROP USER IF EXISTS '<%= p('admin_username') %>'@'<%= host %>';
<%- end -%>
DROP USER IF EXISTS 'roadmin'@'<%= host %>';

<%- end -%>
<%- if_p('mysql_backup_password') do |password| -%>
CREATE USER IF NOT EXISTS '<%= p('mysql_backup_username') %>'@'localhost';
ALTER USER '<%= p('mysql_backup_username') %>'@'localhost' IDENTIFIED WITH <%= p('engine_config.user_authentication_policy') %> BY '<%= password %>';
GRANT RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, /*!80001 BACKUP_ADMIN,*/ PROCESS ON *.* to '<%= p('mysql_backup_username') %>'@'localhost';
GRANT SELECT on performance_schema.keyring_component_status to '<%= p('mysql_backup_username') %>'@'localhost';
GRANT SELECT ON performance_schema.log_status TO '<%= p('mysql_backup_username') %>'@'localhost';
<%- end
if_p('mysql_backup_password') do |password| -%>
CREATE USER IF NOT EXISTS '<%= p('mysql_backup_username') %>'@'<%= p('mysql_backup_allowed_remote_hosts') %>';
ALTER USER '<%= p('mysql_backup_username') %>'@'<%= p('mysql_backup_allowed_remote_hosts') %>' IDENTIFIED WITH <%= p('engine_config.user_authentication_policy') %> BY '<%= password %>';
GRANT EVENT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT, /*!80001 BACKUP_ADMIN,*/ PROCESS ON *.* to '<%= p('mysql_backup_username') %>'@'<%= p('mysql_backup_allowed_remote_hosts') %>';
GRANT SELECT ON performance_schema.keyring_component_status to '<%= p('mysql_backup_username') %>'@'<%= p('mysql_backup_allowed_remote_hosts') %>';
GRANT SELECT ON performance_schema.log_status TO '<%= p('mysql_backup_username') %>'@'<%= p('mysql_backup_allowed_remote_hosts') %>';

<%- end -%>
<%- hosts.each do |host| -%>
Expand Down
5 changes: 5 additions & 0 deletions jobs/pxc-replicator/monit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
check process pxc-replicator
with pidfile /var/vcap/sys/run/bpm/pxc-replicator/pxc-replicator.pid
start program "/var/vcap/jobs/bpm/bin/bpm start pxc-replicator"
stop program "/var/vcap/jobs/bpm/bin/bpm stop pxc-replicator"
group vcap
72 changes: 72 additions & 0 deletions jobs/pxc-replicator/spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
name: pxc-replicator

templates:
bpm.yml.erb: config/bpm.yml
config/config.yml.erb: config/config.yml

packages:
- percona-xtradb-cluster-8.0
- percona-xtradb-cluster-8.4
- pxc-replicator

consumes:
- name: mysql-backup-user-creds
type: mysql-backup-user-creds
optional: true
- name: source
type: mysql
optional: true
- name: target
type: mysql
optional: true

properties:
#SOURCE
source_admin_username:
description: |
this is here for compatibility with older deployments of the pxc-release.
If provided it will be used to create, authorize the `mysql-backup-user` on the source instance
source_admin_password:
description: |
this is here for compatibility with older deployments of the pxc-release.
If provided it will be used to create, authorize the `mysql-backup-user` on the source instance
mysql_backup_username:
description: 'a replication enabled user that exists on the source mysql. It requires permissions to do a full `mysqldump --all-databases --events --triggers --routines --single-transaction` of the source instance. If specified alongside source_admin_username && source_admin_password this user will automatically be generated and provided with the right permissions. '
mysql_backup_password:
description: 'password to use for connection to source instance. If specified alongside source_admin_username && source_admin_password this user will automatically be generated and provided with the right permissions.'

#SOURCE TLS/CONNECTION
source_tls.ca:
description: ca certificate in pem format to validate the source instance
source_host:
description: 'hostname of the source database instance'
source_port:
default: 3306

#TARGET
target_admin_username:
description: |
the admin user for the target of the replication. It will be used to connect and setup the replication
connection
target_admin_password:
description: |
the admin user for the target of the replication. It will be used to connect and setup the replication
connection
#TARGET TLS/CONNECTION
target_host:
description: 'hostname of the target database instance'
target_port:
default: 3306
target_tls.ca:
description: ca certificate in pem format to validate the target instance

#GENERAL
clean_expired_backups:
description: |
To setup replication, pxc replicator will run an initial sync that takes a backup via mysqldump of the source. Re-Syncing is necessary in some cases where the replication breaks in a way where the incoming transactions from the source do not cleanly apply.
Enabling this setting will cleanup "expired" backups once the contained GTID is too old to reconnect the target with the source. When multiple viable backups are cached, only the latest viable backup is kept.
default: true
mysql_version:
description: 'the version of mysql deployed for source and target. Both deployments should use the same version.'
default: 8.4
17 changes: 17 additions & 0 deletions jobs/pxc-replicator/templates/bpm.yml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
processes:
- name: pxc-replicator
executable: /var/vcap/packages/pxc-replicator/bin/replicator
args:
- -config=/var/vcap/jobs/pxc-replicator/config/config.yml
- -data-dir=/var/vcap/data/pxc-replicator/data
- -dump-dir=/var/vcap/data/pxc-replicator/dumps
- -mysql-bin-path=/var/vcap/packages/percona-xtradb-cluster-<%= p('mysql_version') -%>/bin/
- -mysql-version=<%= p('mysql_version') %>
additional_volumes:
- path: /var/vcap/data/pxc-replicator/data
writable: true
- path: /var/vcap/data/pxc-replicator/dumps
writable: true
- path: /var/vcap/data/pxc-mysql
mount_only: true
writable: true
83 changes: 83 additions & 0 deletions jobs/pxc-replicator/templates/config/config.yml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<%-
source_creds = {}
fallback = true
if_link('mysql-backup-user-creds') do |link|
link.if_p('mysql_backup_username','mysql_backup_password') do |user,pass|
source_creds = { 'username' => user, 'password' => pass }
fallback = false
end
end
if fallback
if_p('mysql_backup_username', 'mysql_backup_password') do |user,pass|
source_creds = { 'username' => user, 'password' => pass }
end
end
if_p('source_admin_username', 'source_admin_password') do |user,pass|
source_creds["admin_username"] = user
source_creds["admin_password"] = pass
end
-%>
version: <%= p('mysql_version') %>
source:
name: source
<%-
if_link('source') do |link|
tls = {}
link.if_p('tls.client.ca') do |val|
tls["ca"] = val
end.else do
if_p('source_tls.ca') do |val|
tls["ca"] = val
end
end
-%>
#link config
host: <%= link.address %>
port: <%= link.p('port') %>
version: <%= link.p('mysql_version') %>
creds: <%= JSON.dump(source_creds) %>
tls: <%= JSON.dump(tls) %>
<%-
end.else do
-%>
#manual config
host: <%= p('source_host') %>
port: <%= p('source_port') %>
version: <%= p('mysql_version') %>
creds: <%= JSON.dump(source_creds) %>
tls: <%= JSON.dump(tls) %>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems to fail on an error:

     NameError:
       undefined local variable or method `tls' for an instance of Bosh::Template::EvaluationContext

<%-
end
-%>
#TARGET
target:
name: target
<%-
target_creds = {
"admin_username" => p('target_admin_username'),
"admin_password" => p('target_admin_password'),
}
if_link('target') do |link|
tls = {}
link.if_p('tls.client.ca') do |ca|
tls["ca"] = ca
end.else do
if_p("target_tls.ca") do |ca|
tls["ca"] = ca
end
end
-%>
version: <%= link.p('mysql_version') %>
host: localhost
port: <%= link.p('port') %>
creds: <%= JSON.dump(target_creds) %>
tls: <%= JSON.dump(tls) %>
<%-
end.else do
-%>
host: <%= p('target_host') %>
port: <%= p('target_port') %>
version: <%= p('mysql_version') %>
creds: <%= JSON.dump(target_creds) %>
tls: <%= JSON.dump(tls) %>
<%- end -%>
9 changes: 9 additions & 0 deletions operations/add-replicator-job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-replicator?
value:
name: pxc-replicator
release: pxc
properties: {}
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/binlog?/enable_gtid_mode?
value: true
34 changes: 34 additions & 0 deletions operations/set-replicator-source.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/server_id?
value: 1
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/binlog?/enable_gtid_mode
value: true
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/provides?
value:
mysql-backup-user-creds:
as: source-creds
shared: true
mysql:
as: replica-source
shared: true
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/mysql_backup_username?
value: ((mysql_backup_user.username))
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/mysql_backup_password?
value: ((mysql_backup_user.password))
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/mysql_backup_allowed_remote_hosts?
value: '%'

- type: replace
path: /variables/name=mysql_backup_user?
value:
name: mysql_backup_user
type: user
parameters:
length: 32


37 changes: 37 additions & 0 deletions operations/set-replicator-target.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/server_id?
value: 2
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/binlog?/enable_gtid_mode?
value: true
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/provides?/mysql?
value:
as: replica-target
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/mysql_version?
value: '8.4'
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-replicator/properties/mysql_version?
value: '8.4'
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-replicator/properties/target_admin_username?
value: 'root'
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-replicator/properties/target_admin_password?
value: ((cf_mysql_mysql_admin_password))
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/tls?/client?/ca
value: ((mysql_server_certificate.ca))
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-replicator/consumes?
value:
source:
from: replica-source
deployment: ((source_deployment_name))
target:
from:
replica-target
mysql-backup-user-creds:
from: source-creds
deployment: ((source_deployment_name))
3 changes: 3 additions & 0 deletions operations/update-azs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/azs?
value: ((azs))
3 changes: 3 additions & 0 deletions operations/update-deployment-name.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /name
value: ((deployment_name))
3 changes: 3 additions & 0 deletions operations/update-network.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/networks?
value: [{name: ((network_name))}]
3 changes: 3 additions & 0 deletions operations/update-persistent-disk-size.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/persistent_disk?
value: ((persistent_disk_size))
3 changes: 3 additions & 0 deletions operations/update-vm-extensions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/vm_extensions?
value: ((vm_extensions))
3 changes: 3 additions & 0 deletions operations/update-vm-type.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/vm_type?
value: ((vm_type))
3 changes: 3 additions & 0 deletions operations/use-mysql-8.4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- type: replace
path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/mysql_version?
value: "8.4"
9 changes: 9 additions & 0 deletions packages/pxc-replicator/packaging
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -ex

source /var/vcap/packages/golang-1-linux/bosh/compile.env

cd pxc-replicator
mkdir -p "${BOSH_INSTALL_TARGET}/bin"
GOOS=linux GOARCH=amd64 go build -mod=vendor -o "${BOSH_INSTALL_TARGET}/bin/replicator"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a reason to hardcode the GOOS/GOARCH here?

Since BOSH compiles packages directly on the target stemcell, hardcoding amd64 is an anti-pattern that will break this component on ARM - which is especially relevant given the open RFC for ARM64 support.

If you drop the env vars, you can also use Go's -C flag to turn this entire block into a clean one-liner while still keeping explicit control over the binary name:

mkdir -p "${BOSH_INSTALL_TARGET}/bin"
go build -C pxc-replicator -mod=vendor -o "${BOSH_INSTALL_TARGET}/bin/replicator" .

cd -
6 changes: 6 additions & 0 deletions packages/pxc-replicator/spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: pxc-replicator
dependencies:
- golang-1-linux
files:
- pxc-replicator/**/*
Loading
Loading