mirror of https://github.com/docker/cli.git
Merge pull request #1642 from tiborvass/better-dep-graph-auth-type
Remove docker api dependency from cli/config
This commit is contained in:
commit
2344627564
|
@ -62,7 +62,7 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptions, copts *containerOptions) error {
|
func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptions, copts *containerOptions) error {
|
||||||
proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), copts.env.GetAll())
|
proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(copts.env.GetAll()))
|
||||||
newEnv := []string{}
|
newEnv := []string{}
|
||||||
for k, v := range proxyConfig {
|
for k, v := range proxyConfig {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
|
|
|
@ -68,7 +68,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copts *containerOptions) error {
|
func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copts *containerOptions) error {
|
||||||
proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), copts.env.GetAll())
|
proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(copts.env.GetAll()))
|
||||||
newEnv := []string{}
|
newEnv := []string{}
|
||||||
for k, v := range proxyConfig {
|
for k, v := range proxyConfig {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
|
|
|
@ -383,7 +383,11 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
configFile := dockerCli.ConfigFile()
|
configFile := dockerCli.ConfigFile()
|
||||||
authConfigs, _ := configFile.GetAllCredentials()
|
creds, _ := configFile.GetAllCredentials()
|
||||||
|
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
||||||
|
for k, auth := range creds {
|
||||||
|
authConfigs[k] = types.AuthConfig(auth)
|
||||||
|
}
|
||||||
buildOptions := imageBuildOptions(dockerCli, options)
|
buildOptions := imageBuildOptions(dockerCli, options)
|
||||||
buildOptions.Version = types.BuilderV1
|
buildOptions.Version = types.BuilderV1
|
||||||
buildOptions.Dockerfile = relDockerfile
|
buildOptions.Dockerfile = relDockerfile
|
||||||
|
@ -619,7 +623,7 @@ func imageBuildOptions(dockerCli command.Cli, options buildOptions) types.ImageB
|
||||||
CgroupParent: options.cgroupParent,
|
CgroupParent: options.cgroupParent,
|
||||||
ShmSize: options.shmSize.Value(),
|
ShmSize: options.shmSize.Value(),
|
||||||
Ulimits: options.ulimits.GetList(),
|
Ulimits: options.ulimits.GetList(),
|
||||||
BuildArgs: configFile.ParseProxyConfig(dockerCli.Client().DaemonHost(), options.buildArgs.GetAll()),
|
BuildArgs: configFile.ParseProxyConfig(dockerCli.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(options.buildArgs.GetAll())),
|
||||||
Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()),
|
Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()),
|
||||||
CacheFrom: options.cacheFrom,
|
CacheFrom: options.cacheFrom,
|
||||||
SecurityOpt: options.securityOpt,
|
SecurityOpt: options.securityOpt,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
configtypes "github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/cli/cli/debug"
|
"github.com/docker/cli/cli/debug"
|
||||||
"github.com/docker/cli/cli/streams"
|
"github.com/docker/cli/cli/streams"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
|
@ -77,7 +78,7 @@ func ResolveAuthConfig(ctx context.Context, cli Cli, index *registrytypes.IndexI
|
||||||
}
|
}
|
||||||
|
|
||||||
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
|
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
|
||||||
return a
|
return types.AuthConfig(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
||||||
|
@ -86,16 +87,17 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
|
||||||
if !isDefaultRegistry {
|
if !isDefaultRegistry {
|
||||||
serverAddress = registry.ConvertToHostname(serverAddress)
|
serverAddress = registry.ConvertToHostname(serverAddress)
|
||||||
}
|
}
|
||||||
var authconfig types.AuthConfig
|
var authconfig configtypes.AuthConfig
|
||||||
var err error
|
var err error
|
||||||
if checkCredStore {
|
if checkCredStore {
|
||||||
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
|
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
|
||||||
} else {
|
} else {
|
||||||
authconfig = types.AuthConfig{}
|
authconfig = configtypes.AuthConfig{}
|
||||||
}
|
}
|
||||||
authconfig.ServerAddress = serverAddress
|
authconfig.ServerAddress = serverAddress
|
||||||
authconfig.IdentityToken = ""
|
authconfig.IdentityToken = ""
|
||||||
return &authconfig, err
|
res := types.AuthConfig(authconfig)
|
||||||
|
return &res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureAuth handles prompting of user's username and password if needed
|
// ConfigureAuth handles prompting of user's username and password if needed
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
|
configtypes "github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
@ -149,7 +150,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint: gocycl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := creds.Store(*authConfig); err != nil {
|
if err := creds.Store(configtypes.AuthConfig(*authConfig)); err != nil {
|
||||||
return errors.Errorf("Error saving credentials: %v", err)
|
return errors.Errorf("Error saving credentials: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
configtypes "github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
|
@ -79,21 +80,21 @@ func TestRunLogin(t *testing.T) {
|
||||||
const validPassword = "p1"
|
const validPassword = "p1"
|
||||||
const validPassword2 = "p2"
|
const validPassword2 = "p2"
|
||||||
|
|
||||||
validAuthConfig := types.AuthConfig{
|
validAuthConfig := configtypes.AuthConfig{
|
||||||
ServerAddress: storedServerAddress,
|
ServerAddress: storedServerAddress,
|
||||||
Username: validUsername,
|
Username: validUsername,
|
||||||
Password: validPassword,
|
Password: validPassword,
|
||||||
}
|
}
|
||||||
expiredAuthConfig := types.AuthConfig{
|
expiredAuthConfig := configtypes.AuthConfig{
|
||||||
ServerAddress: storedServerAddress,
|
ServerAddress: storedServerAddress,
|
||||||
Username: validUsername,
|
Username: validUsername,
|
||||||
Password: expiredPassword,
|
Password: expiredPassword,
|
||||||
}
|
}
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
inputLoginOption loginOptions
|
inputLoginOption loginOptions
|
||||||
inputStoredCred *types.AuthConfig
|
inputStoredCred *configtypes.AuthConfig
|
||||||
expectedErr string
|
expectedErr string
|
||||||
expectedSavedCred types.AuthConfig
|
expectedSavedCred configtypes.AuthConfig
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
inputLoginOption: loginOptions{
|
inputLoginOption: loginOptions{
|
||||||
|
@ -118,7 +119,7 @@ func TestRunLogin(t *testing.T) {
|
||||||
},
|
},
|
||||||
inputStoredCred: &validAuthConfig,
|
inputStoredCred: &validAuthConfig,
|
||||||
expectedErr: "",
|
expectedErr: "",
|
||||||
expectedSavedCred: types.AuthConfig{
|
expectedSavedCred: configtypes.AuthConfig{
|
||||||
ServerAddress: storedServerAddress,
|
ServerAddress: storedServerAddress,
|
||||||
Username: validUsername,
|
Username: validUsername,
|
||||||
Password: validPassword2,
|
Password: validPassword2,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
// Prevents a circular import with "github.com/docker/cli/internal/test"
|
// Prevents a circular import with "github.com/docker/cli/internal/test"
|
||||||
|
|
||||||
. "github.com/docker/cli/cli/command"
|
. "github.com/docker/cli/cli/command"
|
||||||
|
configtypes "github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/cli/cli/debug"
|
"github.com/docker/cli/cli/debug"
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -134,7 +135,7 @@ func TestGetDefaultAuthConfig(t *testing.T) {
|
||||||
errBuf := new(bytes.Buffer)
|
errBuf := new(bytes.Buffer)
|
||||||
cli.SetErr(errBuf)
|
cli.SetErr(errBuf)
|
||||||
for _, authconfig := range testAuthConfigs {
|
for _, authconfig := range testAuthConfigs {
|
||||||
cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(authconfig)
|
cli.ConfigFile().GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig))
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
serverAddress := tc.inputServerAddress
|
serverAddress := tc.inputServerAddress
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config/configfile"
|
"github.com/docker/cli/cli/config/configfile"
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/docker/pkg/homedir"
|
"github.com/docker/docker/pkg/homedir"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,8 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/cli/opts"
|
"github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -196,7 +195,7 @@ func (configFile *ConfigFile) Save() error {
|
||||||
|
|
||||||
// ParseProxyConfig computes proxy configuration by retrieving the config for the provided host and
|
// ParseProxyConfig computes proxy configuration by retrieving the config for the provided host and
|
||||||
// then checking this against any environment variables provided to the container
|
// then checking this against any environment variables provided to the container
|
||||||
func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts []string) map[string]*string {
|
func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts map[string]*string) map[string]*string {
|
||||||
var cfgKey string
|
var cfgKey string
|
||||||
|
|
||||||
if _, ok := configFile.Proxies[host]; !ok {
|
if _, ok := configFile.Proxies[host]; !ok {
|
||||||
|
@ -212,7 +211,10 @@ func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts []string) ma
|
||||||
"NO_PROXY": &config.NoProxy,
|
"NO_PROXY": &config.NoProxy,
|
||||||
"FTP_PROXY": &config.FTPProxy,
|
"FTP_PROXY": &config.FTPProxy,
|
||||||
}
|
}
|
||||||
m := opts.ConvertKVStringsToMapWithNil(runOpts)
|
m := runOpts
|
||||||
|
if m == nil {
|
||||||
|
m = make(map[string]*string)
|
||||||
|
}
|
||||||
for k := range permitted {
|
for k := range permitted {
|
||||||
if *permitted[k] == "" {
|
if *permitted[k] == "" {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package configfile
|
package configfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli/config/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
@ -41,7 +40,7 @@ func TestProxyConfig(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", []string{})
|
proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", nil)
|
||||||
expected := map[string]*string{
|
expected := map[string]*string{
|
||||||
"HTTP_PROXY": &httpProxy,
|
"HTTP_PROXY": &httpProxy,
|
||||||
"http_proxy": &httpProxy,
|
"http_proxy": &httpProxy,
|
||||||
|
@ -75,9 +74,14 @@ func TestProxyConfigOverride(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ropts := []string{
|
clone := func(s string) *string {
|
||||||
fmt.Sprintf("HTTP_PROXY=%s", overrideHTTPProxy),
|
s2 := s
|
||||||
"NO_PROXY=",
|
return &s2
|
||||||
|
}
|
||||||
|
|
||||||
|
ropts := map[string]*string{
|
||||||
|
"HTTP_PROXY": clone(overrideHTTPProxy),
|
||||||
|
"NO_PROXY": clone(overrideNoProxy),
|
||||||
}
|
}
|
||||||
proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", ropts)
|
proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", ropts)
|
||||||
expected := map[string]*string{
|
expected := map[string]*string{
|
||||||
|
@ -124,7 +128,7 @@ func TestProxyConfigPerHost(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyConfig := cfg.ParseProxyConfig("tcp://example.docker.com:2376", []string{})
|
proxyConfig := cfg.ParseProxyConfig("tcp://example.docker.com:2376", nil)
|
||||||
expected := map[string]*string{
|
expected := map[string]*string{
|
||||||
"HTTP_PROXY": &extHTTPProxy,
|
"HTTP_PROXY": &extHTTPProxy,
|
||||||
"http_proxy": &extHTTPProxy,
|
"http_proxy": &extHTTPProxy,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package credentials
|
package credentials
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli/config/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store is the interface that any credentials store must implement.
|
// Store is the interface that any credentials store must implement.
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package credentials
|
package credentials
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/api/types"
|
"strings"
|
||||||
"github.com/docker/docker/registry"
|
|
||||||
|
"github.com/docker/cli/cli/config/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type store interface {
|
type store interface {
|
||||||
|
@ -35,7 +36,7 @@ func (c *fileStore) Get(serverAddress string) (types.AuthConfig, error) {
|
||||||
// Maybe they have a legacy config file, we will iterate the keys converting
|
// Maybe they have a legacy config file, we will iterate the keys converting
|
||||||
// them to the new format and testing
|
// them to the new format and testing
|
||||||
for r, ac := range c.file.GetAuthConfigs() {
|
for r, ac := range c.file.GetAuthConfigs() {
|
||||||
if serverAddress == registry.ConvertToHostname(r) {
|
if serverAddress == ConvertToHostname(r) {
|
||||||
return ac, nil
|
return ac, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,3 +63,19 @@ func (c *fileStore) GetFilename() string {
|
||||||
func (c *fileStore) IsFileStore() bool {
|
func (c *fileStore) IsFileStore() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertToHostname converts a registry url which has http|https prepended
|
||||||
|
// to just an hostname.
|
||||||
|
// Copied from github.com/docker/docker/registry.ConvertToHostname to reduce dependencies.
|
||||||
|
func ConvertToHostname(url string) string {
|
||||||
|
stripped := url
|
||||||
|
if strings.HasPrefix(url, "http://") {
|
||||||
|
stripped = strings.TrimPrefix(url, "http://")
|
||||||
|
} else if strings.HasPrefix(url, "https://") {
|
||||||
|
stripped = strings.TrimPrefix(url, "https://")
|
||||||
|
}
|
||||||
|
|
||||||
|
nameParts := strings.SplitN(stripped, "/", 2)
|
||||||
|
|
||||||
|
return nameParts[0]
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package credentials
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli/config/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package credentials
|
package credentials
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/docker-credential-helpers/client"
|
"github.com/docker/docker-credential-helpers/client"
|
||||||
"github.com/docker/docker-credential-helpers/credentials"
|
"github.com/docker/docker-credential-helpers/credentials"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -8,9 +8,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/config/types"
|
||||||
"github.com/docker/docker-credential-helpers/client"
|
"github.com/docker/docker-credential-helpers/client"
|
||||||
"github.com/docker/docker-credential-helpers/credentials"
|
"github.com/docker/docker-credential-helpers/credentials"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
// AuthConfig contains authorization information for connecting to a Registry
|
||||||
|
type AuthConfig struct {
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Auth string `json:"auth,omitempty"`
|
||||||
|
|
||||||
|
// Email is an optional value associated with the username.
|
||||||
|
// This field is deprecated and will be removed in a later
|
||||||
|
// version of docker.
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
|
||||||
|
ServerAddress string `json:"serveraddress,omitempty"`
|
||||||
|
|
||||||
|
// IdentityToken is used to authenticate the user and get
|
||||||
|
// an access token for the registry.
|
||||||
|
IdentityToken string `json:"identitytoken,omitempty"`
|
||||||
|
|
||||||
|
// RegistryToken is a bearer token to be sent to a registry
|
||||||
|
RegistryToken string `json:"registrytoken,omitempty"`
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/cli/cli/config/credentials"
|
"github.com/docker/cli/cli/config/credentials"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/cli/cli/config/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FakeStore implements a credentials.Store that only acts as an in memory map
|
// FakeStore implements a credentials.Store that only acts as an in memory map
|
||||||
|
|
Loading…
Reference in New Issue