-
Notifications
You must be signed in to change notification settings - Fork 23
fix: avoid hard fail when no config json file is present #164
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
Open
KatIsCoding
wants to merge
6
commits into
docker:main
Choose a base branch
from
KatIsCoding:fix/avoid-hard-fail-no-config-json
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
7f96f2d
fix(config): tolerate missing config.json instead of hard-failing
KatIsCoding f981c06
fix(config): drop unused ErrConfigPathNotExists sentinel
KatIsCoding 1dc65b6
Move sentinel error to errors.go
KatIsCoding 8c25a83
fix(context): The context encoded name is pre-calculated before retur…
KatIsCoding ba5cd46
fix(config): fall back to credential helper when config is missing
KatIsCoding 72f1064
test(config,context): cover ErrConfigFileNotFound code paths
KatIsCoding File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| package config | ||
|
|
||
| import ( | ||
| "errors" | ||
| "os/exec" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| // setupConfigDirWithoutFile creates a temporary directory and sets DOCKER_CONFIG | ||
| // to point to it, but does NOT create a config.json file. This exercises the | ||
| // ErrConfigFileNotFound code path in Load/Filepath. | ||
| func setupConfigDirWithoutFile(t *testing.T) { | ||
| t.Helper() | ||
| t.Setenv(EnvOverrideDir, t.TempDir()) | ||
| } | ||
|
|
||
| func TestAuthConfigs_ConfigNotFound(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
| mockExecCommand(t) | ||
|
|
||
| authConfigs, err := AuthConfigs("some.io/repo/image:tag") | ||
| require.NoError(t, err) | ||
| require.Contains(t, authConfigs, "some.io") | ||
| require.Empty(t, authConfigs["some.io"].Username) | ||
| require.Empty(t, authConfigs["some.io"].Password) | ||
| } | ||
|
|
||
| func TestAuthConfigs_ConfigNotFound_FallsBackToCredentialHelper(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
|
|
||
| execLookPath = func(string) (string, error) { | ||
| return "", errors.New("helper unreachable") | ||
| } | ||
| t.Cleanup(func() { execLookPath = exec.LookPath }) | ||
|
|
||
| _, err := AuthConfigs("some.io/repo/image:tag") | ||
| require.Error(t, err) | ||
| require.ErrorContains(t, err, "helper unreachable") | ||
| } | ||
|
|
||
| func TestAuthConfigForHostname_ConfigNotFound(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
| mockExecCommand(t) | ||
|
|
||
| creds, err := AuthConfigForHostname("some.io") | ||
| require.NoError(t, err) | ||
| require.Empty(t, creds.Username) | ||
| require.Empty(t, creds.Password) | ||
| } | ||
|
|
||
| func TestAuthConfigForHostname_ConfigNotFound_FallsBackToCredentialHelper(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
|
|
||
| execLookPath = func(string) (string, error) { | ||
| return "", errors.New("helper unreachable") | ||
| } | ||
| t.Cleanup(func() { execLookPath = exec.LookPath }) | ||
|
|
||
| _, err := AuthConfigForHostname("some.io") | ||
| require.Error(t, err) | ||
| require.ErrorContains(t, err, "helper unreachable") | ||
| } | ||
|
|
||
| func TestLoad_ConfigNotFound_ReturnsSentinel(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
|
|
||
| _, err := Load() | ||
| require.ErrorIs(t, err, ErrConfigFileNotFound) | ||
| } | ||
|
|
||
| func TestFilepath_ConfigNotFound_ReturnsSentinel(t *testing.T) { | ||
| setupConfigDirWithoutFile(t) | ||
|
|
||
| _, err := Filepath() | ||
| require.ErrorIs(t, err, ErrConfigFileNotFound) | ||
| require.Contains(t, err.Error(), "config file does not exist") | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package config | ||
|
|
||
| import "errors" | ||
|
|
||
| // ErrConfigFileNotFound is used as a sentinel error to distinguish when a docker config file is not present, | ||
| // so that cases without a config file work, but cases with an invalid config file still fail | ||
| var ErrConfigFileNotFound = errors.New("config file not found") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| package context | ||
|
|
||
| import ( | ||
| "os" | ||
| "path/filepath" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/docker/go-sdk/config" | ||
| ) | ||
|
|
||
| // setupDockerDirWithoutConfigFile creates a ~/.docker directory in a temp home | ||
| // so that config.Dir() succeeds, but does NOT create config.json, so that | ||
| // config.Load() returns ErrConfigFileNotFound. | ||
| func setupDockerDirWithoutConfigFile(tb testing.TB) { | ||
| tb.Helper() | ||
| tmpDir := tb.TempDir() | ||
| tb.Setenv("HOME", tmpDir) | ||
| tb.Setenv("USERPROFILE", tmpDir) // Windows support | ||
| require.NoError(tb, os.MkdirAll(filepath.Join(tmpDir, ".docker"), 0o755)) | ||
| } | ||
|
|
||
| // removeConfigFile deletes the config.json from the current DOCKER_CONFIG dir. | ||
| func removeConfigFile(tb testing.TB) { | ||
| tb.Helper() | ||
| dir, err := config.Dir() | ||
| require.NoError(tb, err) | ||
| require.NoError(tb, os.Remove(filepath.Join(dir, config.FileName))) | ||
| } | ||
|
|
||
| func TestCurrent_ConfigNotFound(t *testing.T) { | ||
| setupDockerDirWithoutConfigFile(t) | ||
|
|
||
| current, err := Current() | ||
| require.NoError(t, err) | ||
| require.Equal(t, DefaultContextName, current) | ||
| } | ||
|
|
||
| func TestInspect_ConfigNotFound(t *testing.T) { | ||
| SetupTestDockerContexts(t, 1, 3) // creates config.json with currentContext=context1 | ||
| removeConfigFile(t) // simulate a fresh install without config.json | ||
|
|
||
| ctx, err := Inspect("context1") | ||
| require.NoError(t, err) | ||
| require.Equal(t, "context1", ctx.Name) | ||
| require.Equal(t, "tcp://127.0.0.1:1", ctx.Endpoints["docker"].Host) | ||
|
|
||
| require.NotEmpty(t, ctx.encodedName, "encodedName should be set even when config is missing") | ||
| require.False(t, ctx.isCurrent, "isCurrent should be false when config file is missing") | ||
| } | ||
|
|
||
| func TestStore_Inspect_ConfigNotFound(t *testing.T) { | ||
| SetupTestDockerContexts(t, 1, 3) | ||
| removeConfigFile(t) | ||
|
|
||
| metaDir, err := metaRoot() | ||
| require.NoError(t, err) | ||
| s := &store{root: metaDir} | ||
|
|
||
| ctx, err := s.inspect("context1") | ||
| require.NoError(t, err) | ||
| require.Equal(t, "context1", ctx.Name) | ||
| require.NotEmpty(t, ctx.encodedName) | ||
| require.False(t, ctx.isCurrent) | ||
| } | ||
|
|
||
| func TestNew_AsCurrent_ConfigNotFound(t *testing.T) { | ||
| setupDockerDirWithoutConfigFile(t) | ||
|
|
||
| ctx, err := New("newctx", | ||
| WithHost("tcp://127.0.0.1:9999"), | ||
| AsCurrent(), | ||
| ) | ||
| require.NoError(t, err) | ||
| defer func() { require.NoError(t, ctx.Delete()) }() | ||
|
|
||
| require.Equal(t, "newctx", ctx.Name) | ||
| require.False(t, ctx.isCurrent, "isCurrent should be false when config file is missing") | ||
|
|
||
| list, err := List() | ||
| require.NoError(t, err) | ||
| require.Contains(t, list, "newctx") | ||
|
|
||
| current, err := Current() | ||
| require.NoError(t, err) | ||
| require.NotEqual(t, "newctx", current, "current should not be the new context without a config file") | ||
| } | ||
|
|
||
| func TestDelete_CurrentContext_ConfigNotFound(t *testing.T) { | ||
| SetupTestDockerContexts(t, 1, 3) // creates config.json + contexts | ||
|
|
||
| ctx, err := New("deleteme", | ||
| WithHost("tcp://127.0.0.1:9999"), | ||
| AsCurrent(), | ||
| ) | ||
| require.NoError(t, err) | ||
| require.True(t, ctx.isCurrent, "new context should be current") | ||
|
|
||
| removeConfigFile(t) | ||
|
|
||
| require.NoError(t, ctx.Delete(), "delete should not fail when config file is missing") | ||
|
|
||
| _, err = Inspect("deleteme") | ||
| require.ErrorIs(t, err, ErrDockerContextNotFound) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.