Skip to content

Commit 28a434e

Browse files
committed
Add compatability layer so that proxy v1 can use proxy v2 code.
1 parent f0c2140 commit 28a434e

File tree

6 files changed

+1500
-13
lines changed

6 files changed

+1500
-13
lines changed

build.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,16 @@ function build() {
3838

3939
## test - Runs local unit tests.
4040
function test() {
41-
go test -v -race -cover -short
41+
go test -v -race -cover -short ./...
42+
}
43+
44+
## test_translatev2 - Runs e2e tests for the transelatev2 code path tests
45+
function test_translatev2() {
46+
if [[ ! -f .envrc ]] ; then
47+
write_e2e_env .envrc
48+
fi
49+
source .envrc
50+
go test -v -race -cover ./translatev2
4251
}
4352

4453
## e2e - Runs end-to-end integration tests.

cmd/cloud_sql_proxy/cloud_sql_proxy.go

Lines changed: 234 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ import (
2424
"errors"
2525
"flag"
2626
"fmt"
27+
"io"
2728
"io/ioutil"
29+
"net"
2830
"net/http"
2931
"os"
3032
"os/signal"
3133
"path/filepath"
34+
"strconv"
3235
"strings"
3336
"sync"
3437
"syscall"
@@ -48,6 +51,8 @@ import (
4851
"golang.org/x/oauth2"
4952
goauth "golang.org/x/oauth2/google"
5053
sqladmin "google.golang.org/api/sqladmin/v1beta4"
54+
55+
proxyv2cmd "github.com/GoogleCloudPlatform/cloud-sql-proxy/v2/cmd"
5156
)
5257

5358
var (
@@ -132,6 +137,8 @@ https://sqladmin.googleapis.com`,
132137
// Settings for healthcheck
133138
useHTTPHealthCheck = flag.Bool("use_http_health_check", false, "When set, creates an HTTP server that checks and communicates the health of the proxy client.")
134139
healthCheckPort = flag.String("health_check_port", "8090", "When applicable, health checks take place on this port number. Defaults to 8090.")
140+
141+
_ = flag.Bool("legacy-v1-proxy", false, "If true, the proxy will run in legacy v1 mode.")
135142
)
136143

137144
const (
@@ -754,6 +761,231 @@ use the value from the flag, Not compatible with -fuse.`,
754761
}
755762

756763
func main() {
757-
code := runProxy()
758-
os.Exit(code)
764+
translatedArgs, logDebugStdout, verbose, ok := translateV2Args()
765+
if !ok {
766+
code := runProxy()
767+
os.Exit(code)
768+
}
769+
770+
opts := []proxyv2cmd.Option{
771+
proxyv2cmd.WithProxyV1Compatibility(),
772+
proxyv2cmd.WithProxyV1Verbose(verbose),
773+
}
774+
if logDebugStdout {
775+
opts = append(opts, proxyv2cmd.WithProxyV1LogDebugStdout())
776+
}
777+
778+
v2cmd := proxyv2cmd.NewCommand(opts...)
779+
v2cmd.SetArgs(translatedArgs)
780+
proxyv2cmd.ExecuteCommand(v2cmd)
781+
}
782+
783+
// translateV2Args translates the v1 command line args to V2 args.
784+
// Checks the command line arguments applied to the v1 proxy and then
785+
// translates it for the v2 proxy.
786+
//
787+
// If the arguments use a feature that is not supported in Proxy v2, this
788+
// returns false for OK, indicating that the legacy proxy v1 should run the
789+
// code.
790+
//
791+
// Returns:
792+
// - v2args the arguments translated for the v2 command
793+
// - logDebugStdout true if the v1 -log_debug_stdout flag was set
794+
// - verbose true if the v1 -verbose flag was set (default true)
795+
// - ok true when it is OK to use the v2 proxy command
796+
func translateV2Args() (v2args []string, logDebugStdout, verbose, ok bool) {
797+
// Check for --legacy-v1-proxy before anything else
798+
for _, arg := range os.Args {
799+
if arg == "--legacy-v1-proxy" || arg == "-legacy-v1-proxy" {
800+
return nil, false, false, false
801+
}
802+
}
803+
804+
fs := flag.NewFlagSet("translate", flag.ContinueOnError)
805+
fs.SetOutput(io.Discard)
806+
807+
credentialFile := fs.String("credential_file", "", "")
808+
token := fs.String("token", "", "")
809+
loginToken := fs.String("login_token", "", "")
810+
enableIAMLogin := fs.Bool("enable_iam_login", false, "")
811+
dir := fs.String("dir", "", "")
812+
useFuse := fs.Bool("fuse", false, "")
813+
fuseTmp := fs.String("fuse_tmp", "", "")
814+
healthCheckPort := fs.String("health_check_port", "", "")
815+
useHTTPHealthCheck := fs.Bool("use_http_health_check", false, "")
816+
host := fs.String("host", "", "")
817+
ipAddressTypes := fs.String("ip_address_types", "PUBLIC,PRIVATE", "")
818+
maxConnections := fs.Uint64("max_connections", 0, "")
819+
quiet := fs.Bool("quiet", false, "")
820+
quotaProject := fs.String("quota_project", "", "")
821+
skipFailedInstanceConfig := fs.Bool("skip_failed_instance_config", false, "")
822+
structuredLogs := fs.Bool("structured_logs", false, "")
823+
termTimeout := fs.Duration("term_timeout", 0, "")
824+
version := fs.Bool("version", false, "")
825+
verboseFlag := fs.Bool("verbose", true, "")
826+
logDebugStdoutFlag := fs.Bool("log_debug_stdout", false, "")
827+
828+
// Untranslatable flags
829+
_ = fs.Bool("check_region", false, "")
830+
_ = fs.String("projects", "", "")
831+
_ = fs.String("instances_metadata", "", "")
832+
_ = fs.Duration("refresh_config_throttle", 0, "")
833+
_ = fs.Uint64("fd_rlimit", 0, "")
834+
_ = fs.Bool("legacy-v1-proxy", false, "")
835+
836+
var instances stringListValue
837+
fs.Var(&instances, "instances", "")
838+
839+
if err := fs.Parse(os.Args[1:]); err != nil {
840+
return nil, false, false, false
841+
}
842+
843+
// Check for unsupported flags being set
844+
unsupportedSet := false
845+
fs.Visit(func(f *flag.Flag) {
846+
switch f.Name {
847+
case "check_region", "projects", "instances_metadata",
848+
"refresh_config_throttle", "fd_rlimit", "legacy-v1-proxy":
849+
unsupportedSet = true
850+
}
851+
})
852+
if unsupportedSet {
853+
return nil, false, false, false
854+
}
855+
856+
var args []string
857+
fs.Visit(func(f *flag.Flag) {
858+
switch f.Name {
859+
case "credential_file":
860+
args = append(args, "--credentials-file", *credentialFile)
861+
case "token":
862+
args = append(args, "--token", *token)
863+
case "login_token":
864+
args = append(args, "--login-token", *loginToken)
865+
case "enable_iam_login":
866+
if *enableIAMLogin {
867+
args = append(args, "--auto-iam-authn")
868+
}
869+
case "dir":
870+
args = append(args, "--unix-socket", *dir)
871+
case "fuse":
872+
if *useFuse {
873+
args = append(args, "--fuse", *dir)
874+
}
875+
case "fuse_tmp":
876+
args = append(args, "--fuse-temp-dir", *fuseTmp)
877+
case "health_check_port":
878+
args = append(args, "--http-port", *healthCheckPort)
879+
case "use_http_health_check":
880+
if *useHTTPHealthCheck {
881+
args = append(args, "--health-check")
882+
}
883+
case "host":
884+
args = append(args, "--sqladmin-api-endpoint", *host)
885+
case "max_connections":
886+
args = append(args, "--max-connections", strconv.FormatUint(*maxConnections, 10))
887+
case "quiet":
888+
if *quiet {
889+
args = append(args, "--quiet")
890+
}
891+
case "quota_project":
892+
args = append(args, "--quota-project", *quotaProject)
893+
case "skip_failed_instance_config":
894+
if *skipFailedInstanceConfig {
895+
args = append(args, "--skip-failed-instance-config")
896+
}
897+
case "structured_logs":
898+
if *structuredLogs {
899+
args = append(args, "--structured-logs")
900+
}
901+
case "term_timeout":
902+
args = append(args, "--max-sigterm-delay", termTimeout.String())
903+
case "version":
904+
if *version {
905+
args = append(args, "--version")
906+
}
907+
}
908+
})
909+
910+
// ip_address_types handling
911+
ipTypesSet := false
912+
fs.Visit(func(f *flag.Flag) {
913+
if f.Name == "ip_address_types" {
914+
ipTypesSet = true
915+
}
916+
})
917+
918+
if !ipTypesSet {
919+
args = append(args, "--auto-ip")
920+
} else {
921+
types := strings.Split(*ipAddressTypes, ",")
922+
hasPublic := false
923+
hasPrivate := false
924+
for _, t := range types {
925+
switch strings.TrimSpace(t) {
926+
case "PUBLIC":
927+
hasPublic = true
928+
case "PRIVATE":
929+
hasPrivate = true
930+
default:
931+
// Unknown type, fallback to v1
932+
return nil, false, false, false
933+
}
934+
}
935+
if hasPublic && hasPrivate {
936+
args = append(args, "--auto-ip")
937+
} else if hasPrivate {
938+
args = append(args, "--private-ip")
939+
} else if hasPublic {
940+
// default in v2 is public
941+
}
942+
}
943+
944+
// instances handling
945+
for _, inst := range instances {
946+
parts := strings.SplitN(inst, "=", 2)
947+
connName := parts[0]
948+
if len(parts) == 1 {
949+
args = append(args, connName)
950+
continue
951+
}
952+
953+
opts := strings.SplitN(parts[1], ":", 2)
954+
if len(opts) != 2 {
955+
return nil, false, false, false // Invalid format
956+
}
957+
958+
netType := opts[0]
959+
netAddr := opts[1]
960+
961+
switch netType {
962+
case "tcp":
963+
if strings.Contains(netAddr, ":") {
964+
// host:port
965+
h, p, err := net.SplitHostPort(netAddr)
966+
if err != nil {
967+
return nil, false, false, false
968+
}
969+
args = append(args, fmt.Sprintf("%s?address=%s&port=%s", connName, h, p))
970+
} else {
971+
// just port
972+
args = append(args, fmt.Sprintf("%s?port=%s", connName, netAddr))
973+
}
974+
case "unix":
975+
if strings.HasPrefix(netAddr, "/") {
976+
args = append(args, fmt.Sprintf("%s?unix-socket-path=%s", connName, netAddr))
977+
} else {
978+
args = append(args, fmt.Sprintf("%s?unix-socket=%s", connName, netAddr))
979+
}
980+
default:
981+
return nil, false, false, false // Unsupported network
982+
}
983+
}
984+
985+
// V2 requires at least one instance OR fuse mode OR version
986+
if len(instances) == 0 && !*useFuse && !*version {
987+
return nil, false, false, false
988+
}
989+
990+
return args, *logDebugStdoutFlag, *verboseFlag, true
759991
}

0 commit comments

Comments
 (0)