// NewClient initializes a new API client for the given host and API version. // It uses the given http client as transport. // It also initializes the custom http headers to add to each request. // // It won't send any version information if the version number is empty. It is // highly recommended that you set a version or your client may break if the // server is upgraded. func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { proto, addr, basePath, err := ParseHost(host) if err != nil { return nil, err } if client == nil { client = &http.Client{} } if client.Transport == nil { // setup the transport, if not already present transport := new(http.Transport) sockets.ConfigureTransport(transport, proto, addr) client.Transport = transport } return &Client{ host: host, proto: proto, addr: addr, basePath: basePath, client: client, version: version, customHTTPHeaders: httpHeaders, }, nil }
// NewClient creates a new plugin client (http). func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) { tr := &http.Transport{} c, err := tlsconfig.Client(tlsConfig) if err != nil { return nil, err } tr.TLSClientConfig = c u, err := url.Parse(addr) if err != nil { return nil, err } socket := u.Host if socket == "" { // valid local socket addresses have the host empty. socket = u.Path } if err := sockets.ConfigureTransport(tr, u.Scheme, socket); err != nil { return nil, err } scheme := httpScheme(u) clientTransport := transport.NewHTTPTransport(tr, scheme, socket) return NewClientWithTransport(clientTransport), nil }
func (provider *Docker) createClient() (client.APIClient, error) { var httpClient *http.Client httpHeaders := map[string]string{ // FIXME(vdemeester) use version here O:) "User-Agent": "Traefik", } if provider.TLS != nil { tlsOptions := tlsconfig.Options{ CAFile: provider.TLS.CA, CertFile: provider.TLS.Cert, KeyFile: provider.TLS.Key, InsecureSkipVerify: provider.TLS.InsecureSkipVerify, } config, err := tlsconfig.Client(tlsOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(provider.Endpoint) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) httpClient = &http.Client{ Transport: tr, } } return client.NewClient(provider.Endpoint, DockerAPIVersion, httpClient, httpHeaders) }
func (provider *Docker) createClient() (client.APIClient, error) { var httpClient *http.Client httpHeaders := map[string]string{ "User-Agent": "Traefik " + version.Version, } if provider.TLS != nil { config, err := provider.TLS.CreateTLSConfig() if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(provider.Endpoint) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) httpClient = &http.Client{ Transport: tr, } } var version string if provider.SwarmMode { version = SwarmAPIVersion } else { version = DockerAPIVersion } return client.NewClient(provider.Endpoint, version, httpClient, httpHeaders) }
// NewClient initializes a new API client for the given host and API version. // It uses the given http client as transport. // It also initializes the custom http headers to add to each request. // // It won't send any version information if the version number is empty. It is // highly recommended that you set a version or your client may break if the // server is upgraded. func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { proto, addr, basePath, err := ParseHost(host) if err != nil { return nil, err } if client != nil { if _, ok := client.Transport.(*http.Transport); !ok { return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport) } } else { transport := new(http.Transport) sockets.ConfigureTransport(transport, proto, addr) client = &http.Client{ Transport: transport, } } return &Client{ host: host, proto: proto, addr: addr, basePath: basePath, client: client, version: version, customHTTPHeaders: httpHeaders, }, nil }
func (d *Daemon) getClientConfig() (*clientConfig, error) { var ( transport *http.Transport scheme string addr string proto string ) if d.UseDefaultTLSHost { option := &tlsconfig.Options{ CAFile: "fixtures/https/ca.pem", CertFile: "fixtures/https/client-cert.pem", KeyFile: "fixtures/https/client-key.pem", } tlsConfig, err := tlsconfig.Client(*option) if err != nil { return nil, err } transport = &http.Transport{ TLSClientConfig: tlsConfig, } addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort) scheme = "https" proto = "tcp" } else if d.UseDefaultHost { addr = opts.DefaultUnixSocket proto = "unix" scheme = "http" transport = &http.Transport{} } else { addr = d.sockPath() proto = "unix" scheme = "http" transport = &http.Transport{} } if err := sockets.ConfigureTransport(transport, proto, addr); err != nil { return nil, err } transport.DisableKeepAlives = true return &clientConfig{ transport: transport, scheme: scheme, addr: addr, }, nil }
// NewClient creates a new plugin client (http). func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) { tr := &http.Transport{} c, err := tlsconfig.Client(tlsConfig) if err != nil { return nil, err } tr.TLSClientConfig = c protoAndAddr := strings.Split(addr, "://") sockets.ConfigureTransport(tr, protoAndAddr[0], protoAndAddr[1]) scheme := protoAndAddr[0] if scheme != "https" { scheme = "http" } return &Client{&http.Client{Transport: tr}, scheme, protoAndAddr[1]}, nil }
func (d *Daemon) getClientConfig() (*clientConfig, error) { var ( transport *http.Transport scheme string addr string proto string ) if d.useDefaultTLSHost { option := &tlsconfig.Options{ CAFile: "fixtures/https/ca.pem", CertFile: "fixtures/https/client-cert.pem", KeyFile: "fixtures/https/client-key.pem", } tlsConfig, err := tlsconfig.Client(*option) if err != nil { return nil, err } transport = &http.Transport{ TLSClientConfig: tlsConfig, } addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort) scheme = "https" proto = "tcp" } else if d.useDefaultHost { addr = opts.DefaultUnixSocket proto = "unix" scheme = "http" transport = &http.Transport{} } else { addr = filepath.Join(d.folder, "docker.sock") proto = "unix" scheme = "http" transport = &http.Transport{} } d.c.Assert(sockets.ConfigureTransport(transport, proto, addr), check.IsNil) return &clientConfig{ transport: transport, scheme: scheme, addr: addr, }, nil }
// NewClient creates an http client for the specific host func NewClient(host string) (*http.Client, error) { // FIXME(vdemeester) 10*time.Second timeout of SockRequest… ? proto, addr, _, err := dclient.ParseHost(host) if err != nil { return nil, err } transport := new(http.Transport) if proto == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" { // Setup the socket TLS configuration. tlsConfig, err := getTLSConfig() if err != nil { return nil, err } transport = &http.Transport{TLSClientConfig: tlsConfig} } err = sockets.ConfigureTransport(transport, proto, addr) return &http.Client{ Transport: transport, }, err }
// NewClient initializes a new API client for the given host and API version. // It uses the given http client as transport. // It also initializes the custom http headers to add to each request. // // It won't send any version information if the version number is empty. It is // highly recommended that you set a version or your client may break if the // server is upgraded. func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { proto, addr, basePath, err := ParseHost(host) if err != nil { return nil, err } if client != nil { if _, ok := client.Transport.(*http.Transport); !ok { return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport) } } else { transport := new(http.Transport) sockets.ConfigureTransport(transport, proto, addr) client = &http.Client{ Transport: transport, } } scheme := "http" tlsConfig := resolveTLSConfig(client.Transport) if tlsConfig != nil { // TODO(stevvooe): This isn't really the right way to write clients in Go. // `NewClient` should probably only take an `*http.Client` and work from there. // Unfortunately, the model of having a host-ish/url-thingy as the connection // string has us confusing protocol and transport layers. We continue doing // this to avoid breaking existing clients but this should be addressed. scheme = "https" } return &Client{ scheme: scheme, host: host, proto: proto, addr: addr, basePath: basePath, client: client, version: version, customHTTPHeaders: httpHeaders, }, nil }
func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, error) { if tlsOptions == nil { // let the api client configure the default transport. return nil, nil } config, err := tlsconfig.Client(*tlsOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(host) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) return &http.Client{ Transport: tr, }, nil }
func (s *Swarm) Exec(cmd []string, containName string) (types.HijackedResponse, error) { var err error defer func() { if err != nil { log.WithFields(log.Fields{ "cmd": cmd, "ContainName": containName, "err": err.Error(), }).Error("swarm exec error") } }() timeEnd := time.Now().Add(s.config.SwarmRetryTimeoutAll) defaultHeaders := map[string]string{"User-Agent": s.config.SwarmUserAgent} // for set client.Timeout do what engine-api do start // transport = defaultTransport(proto, addr) transport := new(http.Transport) sockets.ConfigureTransport(transport, "tcp", s.host) // for set client.Timeout do what engine-api do end c := &http.Client{ Timeout: s.config.SwarmRetryTimeout, Transport: transport, } // get last swarm host when connect error and retry once bRegetSwarmHost := false for i := 1; i <= s.config.SwarmRetryTimes; i++ { if timeEnd.Before(time.Now()) { return types.HijackedResponse{}, errors.New(fmt.Sprintf("time out after %+v\n", s.config.SwarmRetryTimeoutAll)) } cli, err := client.NewClient("tcp://"+s.host, s.ApiVersion, c, defaultHeaders) if err != nil { log.WithFields(log.Fields{ "cmd": cmd, "ContainName": containName, "RetryTimes": i, "err": err.Error(), }).Error("swarm NewClient error") if !bRegetSwarmHost && s.consul != nil { log.Info("try to get swarm host from consul once again") bRegetSwarmHost = true swarmHost, err := s.consul.GetVal(s.config.SwarmHostKey) if err != nil { log.WithFields(log.Fields{ "err": err.Error(), }).Error("consul connect error") time.Sleep(s.config.SwarmRetryInterval) } else if swarmHost == "" { log.WithFields(log.Fields{ "key": s.config.SwarmHostKey, "err": err.Error(), }).Error("get empty SwarmHost from consul") time.Sleep(s.config.SwarmRetryInterval) } else { log.WithFields(log.Fields{ "OldSwarmHost": s.host, "NewSwarmHost": swarmHost, }).Info("swarm host updated from consul") s.host = swarmHost // retry once cli, err = client.NewClient("tcp://"+s.host, s.ApiVersion, c, defaultHeaders) if err != nil { log.WithFields(log.Fields{ "err": err.Error(), }).Error("swarm reconnect error") } } } else { time.Sleep(s.config.SwarmRetryInterval) continue } } execConfig := types.ExecConfig{ Tty: true, Detach: false, AttachStdin: true, AttachStderr: true, AttachStdout: true, } //execConfig.Container = containName execConfig.Cmd = cmd creres, err := cli.ContainerExecCreate(context.Background(), containName, execConfig) if err != nil { log.WithFields(log.Fields{ "cmd": cmd, "ContainName": containName, "RetryTimes": i, "err": err.Error(), }).Error("swarm ContainerExecCreate error") time.Sleep(s.config.SwarmRetryInterval) continue } res, err := cli.ContainerExecAttach(context.Background(), creres.ID, execConfig) if err != nil { log.WithFields(log.Fields{ "cmd": cmd, "ContainName": containName, "RetryTimes": i, "err": err.Error(), }).Error("swarm ContainerExecAttach error") time.Sleep(s.config.SwarmRetryInterval) continue } return res, nil } return types.HijackedResponse{}, errors.New(fmt.Sprintf("swarm exec cmd:%+v, containName:%s, retry %d times fail\n", cmd, containName, s.config.SwarmRetryTimes)) }
// defaultTransport creates a new http.Transport with Docker's // default transport configuration. func defaultTransport(proto, addr string) *http.Transport { tr := new(http.Transport) sockets.ConfigureTransport(tr, proto, addr) return tr }
// CreateClient creates a docker client based on the specified options. func CreateClient(c ClientOpts) (client.APIClient, error) { if c.Host == "" { if os.Getenv("DOCKER_API_VERSION") == "" { os.Setenv("DOCKER_API_VERSION", DefaultAPIVersion) } client, err := client.NewEnvClient() if err != nil { return nil, err } return client, nil } apiVersion := c.APIVersion if apiVersion == "" { apiVersion = DefaultAPIVersion } if c.TLSOptions.CAFile == "" { c.TLSOptions.CAFile = filepath.Join(dockerCertPath, defaultCaFile) } if c.TLSOptions.CertFile == "" { c.TLSOptions.CertFile = filepath.Join(dockerCertPath, defaultCertFile) } if c.TLSOptions.KeyFile == "" { c.TLSOptions.KeyFile = filepath.Join(dockerCertPath, defaultKeyFile) } if c.TrustKey == "" { c.TrustKey = filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile) } if c.TLSVerify { c.TLS = true } if c.TLS { c.TLSOptions.InsecureSkipVerify = !c.TLSVerify } var httpClient *http.Client if c.TLS { config, err := tlsconfig.Client(c.TLSOptions) if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } proto, addr, _, err := client.ParseHost(c.Host) if err != nil { return nil, err } sockets.ConfigureTransport(tr, proto, addr) httpClient = &http.Client{ Transport: tr, } } customHeaders := map[string]string{} customHeaders["User-Agent"] = fmt.Sprintf("Libcompose-Client/%s (%s)", version.VERSION, runtime.GOOS) client, err := client.NewClient(c.Host, apiVersion, httpClient, customHeaders) if err != nil { return nil, err } return client, nil }