diff --git a/jobs/pxc-mysql/spec b/jobs/pxc-mysql/spec index eec4b2ecd..607e33873 100644 --- a/jobs/pxc-mysql/spec +++ b/jobs/pxc-mysql/spec @@ -51,6 +51,15 @@ consumes: optional: true provides: +- name: source + type: source + properties: + - port + - mysql_version + - mysql_backup_username + - mysql_backup_password + - tls + - name: mysql type: mysql properties: @@ -67,7 +76,6 @@ 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 @@ -75,7 +83,6 @@ properties: 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' @@ -309,6 +316,12 @@ properties: engine_config.read_write_permissions: description: "Specify the database server's read/write setting. For single-node deployments, valid options are `read_write`, `read_only`, or `super_read_only`. The setting must be `read_write` for Galera clusters." default: read_write + engine_config.enable_replication_target: + description: 'When configuring a replica, this will use spec.index to populate server_id on each node starting at the highest possible index. Any value set for server_id will be discarded by enabling this setting' + default: false + engine_config.enable_replication_source: + description: 'When configuring a replica, this will use spec.index to populate server_id on each node starting at the lowest possible index. Any value set for server_id will be discarded by enabling this setting' + default: false engine_config.server_id: description: 'In leader-follower topology, this value must be unique. In other words, the leader must have a different value than the follower and vice versa. If this is set to 0, then the server refuses any replication connections.' default: 0 @@ -388,4 +401,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/ \ No newline at end of file + # https://www.percona.com/blog/mysql-101-linux-tuning-for-mysql/ diff --git a/jobs/pxc-mysql/templates/db_init.erb b/jobs/pxc-mysql/templates/db_init.erb index e09d11d0c..d119c48e8 100644 --- a/jobs/pxc-mysql/templates/db_init.erb +++ b/jobs/pxc-mysql/templates/db_init.erb @@ -22,13 +22,19 @@ 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 +allowed_remote_backup_hosts='localhost' + +if p('engine_config.enable_replication_source') + allowed_remote_backup_hosts='%' +end + +if_p('mysql_backup_password') do |password| -%> +CREATE USER IF NOT EXISTS '<%= p('mysql_backup_username') %>'@'<%= allowed_remote_backup_hosts %>'; +ALTER USER '<%= p('mysql_backup_username') %>'@'<%= allowed_remote_backup_hosts %>' 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') %>'@'<%= allowed_remote_backup_hosts %>'; +GRANT SELECT on performance_schema.keyring_component_status to '<%= p('mysql_backup_username') %>'@'<%= allowed_remote_backup_hosts %>'; +GRANT SELECT ON performance_schema.log_status TO '<%= p('mysql_backup_username') %>'@'<%= allowed_remote_backup_hosts %>'; <%- end -%> <%- hosts.each do |host| -%> diff --git a/jobs/pxc-replicator/monit b/jobs/pxc-replicator/monit new file mode 100644 index 000000000..dedf6902b --- /dev/null +++ b/jobs/pxc-replicator/monit @@ -0,0 +1,7 @@ +<% if p('replicator_enabled') == true %> +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" with timeout <%= p('monit_startup_timeout') %> seconds + stop program "/var/vcap/jobs/bpm/bin/bpm stop pxc-replicator" + group vcap +<% end %> diff --git a/jobs/pxc-replicator/spec b/jobs/pxc-replicator/spec new file mode 100644 index 000000000..eff0af31d --- /dev/null +++ b/jobs/pxc-replicator/spec @@ -0,0 +1,72 @@ +--- +name: pxc-replicator + +templates: + bpm.yml.erb: config/bpm.yml + bin/setup: bin/setup + bin/post-start: bin/post-start + source.mysql.cnf.erb: config/source.mysql.cnf + source.admin.mysql.cnf.erb: config/source.admin.mysql.cnf + config/client-cert.pem.erb: certificates/client-cert.pem + config/client-key.pem.erb: certificates/client-key.pem + config/server-ca.pem.erb: certificates/server-ca.pem + +packages: +- percona-xtradb-cluster-8.0 +- percona-xtradb-cluster-8.4 +- percona-xtrabackup-2.4 +- percona-xtrabackup-8.0 +- percona-xtrabackup-8.4 +- pxc-utils + +consumes: +- name: source + type: source + optional: true + properties: + - port + - mysql_version + - mysql_backup_username + - mysql_backup_password + - tls + +properties: + source_admin_username: + description: | + this is here for compatibility with older deployments of the pxc-release. + technically, the `roadmin` user is viable as a replication user, but it misses `REPLICATION SLAVE` privilege. + providing the source_admin_username & password will ensure that the roadmin will updated with the missing permission + + source_admin_password: + description: | + this is here for compatibility with older deployments of the pxc-release. + technically, the `roadmin` user is viable as a replication user, but it misses `REPLICATION SLAVE` privilege. + providing the source_admin_username & password will ensure that the roadmin will updated with the missing permission + monit_startup_timeout: + description: 'How long to wait for monit to show running for the process, will also be used as a timeout for the post-start health check' + default: 180 + mysql_version: + description: 'deployed version' + default: 8.0 + logging.format.timestamp: + default: rfc3339 + replicator_enabled: + description: 'Whether to enable the job ( skips writing monit file if set to false )' + default: false + mysql_backup_username: + description: 'user to use for connection to source instance' + mysql_backup_password: + description: 'password to use for connection to source instance' + host: + description: 'hostname of the source database instance' + port: + description: 'Whether to enable the job ( skips writing monit file if set to false )' + default: 3306 + tls: + description: 'TLS certificates to use for connections' + example: { + "ca": "...", + "certificate": "...", + "private_key": "..." + } + default: {} diff --git a/jobs/pxc-replicator/templates/bin/post-start b/jobs/pxc-replicator/templates/bin/post-start new file mode 100644 index 000000000..089a45aff --- /dev/null +++ b/jobs/pxc-replicator/templates/bin/post-start @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +<% if p('replicator_enabled') then %> +. /var/vcap/packages/pxc-utils/logging.sh + +#it's a bash feature. +#https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#index-SECONDS +SECONDS=0 +PATH="${PATH}:/var/vcap/packages/percona-xtradb-cluster-<%= p('mysql_version') -%>/bin" + +log "starting post-start, checking replication" +while [[ $SECONDS -lt 300 ]]; do + if mysql --defaults-file=/var/vcap/jobs/pxc-mysql/config/mylogin.cnf <<< "SHOW REPLICA STATUS\G" | grep 'Replica_IO_Running: Yes'; then + log "IO thread is running" + else + log "IO thread is running" + continue + fi + + if mysql --defaults-file=/var/vcap/jobs/pxc-mysql/config/mylogin.cnf <<< "SHOW REPLICA STATUS\G" | grep 'Replica_SQL_Running: Yes'; then + log "SQL thread is running" + exit 0 + else + log "SQL thread not running" && continue + continue + fi + sleep 5 +done + +log "timed out waiting for replication to report healthy" +exit -1 +<% end %> diff --git a/jobs/pxc-replicator/templates/bin/setup b/jobs/pxc-replicator/templates/bin/setup new file mode 100644 index 000000000..8080fe81e --- /dev/null +++ b/jobs/pxc-replicator/templates/bin/setup @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -eo pipefail + +. /var/vcap/packages/pxc-utils/logging.sh + + +<%- if_p('tls.client.ca','tls.client.certificate','tls.client.private_key') do -%> +SOURCE_SSL_CONFIG="SOURCE_SSL_CA = '/var/vcap/jobs/pxc-replicator/certificates/server-ca.pem', SOURCE_SSL_CERT = '/var/vcap/jobs/pxc-replicator/certificates/client-cert.pem', SOURCE_SSL_KEY = '/var/vcap/jobs/pxc-replicator/certificates/client-key.pem'" +<%- end.else do if_link('source') do |link| -%> + <%- if link.p('tls') != nil && link.p('tls')['client'] != nil then -%> +SOURCE_SSL_CONFIG="SOURCE_SSL_CA = '/var/vcap/jobs/pxc-replicator/certificates/server-ca.pem', SOURCE_SSL_CERT = '/var/vcap/jobs/pxc-replicator/certificates/client-cert.pem', SOURCE_SSL_KEY = '/var/vcap/jobs/pxc-replicator/certificates/client-key.pem'" + <%- else -%> +SOURCE_SSL_CONFIG="" + <%- end -%> +<%- end end -%> +function is_replication_configured(){ + ! test "$($self_mysql <<< "SHOW REPLICA STATUS\G")" = "" +} +function is_replica_io_running (){ + $self_mysql <<< "SHOW REPLICA STATUS\G" | grep 'Replica_IO_Running: Yes' +} +function is_replica_sql_running (){ + $self_mysql <<< "SHOW REPLICA STATUS\G" | grep 'Replica_SQL_Running: Yes' +} +function enable_replication (){ + $self_mysql <<< "STOP REPLICA; +CHANGE REPLICATION SOURCE TO + SOURCE_HOST='${SOURCE_ADDR}', + SOURCE_USER='${SOURCE_USER}', + SOURCE_PASSWORD='${SOURCE_PASS}', + SOURCE_AUTO_POSITION=1, + ${SOURCE_SSL_CONFIG}; +START REPLICA;" +} +function ensure_backup_user_has_replication_slave(){ + if [[ ! -z "${source_admin_mysql}" ]]; then + log "found source_admin_creds, ensuring source_replica user permissions" + ${source_admin_mysql} <<< "GRANT REPLICATION SLAVE ON *.* TO '${SOURCE_USER}'@'%';" + fi +} +function sync_databases(){ + log "resyncing with full backup" + ensure_backup_user_has_replication_slave + log $($self_mysql <<< "STOP REPLICA;") + log $($self_mysql <<< "RESET REPLICA;") + log $($self_mysql <<< "RESET MASTER;") + log $($source_dump --all-databases --triggers --routines --single-transaction | $self_mysql) +} +function source_upcheck(){ + $source_mysql <<< "exit" +} +function self_upcheck(){ + $self_mysql <<< "exit" +} + +while ! source_upcheck; do + log "waiting for source to be available" + sleep 5 +done + +while ! self_upcheck; do + log "waiting for self to be available" + sleep 5 +done + +log "starting replication setup" + +log "checking existing databases in source instance" + +log "checking replication status" + +if ! is_replication_configured; then + log "replication is not yet enabled" + sync_databases + + log "replication is not configured. enabling" + OUT=$(enable_replication); + if [[ "${OUT}" != "" ]]; then + log "failed enabling replication: '$OUT'" | sed "s/${SOURCE_PASS}//g" + else + log "replication enabled" + fi +else + log "replicaton already enabled, skipping" +fi + +while true; do + log "checking running status" + RUNNING_STATUS="$($self_mysql <<< "SHOW REPLICA STATUS\G" | grep 'Replica_.*_Running: ' | xargs )" + if is_replica_io_running && is_replica_sql_running; then + log "replication healthy" + elif ! is_replica_io_running; then + log "restarting replica" + ensure_backup_user_has_replication_slave + $self_mysql <<< "START REPLICA;" + sleep 30 + elif ! is_replica_sql_running ; then + log "replication Replica_SQL_Running marked as no. Attempting to resync" + sync_databases + else + log "$RUNNING_STATUS" + for line in $($self_mysql <<< "SHOW REPLICA STATUS\G" | grep 'Err' | tr -d '[:blank:]' ); do + log "${line/$SOURCE_PASS//}"; + done + fi + log "$RUNNING_STATUS" + sleep 5 +done diff --git a/jobs/pxc-replicator/templates/bpm.yml.erb b/jobs/pxc-replicator/templates/bpm.yml.erb new file mode 100644 index 000000000..518e90fe1 --- /dev/null +++ b/jobs/pxc-replicator/templates/bpm.yml.erb @@ -0,0 +1,53 @@ +<%- +if !['rfc3339', 'unix-epoch'].include?(p('logging.format.timestamp')) + raise "'#{p('logging.format.timestamp')}' is not a valid timestamp format for the property 'logging.format.timestamp'." + + " Valid options are: 'rfc3339' and 'unix-epoch'." +end +path = [ + "/usr/bin", + "/bin", + "/var/vcap/packages/percona-xtradb-cluster-#{p('mysql_version')}/bin", +] +flags = "" +if_p('tls.client.ca','tls.client.certificate','tls.client.private_key') do + flags = "--ssl-ca=/var/vcap/jobs/pxc-replicator/certificates/server-ca.pem --ssl-cert=/var/vcap/jobs/pxc-replicator/certificates/client-cert.pem --ssl-key=/var/vcap/jobs/pxc-replicator/certificates/client-key.pem" +end +if_link('source') do |link| + if link.p('tls') != nil && link.p('tls')['client'] != nil then + flags = "--ssl-ca=/var/vcap/jobs/pxc-replicator/certificates/server-ca.pem --ssl-cert=/var/vcap/jobs/pxc-replicator/certificates/client-cert.pem --ssl-key=/var/vcap/jobs/pxc-replicator/certificates/client-key.pem" + end +end +-%> +--- +<% if p('replicator_enabled') %> +processes: +- name: pxc-replicator + executable: /var/vcap/jobs/pxc-replicator/bin/setup + args: [] + env: + PATH: <%= path.join(":") %> +<%- if_p('mysql_backup_username', 'mysql_backup_password' ,'host', 'port') do |user,pass,host| -%> + SOURCE_USER: <%= user %> + SOURCE_PASS: <%= pass %> + SOURCE_ADDR: <%= host %> +<%- end.else do if_link("source") do |link| -%> + SOURCE_USER: <%= link.p('mysql_backup_username') %> + SOURCE_PASS: <%= link.p('mysql_backup_password') %> + SOURCE_ADDR: <%= link.address %> +<%- end end -%> + self_mysql: 'mysql --defaults-file=/var/vcap/jobs/pxc-mysql/config/mylogin.cnf' + source_dump: 'mysqldump --defaults-file=/var/vcap/jobs/pxc-replicator/config/source.mysql.cnf <%= flags -%>' + source_mysql: 'mysql --defaults-file=/var/vcap/jobs/pxc-replicator/config/source.mysql.cnf <%= flags -%>' +<%- if_p('source_admin_username','source_admin_password','host') do -%> + source_admin_mysql: 'mysql --defaults-file=/var/vcap/jobs/pxc-replicator/config/source.admin.mysql.cnf <%= flags -%>' +<%- end -%> + persistent_disk: true + ephemeral_disk: true + additional_volumes: + - path: /var/vcap/sys/run/pxc-mysql + writeable: false + - path: /var/vcap/jobs/pxc-mysql/config + writeable: false + - path: /var/vcap/jobs/pxc-replicator/certificates + writeable: false +<% end %> diff --git a/jobs/pxc-replicator/templates/config/client-cert.pem.erb b/jobs/pxc-replicator/templates/config/client-cert.pem.erb new file mode 100644 index 000000000..df2693808 --- /dev/null +++ b/jobs/pxc-replicator/templates/config/client-cert.pem.erb @@ -0,0 +1,5 @@ +<%- if_p('tls.client') do |client_tls| -%> +<%= client_tls['certificate'] %> +<%- end.else_if_p do if_link('source') do |link| -%> +<%= link.tls.client.certificate -%> +<%- end end -%> diff --git a/jobs/pxc-replicator/templates/config/client-key.pem.erb b/jobs/pxc-replicator/templates/config/client-key.pem.erb new file mode 100644 index 000000000..0d6cb9630 --- /dev/null +++ b/jobs/pxc-replicator/templates/config/client-key.pem.erb @@ -0,0 +1,5 @@ +<%- if_p('tls.client') do |client_tls| -%> +<%= client_tls['private_key'] %> +<%- end.else_if_p do if_link('source') do |link| -%> +<%= link.tls.client.private_key -%> +<%- end end -%> diff --git a/jobs/pxc-replicator/templates/config/server-ca.pem.erb b/jobs/pxc-replicator/templates/config/server-ca.pem.erb new file mode 100644 index 000000000..02b42fd7f --- /dev/null +++ b/jobs/pxc-replicator/templates/config/server-ca.pem.erb @@ -0,0 +1,5 @@ +<%- if_p('tls.client') do |client_tls| -%> +<%= client_tls['ca'] %> +<%- end.else_if_p do if_link('source') do |link| -%> +<%= link.tls.client.ca -%> +<%- end end -%> diff --git a/jobs/pxc-replicator/templates/source.admin.mysql.cnf.erb b/jobs/pxc-replicator/templates/source.admin.mysql.cnf.erb new file mode 100644 index 000000000..f28e81799 --- /dev/null +++ b/jobs/pxc-replicator/templates/source.admin.mysql.cnf.erb @@ -0,0 +1,7 @@ +<% if_p('source_admin_username','source_admin_password','host','port') do |user,pass,host,port| %> +[client] +user = <%= user %> +password = <%= pass %> +host = <%= host %> +port = <%= port %> +<% end %> diff --git a/jobs/pxc-replicator/templates/source.mysql.cnf.erb b/jobs/pxc-replicator/templates/source.mysql.cnf.erb new file mode 100644 index 000000000..286ca1825 --- /dev/null +++ b/jobs/pxc-replicator/templates/source.mysql.cnf.erb @@ -0,0 +1,13 @@ +<% if_p('mysql_backup_username', 'mysql_backup_password' ,'host', 'port') do |user,pass,host,port| %> +[client] +user = <%= user %> +password = <%= pass %> +host = <%= host %> +port = <%= port %> +<% end.else_if_p do if_link("source") do |link| %> +[client] +user = <%= link.p('mysql_backup_username') %> +password = <%= link.p('mysql_backup_password') %> +host = <%= link.address %> +port = <%= link.p('port') %> +<% end end %> diff --git a/operations/add-replicator-job.yml b/operations/add-replicator-job.yml new file mode 100644 index 000000000..87946d535 --- /dev/null +++ b/operations/add-replicator-job.yml @@ -0,0 +1,11 @@ +- type: replace + path: /instance_groups/name=mysql/jobs/name=pxc-replicator? + value: + name: pxc-replicator + release: pxc + properties: + config.tls.enabled: true + +- type: replace + path: /instance_groups/name=mysql/jobs/name=pxc-mysql/properties/engine_config?/binlog?/enable_gtid_mode? + value: true diff --git a/operations/set-replicator-source.yml b/operations/set-replicator-source.yml new file mode 100644 index 000000000..3f1c9c0e6 --- /dev/null +++ b/operations/set-replicator-source.yml @@ -0,0 +1,26 @@ +- 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?/enable_replication_source + value: true +- type: replace + path: /instance_groups/name=mysql/jobs/name=pxc-mysql/provides?/source + value: + shared: true + as: replica-source +- 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: /variables/name=mysql_backup_user? + value: + name: mysql_backup_user + type: user + parameters: + length: 32 + + diff --git a/operations/set-replicator-target.yml b/operations/set-replicator-target.yml new file mode 100644 index 000000000..fd4a126f7 --- /dev/null +++ b/operations/set-replicator-target.yml @@ -0,0 +1,11 @@ +- 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?/enable_replication_target + value: true +- type: replace + path: /instance_groups/name=mysql/jobs/name=pxc-replicator/consumes?/source + value: + from: replica-source + deployment: ((source_deployment_name)) diff --git a/operations/update-azs.yml b/operations/update-azs.yml new file mode 100644 index 000000000..334df0adf --- /dev/null +++ b/operations/update-azs.yml @@ -0,0 +1,3 @@ +- type: replace + path: /instance_groups/name=mysql/azs? + value: ((azs)) diff --git a/operations/update-deployment-name.yml b/operations/update-deployment-name.yml new file mode 100644 index 000000000..8c21e0394 --- /dev/null +++ b/operations/update-deployment-name.yml @@ -0,0 +1,3 @@ +- type: replace + path: /name + value: ((deployment_name)) diff --git a/operations/update-network.yml b/operations/update-network.yml new file mode 100644 index 000000000..5df73976d --- /dev/null +++ b/operations/update-network.yml @@ -0,0 +1,3 @@ +- type: replace + path: /instance_groups/name=mysql/networks? + value: [{name: ((network_name))}] diff --git a/operations/update-persistent-disk-size.yml b/operations/update-persistent-disk-size.yml new file mode 100644 index 000000000..fbe80969a --- /dev/null +++ b/operations/update-persistent-disk-size.yml @@ -0,0 +1,3 @@ +- type: replace + path: /instance_groups/name=mysql/persistent_disk? + value: ((persistent_disk_size)) diff --git a/operations/update-vm-type.yml b/operations/update-vm-type.yml new file mode 100644 index 000000000..47c680a3f --- /dev/null +++ b/operations/update-vm-type.yml @@ -0,0 +1,3 @@ +- type: replace + path: /instance_groups/name=mysql/vm_type? + value: ((vm_type)) diff --git a/render-manifest.sh b/render-manifest.sh new file mode 100755 index 000000000..a74bdf1bc --- /dev/null +++ b/render-manifest.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +GENERAL_OPS=( + "-o operations/update-deployment-name.yml" + "-o operations/update-persistent-disk-size.yml" + "-o operations/update-network.yml" + "-o operations/update-vm-type.yml" + "-o operations/update-azs.yml" + "-o operations/dev-release.yml" + "-o operations/add-replicator-job.yml" +) +SOURCE_OPS=( + "-o operations/set-replicator-source.yml" +) +REPLICA_OPS=( + "-o operations/set-replicator-target.yml" +) +REPLICA_VARS=( + "-v deployment_name=replica" + "-v source_deployment_name=source" +) +SOURCE_VARS=( + "-v deployment_name=source" +) +GENERAL_VARS=( + "-v vm_type=medium" + "-v azs=['az-0','az-1','az-2']" + "-v network_name=004-dev-scf-eu01-mgmt" + "-v persistent_disk_size=10000" +) +#shellcheck disable=2068 +bosh int pxc-deployment.yml \ + ${GENERAL_OPS[@]} \ + ${GENERAL_VARS[@]} \ + ${REPLICA_OPS[@]} \ + ${REPLICA_VARS[@]} \ + > replica.yml + +#shellcheck disable=2068 +bosh int pxc-deployment.yml \ + ${GENERAL_OPS[@]} \ + ${GENERAL_VARS[@]} \ + ${SOURCE_OPS[@]} \ + ${SOURCE_VARS[@]} \ + > source.yml