Esempio n. 1
0
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)
}
Esempio n. 3
0
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
}
Esempio n. 4
0
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)
}
Esempio n. 6
0
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)
}
Esempio n. 7
0
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)
}
Esempio n. 9
0
// 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
}
Esempio n. 10
0
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)
}
Esempio n. 12
0
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)
}
Esempio n. 13
0
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)
}
Esempio n. 14
0
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
}