Skip to content
This repository has been archived by the owner on Apr 7, 2024. It is now read-only.

refactor!: rename DetectDefaultCredsStore to DetectDefaultNativeStore #75

Merged
merged 2 commits into from
Jun 9, 2023
Merged
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
14 changes: 7 additions & 7 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,27 +61,27 @@ type StoreOptions struct {
// plaintext in the config file when native store is not available.
AllowPlaintextPut bool

// DetectDefaultCredsStore enables detecting the platform-default
// DetectDefaultNativeStore enables detecting the platform-default native
// credentials store when the config file has no authentication information.
//
// If DetectDefaultCredsStore is set to true, the store will detect and set
// the default credentials store in the "credsStore" field of the config
// file.
// If DetectDefaultNativeStore is set to true, the store will detect and set
// the default native credentials store in the "credsStore" field of the
// config file.
// - Windows: "wincred"
// - Linux: "pass" or "secretservice"
// - macOS: "osxkeychain"
//
// References:
// - https://docs.docker.com/engine/reference/commandline/login/#credentials-store
// - https://docs.docker.com/engine/reference/commandline/cli/#docker-cli-configuration-file-configjson-properties
DetectDefaultCredsStore bool
DetectDefaultNativeStore bool
}

// NewStore returns a Store based on the given configuration file.
//
// For Get(), Put() and Delete(), the returned Store will dynamically determine
// which underlying credentials store to use for the given server address.
// The underlying credentials store is determined in the following order:
// The underlying credentials store is determined in the following order:
// 1. Native server-specific credential helper
// 2. Native credentials store
// 3. The plain-text config file itself
Expand All @@ -98,7 +98,7 @@ func NewStore(configPath string, opts StoreOptions) (*DynamicStore, error) {
config: cfg,
options: opts,
}
if opts.DetectDefaultCredsStore && !cfg.IsAuthConfigured() {
if opts.DetectDefaultNativeStore && !cfg.IsAuthConfigured() {
// no authentication configured, detect the default credentials store
ds.detectedCredsStore = getDefaultHelperSuffix()
}
Expand Down
112 changes: 99 additions & 13 deletions store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,90 @@ func Test_DynamicStore_authConfigured(t *testing.T) {
if err := ds.Put(ctx, serverAddr, cred); err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
// Put() should not set detected store back to config
if got := ds.detectedCredsStore; got != "" {
t.Errorf("ds.detectedCredsStore = %v, want empty", got)
}
if got := ds.config.CredentialsStore(); got != "" {
t.Errorf("ds.config.CredentialsStore() = %v, want empty", got)
}

// test get
got, err := ds.Get(ctx, serverAddr)
if err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
if want := cred; got != want {
t.Errorf("DynamicStore.Get() = %v, want %v", got, want)
}

// test delete
err = ds.Delete(ctx, serverAddr)
if err != nil {
t.Fatal("DynamicStore.Delete() error =", err)
}

// verify delete
got, err = ds.Get(ctx, serverAddr)
if err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
if want := auth.EmptyCredential; got != want {
t.Errorf("DynamicStore.Get() = %v, want %v", got, want)
}
}

func Test_DynamicStore_authConfigured_DetectDefaultNativeStore(t *testing.T) {
// prepare test content
tempDir := t.TempDir()
configPath := filepath.Join(tempDir, "auth_configured.json")
config := configtest.Config{
AuthConfigs: map[string]configtest.AuthConfig{
"xxx": {},
},
SomeConfigField: 123,
}
jsonStr, err := json.Marshal(config)
if err != nil {
t.Fatalf("failed to marshal config: %v", err)
}
if err := os.WriteFile(configPath, jsonStr, 0666); err != nil {
t.Fatalf("failed to write config file: %v", err)
}

opts := StoreOptions{
AllowPlaintextPut: true,
DetectDefaultNativeStore: true,
}
ds, err := NewStore(configPath, opts)
if err != nil {
t.Fatal("NewStore() error =", err)
}

// test IsAuthConfigured
authConfigured := ds.IsAuthConfigured()
if want := true; authConfigured != want {
t.Errorf("DynamicStore.IsAuthConfigured() = %v, want %v", authConfigured, want)
}

serverAddr := "test.example.com"
cred := auth.Credential{
Username: "username",
Password: "password",
}
ctx := context.Background()

// test put
if err := ds.Put(ctx, serverAddr, cred); err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
// Put() should not set detected store back to config
if got := ds.detectedCredsStore; got != "" {
t.Errorf("ds.detectedCredsStore = %v, want empty", got)
}
if got := ds.config.CredentialsStore(); got != "" {
t.Errorf("ds.config.CredentialsStore() = %v, want empty", got)
}

// test get
got, err := ds.Get(ctx, serverAddr)
Expand Down Expand Up @@ -280,16 +364,15 @@ func Test_DynamicStore_noAuthConfigured(t *testing.T) {
if _, err := ds.Get(ctx, serverAddr); err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
if got := ds.config.CredentialsStore(); got != "" {
t.Errorf("ds.config.CredentialsStore() = %v, want empty", got)
}

// test put
if err := ds.Put(ctx, serverAddr, cred); err != nil {
t.Fatal("DynamicStore.Put() error =", err)
}

// Put() should not set detected store back to config
if got := ds.detectedCredsStore; got != "" {
t.Errorf("ds.detectedCredsStore = %v, want empty", got)
}
if got := ds.config.CredentialsStore(); got != "" {
t.Errorf("ds.config.CredentialsStore() = %v, want empty", got)
}
Expand Down Expand Up @@ -319,7 +402,7 @@ func Test_DynamicStore_noAuthConfigured(t *testing.T) {
}
}

func Test_DynamicStore_noAuthConfigured_DetectDefaultStore(t *testing.T) {
func Test_DynamicStore_noAuthConfigured_DetectDefaultNativeStore(t *testing.T) {
// prepare test content
tempDir := t.TempDir()
configPath := filepath.Join(tempDir, "no_auth_configured.json")
Expand All @@ -335,8 +418,8 @@ func Test_DynamicStore_noAuthConfigured_DetectDefaultStore(t *testing.T) {
}

opts := StoreOptions{
AllowPlaintextPut: true,
DetectDefaultCredsStore: true,
AllowPlaintextPut: true,
DetectDefaultNativeStore: true,
}
ds, err := NewStore(configPath, opts)
if err != nil {
Expand All @@ -356,10 +439,15 @@ func Test_DynamicStore_noAuthConfigured_DetectDefaultStore(t *testing.T) {
}
ctx := context.Background()

// Get() should not set detected store back to config
// Get() should set detectedCredsStore only, but should not save it back to config
if _, err := ds.Get(ctx, serverAddr); err != nil {
t.Fatal("DynamicStore.Get() error =", err)
}
if defaultStore := getDefaultHelperSuffix(); defaultStore != "" {
if got := ds.detectedCredsStore; got != defaultStore {
t.Errorf("ds.detectedCredsStore = %v, want %v", got, defaultStore)
}
}
if got := ds.config.CredentialsStore(); got != "" {
t.Errorf("ds.config.CredentialsStore() = %v, want empty", got)
}
Expand All @@ -369,11 +457,9 @@ func Test_DynamicStore_noAuthConfigured_DetectDefaultStore(t *testing.T) {
t.Fatal("DynamicStore.Put() error =", err)
}

// Put() should set detected store back to config
if defaultStore := getDefaultHelperSuffix(); defaultStore != "" {
if got := ds.config.CredentialsStore(); got != defaultStore {
t.Errorf("ds.config.CredentialsStore() = %v, want %v", got, defaultStore)
}
// Put() should set the detected store back to config
if got := ds.config.CredentialsStore(); got != ds.detectedCredsStore {
t.Errorf("ds.config.CredentialsStore() = %v, want %v", got, ds.detectedCredsStore)
}

// test get
Expand Down