-
Notifications
You must be signed in to change notification settings - Fork 2
Add 'dbdeployer deploy proxysql' and --with-proxysql for replication #46
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
Changes from all commits
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,97 @@ | ||||||
| // DBDeployer - The MySQL Sandbox | ||||||
| // Copyright © 2006-2021 Giuseppe Maxia | ||||||
| // | ||||||
| // 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 cmd | ||||||
|
|
||||||
| import ( | ||||||
| "fmt" | ||||||
| "path" | ||||||
|
|
||||||
| "github.com/ProxySQL/dbdeployer/common" | ||||||
| "github.com/ProxySQL/dbdeployer/defaults" | ||||||
| "github.com/ProxySQL/dbdeployer/providers" | ||||||
| "github.com/spf13/cobra" | ||||||
| ) | ||||||
|
|
||||||
| func deploySandboxProxySQL(cmd *cobra.Command, args []string) { | ||||||
| flags := cmd.Flags() | ||||||
| port, _ := flags.GetInt("port") | ||||||
| adminUser, _ := flags.GetString("admin-user") | ||||||
| adminPassword, _ := flags.GetString("admin-password") | ||||||
| skipStart, _ := flags.GetBool("skip-start") | ||||||
|
|
||||||
| p, err := providers.DefaultRegistry.Get("proxysql") | ||||||
|
Comment on lines
+30
to
+35
|
||||||
| if err != nil { | ||||||
| common.Exitf(1, "ProxySQL provider not available: %s", err) | ||||||
| } | ||||||
|
|
||||||
| if _, err := p.FindBinary(""); err != nil { | ||||||
| common.Exitf(1, "proxysql binary not found in PATH: %s", err) | ||||||
|
||||||
| common.Exitf(1, "proxysql binary not found in PATH: %s", err) | |
| common.Exitf(1, "%s", err) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,11 @@ | |
| package cmd | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "path" | ||
|
|
||
| "github.com/ProxySQL/dbdeployer/common" | ||
| "github.com/ProxySQL/dbdeployer/defaults" | ||
| "github.com/ProxySQL/dbdeployer/globals" | ||
| "github.com/ProxySQL/dbdeployer/providers" | ||
| "github.com/ProxySQL/dbdeployer/sandbox" | ||
|
|
@@ -102,6 +106,37 @@ func replicationSandbox(cmd *cobra.Command, args []string) { | |
| if err != nil { | ||
| common.Exitf(1, globals.ErrCreatingSandbox, err) | ||
| } | ||
|
|
||
| withProxySQL, _ := flags.GetBool("with-proxysql") | ||
| if withProxySQL { | ||
| // Determine the sandbox directory that was created | ||
| sandboxDir := path.Join(sd.SandboxDir, defaults.Defaults().MasterSlavePrefix+common.VersionToName(origin)) | ||
| if sd.DirName != "" { | ||
| sandboxDir = path.Join(sd.SandboxDir, sd.DirName) | ||
| } | ||
|
|
||
| // Read port info from child sandbox descriptions | ||
| masterDesc, err := common.ReadSandboxDescription(path.Join(sandboxDir, defaults.Defaults().MasterName)) | ||
|
Comment on lines
+112
to
+119
|
||
| if err != nil { | ||
| common.Exitf(1, "could not read master sandbox description: %s", err) | ||
| } | ||
| masterPort := masterDesc.Port[0] | ||
|
|
||
| var slavePorts []int | ||
| for i := 1; i < nodes; i++ { | ||
| nodeDir := path.Join(sandboxDir, fmt.Sprintf("%s%d", defaults.Defaults().NodePrefix, i)) | ||
| nodeDesc, err := common.ReadSandboxDescription(nodeDir) | ||
| if err != nil { | ||
| common.Exitf(1, "could not read node%d sandbox description: %s", i, err) | ||
| } | ||
| slavePorts = append(slavePorts, nodeDesc.Port[0]) | ||
| } | ||
|
|
||
| err = sandbox.DeployProxySQLForTopology(sandboxDir, masterPort, slavePorts, 0, "127.0.0.1") | ||
|
||
| if err != nil { | ||
| common.Exitf(1, "ProxySQL deployment failed: %s", err) | ||
| } | ||
|
Comment on lines
+135
to
+138
|
||
| } | ||
| } | ||
|
|
||
| var replicationCmd = &cobra.Command{ | ||
|
|
@@ -154,4 +189,5 @@ func init() { | |
| replicationCmd.PersistentFlags().BoolP(globals.SuperReadOnlyLabel, "", false, "Set super-read-only for slaves") | ||
| replicationCmd.PersistentFlags().Bool(globals.ReplHistoryDirLabel, false, "uses the replication directory to store mysql client history") | ||
| setPflag(replicationCmd, globals.ChangeMasterOptions, "", "CHANGE_MASTER_OPTIONS", "", "options to add to CHANGE MASTER TO", true) | ||
| replicationCmd.PersistentFlags().Bool("with-proxysql", false, "Deploy ProxySQL alongside the replication sandbox") | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,76 @@ | ||||||||||||||||||||||||||||||||||||||||||
| package sandbox | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+3
|
||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||
| "path" | ||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| "github.com/ProxySQL/dbdeployer/common" | ||||||||||||||||||||||||||||||||||||||||||
| "github.com/ProxySQL/dbdeployer/providers" | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // DeployProxySQLForTopology creates a ProxySQL sandbox configured for a MySQL topology. | ||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||
| // Parameters: | ||||||||||||||||||||||||||||||||||||||||||
| // - sandboxDir: parent sandbox directory (e.g. ~/sandboxes/rsandbox_8_4_4) | ||||||||||||||||||||||||||||||||||||||||||
| // - masterPort: MySQL master port | ||||||||||||||||||||||||||||||||||||||||||
| // - slavePorts: MySQL slave ports (empty for single topology) | ||||||||||||||||||||||||||||||||||||||||||
| // - proxysqlPort: port for ProxySQL admin interface (0 = auto-assign) | ||||||||||||||||||||||||||||||||||||||||||
| // - host: bind address (typically "127.0.0.1") | ||||||||||||||||||||||||||||||||||||||||||
| func DeployProxySQLForTopology(sandboxDir string, masterPort int, slavePorts []int, proxysqlPort int, host string) error { | ||||||||||||||||||||||||||||||||||||||||||
| reg := providers.DefaultRegistry | ||||||||||||||||||||||||||||||||||||||||||
| p, err := reg.Get("proxysql") | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("ProxySQL provider not available: %w", err) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if _, err := p.FindBinary(""); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("proxysql binary not found: %w", err) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| proxysqlDir := path.Join(sandboxDir, "proxysql") | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if proxysqlPort == 0 { | ||||||||||||||||||||||||||||||||||||||||||
| proxysqlPort = 6032 | ||||||||||||||||||||||||||||||||||||||||||
| // Try to find a free port | ||||||||||||||||||||||||||||||||||||||||||
| freePort, err := common.FindFreePort(proxysqlPort, []int{}, 1) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+36
|
||||||||||||||||||||||||||||||||||||||||||
| // Try to find a free port | |
| freePort, err := common.FindFreePort(proxysqlPort, []int{}, 1) | |
| // Try to find a free range of two consecutive ports (admin and MySQL interface) | |
| freePort, err := common.FindFreePort(proxysqlPort, []int{}, 2) |
Copilot
AI
Mar 24, 2026
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.
When proxysqlPort==0, this calls common.FindFreePort with an empty installedPorts list and ignores the returned error. This effectively always selects 6032 even if it conflicts with existing sandboxes, and can silently fall back to a busy port. Use the actual installed ports (e.g. from common.GetInstalledPorts on the sandbox home) and return an error if a free port cannot be found.
| proxysqlPort = 6032 | |
| // Try to find a free port | |
| freePort, err := common.FindFreePort(proxysqlPort, []int{}, 1) | |
| if err == nil { | |
| proxysqlPort = freePort | |
| } | |
| // Determine currently used ports from the sandbox home (parent of sandboxDir) | |
| sandboxHome := path.Dir(sandboxDir) | |
| installedPorts, err := common.GetInstalledPorts(sandboxHome) | |
| if err != nil { | |
| return fmt.Errorf("cannot determine installed ports in %s: %w", sandboxHome, err) | |
| } | |
| proxysqlPort = 6032 | |
| // Try to find a free port starting from the default ProxySQL admin port | |
| freePort, err := common.FindFreePort(proxysqlPort, installedPorts, 1) | |
| if err != nil { | |
| return fmt.Errorf("no free port available for ProxySQL starting at %d: %w", proxysqlPort, err) | |
| } | |
| proxysqlPort = freePort |
Copilot
AI
Mar 24, 2026
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.
Consider adding unit tests for DeployProxySQLForTopology, especially for backend string generation (HG0/HG1 mapping) and port selection behavior. The sandbox package has existing tests, but this new helper currently isn't covered.
Copilot
AI
Mar 24, 2026
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.
This helper always starts ProxySQL after creating the sandbox. When used from replication deployment, it should respect the user's --skip-start choice (i.e., avoid starting ProxySQL when the replication sandbox was deployed with SkipStart), or accept a skipStart parameter.
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.
This command always uses the requested/default admin port (6032) without checking for conflicts or reserving the required 2-port range (admin + mysql interface). Consider using common.GetInstalledPorts + common.FindFreePort (howMany=2), at least when the user did not explicitly set --port.