// Init must be called before Dial is called. This is a more flexible version
// of InitDefault, but allows you to set more fields.
//
// The http.Client is used to authenticate API requests.
// The connset parameter is optional.
// If the dialer is nil, net.Conn is used.
func Init(auth *http.Client, connset *ConnSet, dialer Dialer) {
	if connset == nil {
		connset = NewConnSet()
	}
	dialClient.Lock()
	dialClient.c = &Client{
		Port:   port,
		Certs:  certs.NewCertSource("https://www.googleapis.com/sql/v1beta4/", auth, true),
		Conns:  connset,
		Dialer: dialer,
	}
	dialClient.Unlock()
}
func main() {
	flag.Parse()

	if *version {
		fmt.Println("Cloud SQL Proxy:", versionString)
		return
	}

	instList := stringList(*instances)
	projList := stringList(*projects)
	// TODO: it'd be really great to consolidate flag verification in one place.
	if len(instList) == 0 && *instanceSrc == "" && len(projList) == 0 && !*useFuse {
		projList = gcloudProject()
	}

	onGCE := onGCE()
	if err := checkFlags(onGCE); err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()
	client, err := authenticatedClient(ctx)
	if err != nil {
		log.Fatal(err)
	}

	ins, err := listInstances(ctx, client, projList)
	if err != nil {
		log.Fatal(err)
	}
	instList = append(instList, ins...)

	cfgs, err := CreateInstanceConfigs(*dir, *useFuse, instList, *instanceSrc)
	if err != nil {
		log.Fatal(err)
	}

	// All active connections are stored in this variable.
	connset := proxy.NewConnSet()

	// Initialize a source of new connections to Cloud SQL instances.
	var connSrc <-chan proxy.Conn
	if *useFuse {
		c, fuse, err := fuse.NewConnSrc(*dir, *fuseTmp, connset)
		if err != nil {
			log.Fatalf("Could not start fuse directory at %q: %v", *dir, err)
		}
		connSrc = c
		defer fuse.Close()
	} else {
		updates := make(chan string)
		if *instanceSrc != "" {
			go func() {
				for {
					err := metadata.Subscribe(*instanceSrc, func(v string, ok bool) error {
						if ok {
							updates <- v
						}
						return nil
					})
					if err != nil {
						log.Print(err)
					}
					time.Sleep(5 * time.Second)
				}
			}()
		}

		c, err := WatchInstances(*dir, cfgs, updates)
		if err != nil {
			log.Fatal(err)
		}
		connSrc = c
	}

	log.Print("Ready for new connections")

	(&proxy.Client{
		Port:  port,
		Certs: certs.NewCertSource(host, client, *checkRegion),
		Conns: connset,
	}).Run(connSrc)
}
func main() {
	flag.Parse()

	instances := strings.Split(*instances, ",")
	if len(instances) == 1 && instances[0] == "" {
		instances = nil
	}
	if err := Check(*dir, *useFuse, instances, *instanceSrc); err != nil {
		log.Fatal(err)
	}

	// All active connections are stored in this variable.
	connset := proxy.NewConnSet()

	// Initialize a source of new connections to Cloud SQL instances.
	var connSrc <-chan proxy.Conn
	if *useFuse {
		c, fuse, err := fuse.NewConnSrc(*dir, *fuseTmp, connset)
		if err != nil {
			log.Fatalf("Could not start fuse directory at %q: %v", *dir, err)
		}
		connSrc = c
		defer fuse.Close()
	} else {
		updates := make(chan string)
		if *instanceSrc != "" {
			go func() {
				for {
					err := metadata.Subscribe(*instanceSrc, func(v string, ok bool) error {
						if ok {
							updates <- v
						}
						return nil
					})
					if err != nil {
						log.Print(err)
					}
					time.Sleep(5 * time.Second)
				}
			}()
		}

		c, err := WatchInstances(*dir, instances, updates)
		if err != nil {
			log.Fatal(err)
		}
		connSrc = c
	}

	// Use the environment variable only if the flag hasn't been set.
	if *tokenFile == "" {
		*tokenFile = os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
	}

	var client *http.Client
	if file := *tokenFile; file != "" {
		all, err := ioutil.ReadFile(file)
		if err != nil {
			log.Fatalf("invalid json file %q: %v", file, err)
		}
		cfg, err := goauth.JWTConfigFromJSON(all, sqlScope)
		if err != nil {
			log.Fatalf("invalid json file %q: %v", file, err)
		}
		client = auth.NewClientFrom(cfg.TokenSource(context.Background()))
	} else if *token != "" || onGCE() {
		// Passing token == "" causes the GCE metadata server to be used.
		client = auth.NewAuthenticatedClient(*token)
	} else {
		log.Fatal("No authentication method available! When not running on Google Compute Engine, provide the -credential_file flag.")
	}

	log.Print("Socket prefix: " + *dir)

	(&proxy.Client{
		Port:  *port,
		Certs: certs.NewCertSource(*host, client, *checkRegion),
		Conns: connset,
	}).Run(connSrc)
}