func NewFleetClient() (client.API, error) { ep, _ := url.Parse(os.Getenv("FLEET_URL")) dialUnix := ep.Scheme == "unix" || ep.Scheme == "file" dialFunc := net.Dial if dialUnix { ep.Host = "domain-sock" ep.Scheme = "http" sockPath := ep.Path ep.Path = "" dialFunc = func(string, string) (net.Conn, error) { return net.Dial("unix", sockPath) } } tr := &http.Transport{ Dial: dialFunc, } cl := http.Client{Transport: tr} httpClient, err := client.NewHTTPClient(&cl, *ep) if err != nil { return nil, err } else { return httpClient, nil } }
func newFleetAPIClient(fleetEndpoint string, socksProxy string) (client.API, error) { u, err := url.Parse(fleetEndpoint) if err != nil { return nil, err } httpClient := &http.Client{} if socksProxy != "" { log.Printf("using proxy %s\n", socksProxy) netDialler := &net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, } dialer, err := proxy.SOCKS5("tcp", socksProxy, nil, netDialler) if err != nil { log.Fatalf("error with proxy %s: %v\n", socksProxy, err) } httpClient.Transport = &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: dialer.Dial, TLSHandshakeTimeout: 10 * time.Second, } } return client.NewHTTPClient(httpClient, *u) }
func getMachines(endpoint, healthzPort string, metadata map[string][]string, reverseLookup bool) ([]string, error) { dialFunc := net.Dial machineList := make([]string, 0) u, err := url.Parse(endpoint) if err != nil { return nil, err } if u.Scheme == "unix" { endpoint = "http://domain-sock/" dialFunc = func(network, addr string) (net.Conn, error) { return net.Dial("unix", u.Path) } } c := &http.Client{ Transport: &http.Transport{ Dial: dialFunc, DisableKeepAlives: true, }, } fleetClient, err := client.NewHTTPClient(c, endpoint) if err != nil { return nil, err } machines, err := fleetClient.Machines() if err != nil { return nil, err } for _, m := range machines { if hasMetadata(m, metadata) && isHealthy(m.PublicIP, healthzPort) { if reverseLookup { hostnames, err := net.LookupAddr(m.PublicIP) if err != nil { return nil, err } if len(hostnames) < 1 { return nil, errors.New("Could not get hostname for IP " + m.PublicIP) } hostname := hostnames[0] // remove trailing dot if hostname[len(hostname)-1] == '.' { hostname = hostname[:len(hostname)-1] } machineList = append(machineList, hostname) } else { machineList = append(machineList, m.PublicIP) } } } return machineList, nil }
func getHTTPClient() (client.API, error) { dialFunc := func(string, string) (net.Conn, error) { return net.Dial("unix", "/var/run/fleet.sock") } trans := http.Transport{ Dial: dialFunc, } hc := http.Client{ Transport: &trans, } return client.NewHTTPClient(&hc) }
func getHTTPClient(driverEndpoint string) (client.API, error) { log.Printf("Using API connection for requests") endpoint, err := url.Parse(driverEndpoint) if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{}, } httpClient := http.Client{ Transport: &trans, } return client.NewHTTPClient(&httpClient, *endpoint) }
func getHTTPClient() (client.API, error) { dialDomainSocket := strings.HasPrefix(globalFlags.Endpoint, "/") tunnelFunc := net.Dial tun := getTunnelFlag() if tun != "" { sshClient, err := ssh.NewSSHClient(globalFlags.SSHUserName, tun, getChecker(), false) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } tunnelFunc = func(net, addr string) (net.Conn, error) { return sshClient.Dial(net, addr) } } dialFunc := tunnelFunc if dialDomainSocket { dialFunc = func(net, addr string) (net.Conn, error) { return tunnelFunc("unix", globalFlags.Endpoint) } } trans := pkg.LoggingHTTPTransport{ http.Transport{ Dial: dialFunc, }, } hc := http.Client{ Transport: &trans, } endpoint := globalFlags.Endpoint if dialDomainSocket { endpoint = "http://domain-sock/" } else if !strings.HasPrefix(endpoint, "http") { endpoint = fmt.Sprintf("http://%s", endpoint) } return client.NewHTTPClient(&hc, endpoint) }
func newFleet() *fleetClient { cl := &http.Client{ Transport: &http.Transport{ Dial: func(string, string) (net.Conn, error) { return net.Dial("unix", "/var/run/fleet.sock") }, }, } url, err := url.Parse("http://localhost/") if err != nil { panic(err) } api, err := client.NewHTTPClient(cl, *url) if err != nil { panic(err) } return &fleetClient{api, new(sync.Mutex)} }
func getTunnelClient(driverEndpoint string, tunnelEndpoint string, maxRetries int) (client.API, error) { log.Printf("Using Fleet Tunnel connection for requests") getSSHClient := func() (interface{}, error) { return ssh.NewSSHClient("core", driverEndpoint, nil, false, defaultTimeout) } result, err := retry(getSSHClient, maxRetries) if err != nil { return nil, err } sshClient := result.(*ssh.SSHForwardingClient) dial := func(string, string) (net.Conn, error) { cmd := fmt.Sprintf("fleetctl fd-forward %s", tunnelEndpoint) return ssh.DialCommand(sshClient, cmd) } // This is needed to fake out the client - it isn't used // since we're overloading the dial method on the transport // but the client complains if it isn't set fakeHTTPEndpoint, err := url.Parse("http://domain-sock") if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dial, }, } httpClient := http.Client{ Transport: &trans, } return client.NewHTTPClient(&httpClient, *fakeHTTPEndpoint) }
// newFleetInterface ... creates a new interface to interact to the fleet cluster service func newFleetClient() (*fleetClient, error) { glog.V(3).Infof("Creating a client to fleet service, endpoint: %s", config.fleetSocket) service := new(fleetClient) // step: parse the verify the fleet endpoint location, err := url.Parse(config.fleetSocket) if err != nil { return nil, err } // step: ensure we are using a fleet socket if location.Scheme != "unix" { return nil, fmt.Errorf("the fleet endpoint should be a unix socket file, please read documentation") } location.Scheme = "http" location.Host = "domain-sock" socket_path := location.Path location.Path = "" // step: create the http client service.httpClient = &http.Client{ Timeout: time.Duration(10) * time.Second, Transport: &http.Transport{ Dial: func(network, addr string) (net.Conn, error) { return net.Dial("unix", socket_path) }, DisableKeepAlives: true, }, } // step: create the fleet client service.client, err = fleet.NewHTTPClient(service.httpClient, *location) if err != nil { return nil, fmt.Errorf("unable to create the fleet api client, error: %s", err) } return service, nil }
func newDeployer() (*deployer, error) { u, err := url.Parse(*fleetEndpoint) if err != nil { return &deployer{}, err } httpClient := &http.Client{} if *socksProxy != "" { log.Printf("using proxy %s\n", *socksProxy) netDialler := &net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, } dialer, err := proxy.SOCKS5("tcp", *socksProxy, nil, netDialler) if err != nil { log.Fatalf("error with proxy %s: %v\n", socksProxy, err) } httpClient.Transport = &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: dialer.Dial, TLSHandshakeTimeout: 10 * time.Second, } } fleetHTTPAPIClient, err := client.NewHTTPClient(httpClient, *u) if err != nil { return &deployer{}, err } fleetHTTPAPIClient = loggingFleetAPI{fleetHTTPAPIClient} if !*destroyFlag { log.Println("destroy not enabled (use -destroy to enable)") fleetHTTPAPIClient = noDestroyFleetAPI{fleetHTTPAPIClient} } serviceDefinitionClient := &httpServiceDefinitionClient{httpClient: &http.Client{}, rootURI: *rootURI} return &deployer{fleetapi: fleetHTTPAPIClient, serviceDefinitionClient: serviceDefinitionClient}, nil }
// getAPI returns an API to Fleet. func getAPI(hostAddr string, maxRetries int) (client.API, error) { if hostAddr == "" { return nullAPI{}, nil } getSSHClient := func() (interface{}, error) { return ssh.NewSSHClient("core", hostAddr, nil, false, time.Second*10) } result, err := retry(getSSHClient, maxRetries) if err != nil { return nil, err } sshClient := result.(*ssh.SSHForwardingClient) dial := func(string, string) (net.Conn, error) { cmd := "fleetctl fd-forward /var/run/fleet.sock" return ssh.DialCommand(sshClient, cmd) } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dial, }, } httpClient := http.Client{ Transport: &trans, } // since dial() ignores the endpoint, we just need something here that // won't make the HTTP client complain. endpoint, err := url.Parse("http://domain-sock") return client.NewHTTPClient(&httpClient, *endpoint) }
func getHTTPClient() (client.API, error) { endpoints := strings.Split(globalFlags.Endpoint, ",") if len(endpoints) > 1 { log.Warningf("multiple endpoints provided but only the first (%s) is used", endpoints[0]) } ep, err := url.Parse(endpoints[0]) if err != nil { return nil, err } if len(ep.Scheme) == 0 { return nil, errors.New("URL scheme undefined") } tun := getTunnelFlag() tunneling := tun != "" dialUnix := ep.Scheme == "unix" || ep.Scheme == "file" tunnelFunc := net.Dial if tunneling { sshClient, err := ssh.NewSSHClient(globalFlags.SSHUserName, tun, getChecker(), true, getSSHTimeoutFlag()) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } if dialUnix { tgt := ep.Path tunnelFunc = func(string, string) (net.Conn, error) { log.Debugf("Establishing remote fleetctl proxy to %s", tgt) cmd := fmt.Sprintf(`fleetctl fd-forward %s`, tgt) return ssh.DialCommand(sshClient, cmd) } } else { tunnelFunc = sshClient.Dial } } dialFunc := tunnelFunc if dialUnix { // This commonly happens if the user misses the leading slash after the scheme. // For example, "unix://var/run/fleet.sock" would be parsed as host "var". if len(ep.Host) > 0 { return nil, fmt.Errorf("unable to connect to host %q with scheme %q", ep.Host, ep.Scheme) } // The Path field is only used for dialing and should not be used when // building any further HTTP requests. sockPath := ep.Path ep.Path = "" // If not tunneling to the unix socket, http.Client will dial it directly. // http.Client does not natively support dialing a unix domain socket, so the // dial function must be overridden. if !tunneling { dialFunc = func(string, string) (net.Conn, error) { return net.Dial("unix", sockPath) } } // http.Client doesn't support the schemes "unix" or "file", but it // is safe to use "http" as dialFunc ignores it anyway. ep.Scheme = "http" // The Host field is not used for dialing, but will be exposed in debug logs. ep.Host = "domain-sock" } tlsConfig, err := pkg.ReadTLSConfigFiles(globalFlags.CAFile, globalFlags.CertFile, globalFlags.KeyFile) if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dialFunc, TLSClientConfig: tlsConfig, }, } hc := http.Client{ Transport: &trans, } return client.NewHTTPClient(&hc, *ep) }
func getHTTPClient() (client.API, error) { ep, err := url.Parse(globalFlags.Endpoint) if err != nil { return nil, err } if len(ep.Scheme) == 0 { return nil, errors.New("URL scheme undefined") } tunnelFunc := net.Dial var tunneling bool tun := getTunnelFlag() if tun != "" { tunneling = true sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false, getSSHTimeoutFlag()) if err != nil { return nil, fmt.Errorf("failed initializing SSH client: %v", err) } tunnelFunc = func(net, addr string) (net.Conn, error) { return sshClient.Dial(net, addr) } } dialFunc := tunnelFunc if ep.Scheme == "unix" || ep.Scheme == "file" { if tunneling { return nil, errors.New("unable to dial unix socket through SSH tunnel") } // This commonly happens if the user misses the leading slash after the scheme. // For example, "unix://var/run/fleet.sock" would be parsed as host "var". if len(ep.Host) > 0 { return nil, fmt.Errorf("unable to connect to host %q with scheme %q", ep.Host, ep.Scheme) } // The Path field is only used for dialing and should not be used when // building any further HTTP requests. sockPath := ep.Path ep.Path = "" // http.Client does not natively support dialing a unix domain socket, so the // dial function must be overridden. dialFunc = func(net, addr string) (net.Conn, error) { return tunnelFunc("unix", sockPath) } // http.Client doesn't support the schemes "unix" or "file", but it // is safe to use "http" as dialFunc ignores it anyway. ep.Scheme = "http" // The Host field is not used for dialing, but will be exposed in debug logs. ep.Host = "domain-sock" } tlsConfig, err := pkg.ReadTLSConfigFiles(globalFlags.CAFile, globalFlags.CertFile, globalFlags.KeyFile) if err != nil { return nil, err } trans := pkg.LoggingHTTPTransport{ Transport: http.Transport{ Dial: dialFunc, TLSClientConfig: tlsConfig, }, } hc := http.Client{ Transport: &trans, } return client.NewHTTPClient(&hc, *ep) }
func fleetAPI() fleet.API { if *fleetEndpoint == "" { glog.Fatalln("No --fleet-fleetEndpoint provided.") } var fleetClient fleet.API switch *fleetDriver { case "http": ep, err := url.Parse(*fleetEndpoint) if err != nil { glog.Fatal(err) } var trans http.RoundTripper switch ep.Scheme { case "unix", "file": // This commonly happens if the user misses the leading slash after the scheme. // For example, "unix://var/run/fleet.sock" would be parsed as host "var". if len(ep.Host) > 0 { glog.Fatalf("unable to connect to host %q with scheme %q\n", ep.Host, ep.Scheme) } // The Path field is only used for dialing and should not be used when // building any further HTTP requests. sockPath := ep.Path ep.Path = "" // http.Client doesn't support the schemes "unix" or "file", but it // is safe to use "http" as dialFunc ignores it anyway. ep.Scheme = "http" // The Host field is not used for dialing, but will be exposed in debug logs. ep.Host = "domain-sock" trans = &http.Transport{ Dial: func(s, t string) (net.Conn, error) { // http.Client does not natively support dialing a unix domain socket, so the // dial function must be overridden. return net.Dial("unix", sockPath) }, } case "http", "https": trans = http.DefaultTransport default: glog.Fatalf("Unknown scheme in fleet fleetEndpoint: %s\n", ep.Scheme) } c := &http.Client{ Transport: trans, } fleetClient, err = fleet.NewHTTPClient(c, *ep) if err != nil { glog.Fatalf("Failed to create FleetHttpClient: %s\n", err) } case "etcd": // Code vaguely oriented on fleetctls getRegistryClient() // https://github.com/coreos/fleet/blob/2e21d3bfd5959a70513c5e0d3c2500dc3c0811cf/fleetctl/fleetctl.go#L312 timeout := time.Duration(5 * time.Second) machines := strings.Split(*fleetEndpoint, ",") trans := &http.Transport{} eClient, err := etcd.NewClient(machines, trans, timeout) if err != nil { glog.Fatalln("Failed to build etcd client: " + err.Error()) } reg := registry.NewEtcdRegistry(eClient, registry.DefaultKeyPrefix) fleetClient = &fleet.RegistryClient{reg} default: glog.Fatalf("Unknown fleet driver: %s\n", *fleetDriver) } glog.Infof("using fleet driver: %s with fleetEndpoint: %s", *fleetDriver, *fleetEndpoint) return fleetClient }