Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for unix sockets on api client #17949

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 42 additions & 7 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ type Config struct {
// Address is the address of the Nomad agent
Address string

// Scheme is the URI scheme for the Nomad agent
Scheme string

// Region to use. If not provided, the default agent region is used.
Region string

Expand Down Expand Up @@ -210,7 +213,8 @@ func (c *Config) ClientConfig(region, address string, tlsEnabled bool) *Config {
scheme = "https"
}
config := &Config{
Address: fmt.Sprintf("%s://%s", scheme, address),
Address: address,
Scheme: scheme,
Region: region,
Namespace: c.Namespace,
HttpClient: c.HttpClient,
Expand Down Expand Up @@ -273,13 +277,18 @@ func (t *TLSConfig) Copy() *TLSConfig {
return nt
}

func defaultHttpClient() *http.Client {
func defaultHttpClient(unixAddr string) *http.Client {
httpClient := cleanhttp.DefaultPooledClient()
transport := httpClient.Transport.(*http.Transport)
transport.TLSHandshakeTimeout = 10 * time.Second
transport.TLSClientConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
}
if unixAddr != "" {
transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", unixAddr)
}
}

// Default to http/1: alloc exec/websocket aren't supported in http/2
// well yet: https://github.com/gorilla/websocket/issues/417
Expand All @@ -291,7 +300,8 @@ func defaultHttpClient() *http.Client {
// DefaultConfig returns a default configuration for the client
func DefaultConfig() *Config {
config := &Config{
Address: "http://127.0.0.1:4646",
Address: "127.0.0.1:4646",
Scheme: "http",
TLSConfig: &TLSConfig{},
}
if addr := os.Getenv("NOMAD_ADDR"); addr != "" {
Expand All @@ -318,6 +328,9 @@ func DefaultConfig() *Config {
Password: password,
}
}
if v := os.Getenv("NOMAD_HTTP_SSL"); v != "" {
config.Scheme = "https"
}

// Read TLS specific env vars
if v := os.Getenv("NOMAD_CACERT"); v != "" {
Expand Down Expand Up @@ -467,13 +480,35 @@ func NewClient(config *Config) (*Client, error) {

if config.Address == "" {
config.Address = defConfig.Address
} else if _, err := url.Parse(config.Address); err != nil {
}

if config.Scheme == "" {
config.Scheme = defConfig.Scheme
}

if _, err := url.Parse(config.Address); err != nil {
return nil, fmt.Errorf("invalid address '%s': %v", config.Address, err)
}

var unixAddr string
parts := strings.SplitN(config.Address, "://", 2)
if len(parts) == 2 {
switch parts[0] {
case "http":
// Never revert to http if TLS was explicitly requested.
case "https":
config.Scheme = "https"
case "unix":
unixAddr = parts[1]
default:
return nil, fmt.Errorf("unknown protocol scheme: %s", parts[0])
}
config.Address = parts[1]
}

httpClient := config.HttpClient
if httpClient == nil {
httpClient = defaultHttpClient()
httpClient = defaultHttpClient(unixAddr)
if err := ConfigureTLS(httpClient, config.TLSConfig); err != nil {
return nil, err
}
Expand Down Expand Up @@ -730,9 +765,9 @@ func (c *Client) newRequest(method, path string) (*request, error) {
config: &c.config,
method: method,
url: &url.URL{
Scheme: base.Scheme,
Scheme: c.config.Scheme,
User: base.User,
Host: base.Host,
Host: c.config.Address,
Path: u.Path,
RawPath: u.RawPath,
},
Expand Down
2 changes: 1 addition & 1 deletion api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func TestClient_NodeClient(t *testing.T) {
}

func TestCloneHttpClient(t *testing.T) {
client := defaultHttpClient()
client := defaultHttpClient("")
originalTransport := client.Transport.(*http.Transport)
originalTransport.Proxy = func(*http.Request) (*url.URL, error) {
return nil, errors.New("stub function")
Expand Down