@@ -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
5358var (
@@ -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
137144const (
@@ -754,6 +761,231 @@ use the value from the flag, Not compatible with -fuse.`,
754761}
755762
756763func 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