mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
feat: support tls with context config
This commit is contained in:
parent
577797d9ed
commit
bcd2807aa7
2 changed files with 99 additions and 8 deletions
|
|
@ -78,11 +78,75 @@ func (c *DockerCommand) NewCommandObject(obj CommandObject) CommandObject {
|
||||||
// API version negotiation to support older Docker daemons.
|
// API version negotiation to support older Docker daemons.
|
||||||
// See https://github.com/jesseduffield/lazydocker/issues/715
|
// See https://github.com/jesseduffield/lazydocker/issues/715
|
||||||
func newDockerClient(dockerHost string) (*client.Client, error) {
|
func newDockerClient(dockerHost string) (*client.Client, error) {
|
||||||
return client.NewClientWithOpts(
|
opts := []client.Opt{
|
||||||
client.WithTLSClientConfigFromEnv(),
|
|
||||||
client.WithAPIVersionNegotiation(),
|
client.WithAPIVersionNegotiation(),
|
||||||
client.WithHost(dockerHost),
|
client.WithHost(dockerHost),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load TLS config from environment variables (for backward compatibility)
|
||||||
|
tlsOpts := []client.Opt{client.WithTLSClientConfigFromEnv()}
|
||||||
|
|
||||||
|
// Also try to load TLS config from the current Docker context
|
||||||
|
contextTLSOpts, err := getContextTLSOptions()
|
||||||
|
if err == nil && contextTLSOpts != nil {
|
||||||
|
// If we have context TLS config, use it instead of env config
|
||||||
|
tlsOpts = contextTLSOpts
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = append(opts, tlsOpts...)
|
||||||
|
|
||||||
|
return client.NewClientWithOpts(opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// getContextTLSOptions loads TLS configuration from the current Docker context
|
||||||
|
func getContextTLSOptions() ([]client.Opt, error) {
|
||||||
|
currentContext := os.Getenv("DOCKER_CONTEXT")
|
||||||
|
if currentContext == "" {
|
||||||
|
cf, err := cliconfig.Load(cliconfig.Dir())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
currentContext = cf.CurrentContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if no context or using default context
|
||||||
|
if currentContext == "" || currentContext == "default" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
storeConfig := ctxstore.NewConfig(
|
||||||
|
func() interface{} { return &ddocker.EndpointMeta{} },
|
||||||
|
ctxstore.EndpointTypeGetter(ddocker.DockerEndpoint, func() interface{} { return &ddocker.EndpointMeta{} }),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
st := ctxstore.New(cliconfig.ContextStoreDir(), storeConfig)
|
||||||
|
|
||||||
|
// First load the endpoint metadata
|
||||||
|
md, err := st.GetMetadata(currentContext)
|
||||||
|
if err != nil {
|
||||||
|
// Context doesn't exist or can't be read - not an error for our use case
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerEP, ok := md.Endpoints[ddocker.DockerEndpoint]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil // No docker endpoint in this context
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerEPMeta, ok := dockerEP.(ddocker.EndpointMeta)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("expected docker.EndpointMeta, got %T", dockerEP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now load the endpoint with TLS data
|
||||||
|
endpoint, err := ddocker.WithTLSData(st, currentContext, dockerEPMeta)
|
||||||
|
if err != nil {
|
||||||
|
// If we can't load TLS data, that's okay - just return nil
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get client options from the endpoint (includes TLS config)
|
||||||
|
return endpoint.ClientOpts()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDockerCommand it runs docker commands
|
// NewDockerCommand it runs docker commands
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,38 @@ func TestNewDockerClientVersionNegotiation(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
|
|
||||||
// Version is NOT locked to the env var value (1.25).
|
// Version should still be negotiable (not locked to env var)
|
||||||
// Instead, it uses the library's default version and will negotiate
|
assert.NotEqual(t, "1.25", cli.ClientVersion())
|
||||||
// with the server on first request. This is the key difference that
|
|
||||||
// fixes the "version too old" error.
|
|
||||||
assert.NotEqual(t, "1.25", cli.ClientVersion(),
|
|
||||||
"client version should not be locked to DOCKER_API_VERSION env var")
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGetContextTLSOptions tests that TLS options can be loaded from Docker contexts
|
||||||
|
func TestGetContextTLSOptions(t *testing.T) {
|
||||||
|
// Save original env vars and restore after test
|
||||||
|
originalContext := os.Getenv("DOCKER_CONTEXT")
|
||||||
|
defer func() {
|
||||||
|
if originalContext == "" {
|
||||||
|
os.Unsetenv("DOCKER_CONTEXT")
|
||||||
|
} else {
|
||||||
|
os.Setenv("DOCKER_CONTEXT", originalContext)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Test with no context set (should return nil)
|
||||||
|
os.Unsetenv("DOCKER_CONTEXT")
|
||||||
|
opts, err := getContextTLSOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, opts)
|
||||||
|
|
||||||
|
// Test with default context (should return nil)
|
||||||
|
os.Setenv("DOCKER_CONTEXT", "default")
|
||||||
|
opts, err = getContextTLSOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, opts)
|
||||||
|
|
||||||
|
// Test with non-existent context (should return nil, not error)
|
||||||
|
os.Setenv("DOCKER_CONTEXT", "nonexistent-context")
|
||||||
|
opts, err = getContextTLSOptions()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, opts)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue