Skip to content

Commit e7c6f4d

Browse files
committed
Create in-memory store
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
1 parent eb43744 commit e7c6f4d

4 files changed

Lines changed: 112 additions & 110 deletions

File tree

cli/config/configfile/file.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010

1111
"github.com/docker/cli/cli/config/credentials"
12+
"github.com/docker/cli/cli/config/memory"
1213
"github.com/docker/cli/cli/config/types"
1314
"github.com/pkg/errors"
1415
"github.com/sirupsen/logrus"
@@ -265,8 +266,16 @@ func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) crede
265266
// if DOCKER_AUTH_CONFIG is set, we need to use the env store instead
266267
// it falls back to native or file store if a value is not found
267268
// in the environment
268-
if os.Getenv("DOCKER_AUTH_CONFIG") != "" {
269-
return credentials.NewEnvStore(store)
269+
if v, ok := os.LookupEnv("DOCKER_AUTH_CONFIG"); ok {
270+
var credentials map[string]map[string]types.AuthConfig
271+
if err := json.Unmarshal([]byte(v), &credentials); err != nil {
272+
return store
273+
}
274+
auth, ok := credentials["auth"]
275+
if !ok {
276+
return store
277+
}
278+
return memory.NewInMemoryStore(auth, memory.WithFallbackStore(store))
270279
}
271280

272281
return store

cli/config/credentials/env_store.go

Lines changed: 0 additions & 79 deletions
This file was deleted.

cli/config/memory/env_store.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package memory
2+
3+
import (
4+
"errors"
5+
"maps"
6+
7+
"github.com/docker/cli/cli/config/credentials"
8+
"github.com/docker/cli/cli/config/types"
9+
)
10+
11+
var errValueNotFound = errors.New("value not found")
12+
13+
func IsErrValueNotFound(err error) bool {
14+
return errors.Is(err, errValueNotFound)
15+
}
16+
17+
type memoryStore struct {
18+
memoryCredentials map[string]types.AuthConfig
19+
fallbackStore credentials.Store
20+
}
21+
22+
func (e *memoryStore) Erase(serverAddress string) error {
23+
delete(e.memoryCredentials, serverAddress)
24+
25+
if e.fallbackStore != nil {
26+
if err := e.fallbackStore.Erase(serverAddress); err != nil {
27+
return err
28+
}
29+
}
30+
31+
return nil
32+
}
33+
34+
func (e *memoryStore) Get(serverAddress string) (types.AuthConfig, error) {
35+
authConfig, ok := e.memoryCredentials[serverAddress]
36+
if !ok {
37+
if e.fallbackStore != nil {
38+
return e.fallbackStore.Get(serverAddress)
39+
}
40+
return types.AuthConfig{}, errValueNotFound
41+
}
42+
return authConfig, nil
43+
}
44+
45+
func (e *memoryStore) GetAll() (map[string]types.AuthConfig, error) {
46+
credentials := make(map[string]types.AuthConfig)
47+
48+
if e.fallbackStore != nil {
49+
fileCredentials, err := e.fallbackStore.GetAll()
50+
if err == nil {
51+
credentials = fileCredentials
52+
}
53+
}
54+
55+
// override the file credentials with the env credentials
56+
maps.Copy(credentials, e.memoryCredentials)
57+
return credentials, nil
58+
}
59+
60+
func (e *memoryStore) Store(authConfig types.AuthConfig) error {
61+
e.memoryCredentials[authConfig.ServerAddress] = authConfig
62+
63+
if e.fallbackStore != nil {
64+
return e.fallbackStore.Store(authConfig)
65+
}
66+
return nil
67+
}
68+
69+
func WithFallbackStore(store credentials.Store) func(*memoryStore) {
70+
return func(s *memoryStore) {
71+
s.fallbackStore = store
72+
}
73+
}
74+
75+
// NewInMemoryStore creates a new credentials store
76+
// from config.
77+
//
78+
// Using the `WithFallbackStore` option, it can be configured to
79+
// use a fallback store to retrieve credentials.
80+
func NewInMemoryStore(config map[string]types.AuthConfig, opts ...func(*memoryStore)) credentials.Store {
81+
m := &memoryStore{
82+
memoryCredentials: config,
83+
}
84+
for _, opt := range opts {
85+
opt(m)
86+
}
87+
return m
88+
}
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,58 @@
1-
package credentials
1+
package memory
22

33
import (
4-
"encoding/json"
54
"testing"
65

76
"github.com/docker/cli/cli/config/types"
87
"gotest.tools/v3/assert"
98
)
109

1110
func TestEnvStore(t *testing.T) {
12-
envConfig := map[string]types.AuthConfig{
11+
config := map[string]types.AuthConfig{
1312
"https://example.com": {
1413
Email: "something-something",
1514
ServerAddress: "https://example.com",
1615
Auth: "super_secret_token",
1716
},
1817
}
19-
d, err := json.Marshal(map[string]map[string]types.AuthConfig{
20-
"auth": envConfig,
21-
})
22-
assert.NilError(t, err)
23-
24-
t.Setenv("DOCKER_AUTH_CONFIG", string(d))
2518

26-
fileConfig := map[string]types.AuthConfig{
19+
fallbackConfig := map[string]types.AuthConfig{
2720
"https://only-in-file.com": {
2821
Email: "something-something",
2922
ServerAddress: "https://only-in-file.com",
3023
Auth: "super_secret_token",
3124
},
3225
}
3326

34-
var saveCount int
35-
fileStore := NewFileStore(&fakeStore{
36-
configs: fileConfig,
37-
saveFn: func(*fakeStore) error {
38-
saveCount++
39-
return nil
40-
},
41-
})
27+
fallbackStore := NewInMemoryStore(fallbackConfig)
4228

43-
envStore := NewEnvStore(fileStore)
29+
memoryStore := NewInMemoryStore(config, WithFallbackStore(fallbackStore))
4430

4531
t.Run("case=get credentials from env", func(t *testing.T) {
46-
c, err := envStore.Get("https://example.com")
32+
c, err := memoryStore.Get("https://example.com")
4733
assert.NilError(t, err)
48-
assert.Equal(t, c, envConfig["https://example.com"])
34+
assert.Equal(t, c, config["https://example.com"])
4935
})
5036

5137
t.Run("case=get credentials from file", func(t *testing.T) {
52-
c, err := envStore.Get("https://only-in-file.com")
38+
c, err := memoryStore.Get("https://only-in-file.com")
5339
assert.NilError(t, err)
54-
assert.Equal(t, c, fileConfig["https://only-in-file.com"])
40+
assert.Equal(t, c, fallbackConfig["https://only-in-file.com"])
5541
})
5642

5743
t.Run("case=storing credentials should not update env", func(t *testing.T) {
58-
err := envStore.Store(types.AuthConfig{
44+
err := memoryStore.Store(types.AuthConfig{
5945
Email: "not-in-env",
6046
ServerAddress: "https://not-in-env",
6147
Auth: "not-in-env",
6248
})
6349
assert.NilError(t, err)
64-
assert.Equal(t, saveCount, 1)
6550
})
6651

6752
t.Run("case=delete credentials should not update env", func(t *testing.T) {
68-
err := envStore.Erase("https://example.com")
69-
assert.NilError(t, err)
70-
c, err := envStore.Get("https://example.com")
53+
err := memoryStore.Erase("https://example.com")
7154
assert.NilError(t, err)
72-
assert.Equal(t, c, envConfig["https://example.com"])
55+
_, err = memoryStore.Get("https://example.com")
56+
assert.Equal(t, IsErrValueNotFound(err), true)
7357
})
7458
}

0 commit comments

Comments
 (0)