diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 8a1927a39ca..d54a1b73646 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,5 +1,9 @@ ### SDK Features ### SDK Enhancements +* `aws/defaults`: Exports shared credentials and config default filenames used by the SDK. [#1308](https://github.com/aws/aws-sdk-go/pull/1308) + * Adds SharedCredentialsFilename and SharedConfigFilename functions to defaults package. ### SDK Bugs +* `aws/credentials`: Fixes shared credential provider's default filename on Windows. [#1308](https://github.com/aws/aws-sdk-go/pull/1308) + * The shared credentials provider would attempt to use the wrong filename on Windows if the `HOME` environment variable was defined. diff --git a/aws/credentials/shared_credentials_provider.go b/aws/credentials/shared_credentials_provider.go index 7fb7cbf0db0..cabecc1f913 100644 --- a/aws/credentials/shared_credentials_provider.go +++ b/aws/credentials/shared_credentials_provider.go @@ -3,11 +3,11 @@ package credentials import ( "fmt" "os" - "path/filepath" "github.com/go-ini/ini" "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/internal/shareddefaults" ) // SharedCredsProviderName provides a name of SharedCreds provider @@ -15,8 +15,6 @@ const SharedCredsProviderName = "SharedCredentialsProvider" var ( // ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found. - // - // @readonly ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil) ) @@ -117,22 +115,23 @@ func loadProfile(filename, profile string) (Value, error) { // // Will return an error if the user's home directory path cannot be found. func (p *SharedCredentialsProvider) filename() (string, error) { - if p.Filename == "" { - if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" { - return p.Filename, nil - } - - homeDir := os.Getenv("HOME") // *nix - if homeDir == "" { // Windows - homeDir = os.Getenv("USERPROFILE") - } - if homeDir == "" { - return "", ErrSharedCredentialsHomeNotFound - } - - p.Filename = filepath.Join(homeDir, ".aws", "credentials") + if len(p.Filename) != 0 { + return p.Filename, nil + } + + if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(p.Filename) != 0 { + return p.Filename, nil } + if home := shareddefaults.UserHomeDir(); len(home) == 0 { + // Backwards compatibility of home directly not found error being returned. + // This error is too verbose, failure when opening the file would of been + // a better error to return. + return "", ErrSharedCredentialsHomeNotFound + } + + p.Filename = shareddefaults.SharedConfigFilename() + return p.Filename, nil } diff --git a/aws/defaults/shared_config.go b/aws/defaults/shared_config.go new file mode 100644 index 00000000000..ca0ee1dcc78 --- /dev/null +++ b/aws/defaults/shared_config.go @@ -0,0 +1,27 @@ +package defaults + +import ( + "github.com/aws/aws-sdk-go/internal/shareddefaults" +) + +// SharedCredentialsFilename returns the SDK's default file path +// for the shared credentials file. +// +// Builds the shared config file path based on the OS's platform. +// +// - Linux/Unix: $HOME/.aws/credentials +// - Windows: %USERPROFILE%\.aws\credentials +func SharedCredentialsFilename() string { + return shareddefaults.SharedCredentialsFilename() +} + +// SharedConfigFilename returns the SDK's default file path for +// the shared config file. +// +// Builds the shared config file path based on the OS's platform. +// +// - Linux/Unix: $HOME/.aws/config +// - Windows: %USERPROFILE%\.aws\config +func SharedConfigFilename() string { + return shareddefaults.SharedConfigFilename() +} diff --git a/aws/session/custom_ca_bundle_test.go b/aws/session/custom_ca_bundle_test.go index 52e59d99c51..a89c0af5982 100644 --- a/aws/session/custom_ca_bundle_test.go +++ b/aws/session/custom_ca_bundle_test.go @@ -42,7 +42,7 @@ func TestMain(m *testing.M) { func TestNewSession_WithCustomCABundle_Env(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) if err != nil { @@ -76,7 +76,7 @@ func TestNewSession_WithCustomCABundle_Env(t *testing.T) { func TestNewSession_WithCustomCABundle_EnvNotExists(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_CA_BUNDLE", "file-not-exists") @@ -94,7 +94,7 @@ func TestNewSession_WithCustomCABundle_EnvNotExists(t *testing.T) { func TestNewSession_WithCustomCABundle_Option(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) if err != nil { @@ -129,7 +129,7 @@ func TestNewSession_WithCustomCABundle_Option(t *testing.T) { func TestNewSession_WithCustomCABundle_OptionPriority(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) if err != nil { @@ -172,7 +172,7 @@ func (m *mockRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { func TestNewSession_WithCustomCABundle_UnsupportedTransport(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) s, err := NewSessionWithOptions(Options{ Config: aws.Config{ @@ -199,7 +199,7 @@ func TestNewSession_WithCustomCABundle_UnsupportedTransport(t *testing.T) { func TestNewSession_WithCustomCABundle_TransportSet(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) endpoint, err := awstesting.CreateTLSServer(TLSBundleCertFile, TLSBundleKeyFile, nil) if err != nil { diff --git a/aws/session/env_config.go b/aws/session/env_config.go index e6278a782c7..7357e545acd 100644 --- a/aws/session/env_config.go +++ b/aws/session/env_config.go @@ -2,7 +2,6 @@ package session import ( "os" - "path/filepath" "strconv" "github.com/aws/aws-sdk-go/aws/credentials" @@ -116,6 +115,12 @@ var ( "AWS_PROFILE", "AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set } + sharedCredsFileEnvKey = []string{ + "AWS_SHARED_CREDENTIALS_FILE", + } + sharedConfigFileEnvKey = []string{ + "AWS_CONFIG_FILE", + } ) // loadEnvConfig retrieves the SDK's environment configuration. @@ -165,8 +170,8 @@ func envConfigLoad(enableSharedConfig bool) envConfig { setFromEnvVal(&cfg.Region, regionKeys) setFromEnvVal(&cfg.Profile, profileKeys) - cfg.SharedCredentialsFile = sharedCredentialsFilename() - cfg.SharedConfigFile = sharedConfigFilename() + setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey) + setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey) cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE") @@ -181,28 +186,3 @@ func setFromEnvVal(dst *string, keys []string) { } } } - -func sharedCredentialsFilename() string { - if name := os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(name) > 0 { - return name - } - - return filepath.Join(userHomeDir(), ".aws", "credentials") -} - -func sharedConfigFilename() string { - if name := os.Getenv("AWS_CONFIG_FILE"); len(name) > 0 { - return name - } - - return filepath.Join(userHomeDir(), ".aws", "config") -} - -func userHomeDir() string { - homeDir := os.Getenv("HOME") // *nix - if len(homeDir) == 0 { // windows - homeDir = os.Getenv("USERPROFILE") - } - - return homeDir -} diff --git a/aws/session/env_config_test.go b/aws/session/env_config_test.go index 162a710546f..10e3662a282 100644 --- a/aws/session/env_config_test.go +++ b/aws/session/env_config_test.go @@ -2,17 +2,16 @@ package session import ( "os" - "path/filepath" - "strings" + "reflect" "testing" "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/stretchr/testify/assert" + "github.com/aws/aws-sdk-go/awstesting" ) func TestLoadEnvConfig_Creds(t *testing.T) { - env := stashEnv() - defer popEnv(env) + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) cases := []struct { Env map[string]string @@ -83,26 +82,30 @@ func TestLoadEnvConfig_Creds(t *testing.T) { } cfg := loadEnvConfig() - assert.Equal(t, c.Val, cfg.Creds) + if !reflect.DeepEqual(c.Val, cfg.Creds) { + t.Errorf("expect credentials to match.\n%s", + awstesting.SprintExpectActual(c.Val, cfg.Creds)) + } } } func TestLoadEnvConfig(t *testing.T) { - env := stashEnv() - defer popEnv(env) + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) cases := []struct { Env map[string]string - Region, Profile string - CustomCABundle string UseSharedConfigCall bool + Config envConfig }{ { Env: map[string]string{ "AWS_REGION": "region", "AWS_PROFILE": "profile", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + }, }, { Env: map[string]string{ @@ -111,7 +114,9 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_PROFILE": "profile", "AWS_DEFAULT_PROFILE": "default_profile", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + }, }, { Env: map[string]string{ @@ -121,7 +126,10 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_DEFAULT_PROFILE": "default_profile", "AWS_SDK_LOAD_CONFIG": "1", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, }, { Env: map[string]string{ @@ -135,14 +143,20 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_DEFAULT_PROFILE": "default_profile", "AWS_SDK_LOAD_CONFIG": "1", }, - Region: "default_region", Profile: "default_profile", + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, }, { Env: map[string]string{ "AWS_REGION": "region", "AWS_PROFILE": "profile", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, { @@ -152,7 +166,10 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_PROFILE": "profile", "AWS_DEFAULT_PROFILE": "default_profile", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, { @@ -163,7 +180,10 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_DEFAULT_PROFILE": "default_profile", "AWS_SDK_LOAD_CONFIG": "1", }, - Region: "region", Profile: "profile", + Config: envConfig{ + Region: "region", Profile: "profile", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, { @@ -171,7 +191,10 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_DEFAULT_REGION": "default_region", "AWS_DEFAULT_PROFILE": "default_profile", }, - Region: "default_region", Profile: "default_profile", + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, { @@ -180,22 +203,40 @@ func TestLoadEnvConfig(t *testing.T) { "AWS_DEFAULT_PROFILE": "default_profile", "AWS_SDK_LOAD_CONFIG": "1", }, - Region: "default_region", Profile: "default_profile", + Config: envConfig{ + Region: "default_region", Profile: "default_profile", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, { Env: map[string]string{ "AWS_CA_BUNDLE": "custom_ca_bundle", }, - CustomCABundle: "custom_ca_bundle", + Config: envConfig{ + CustomCABundle: "custom_ca_bundle", + }, }, { Env: map[string]string{ "AWS_CA_BUNDLE": "custom_ca_bundle", }, - CustomCABundle: "custom_ca_bundle", + Config: envConfig{ + CustomCABundle: "custom_ca_bundle", + EnableSharedConfig: true, + }, UseSharedConfigCall: true, }, + { + Env: map[string]string{ + "AWS_SHARED_CREDENTIALS_FILE": "/path/to/credentials/file", + "AWS_CONFIG_FILE": "/path/to/config/file", + }, + Config: envConfig{ + SharedCredentialsFile: "/path/to/credentials/file", + SharedConfigFile: "/path/to/config/file", + }, + }, } for _, c := range cases { @@ -212,55 +253,16 @@ func TestLoadEnvConfig(t *testing.T) { cfg = loadEnvConfig() } - assert.Equal(t, c.Region, cfg.Region) - assert.Equal(t, c.Profile, cfg.Profile) - assert.Equal(t, c.CustomCABundle, cfg.CustomCABundle) + if !reflect.DeepEqual(c.Config, cfg) { + t.Errorf("expect config to match.\n%s", + awstesting.SprintExpectActual(c.Config, cfg)) + } } } -func TestSharedCredsFilename(t *testing.T) { - env := stashEnv() - defer popEnv(env) - - os.Setenv("USERPROFILE", "profile_dir") - expect := filepath.Join("profile_dir", ".aws", "credentials") - name := sharedCredentialsFilename() - assert.Equal(t, expect, name) - - os.Setenv("HOME", "home_dir") - expect = filepath.Join("home_dir", ".aws", "credentials") - name = sharedCredentialsFilename() - assert.Equal(t, expect, name) - - expect = filepath.Join("path/to/credentials/file") - os.Setenv("AWS_SHARED_CREDENTIALS_FILE", expect) - name = sharedCredentialsFilename() - assert.Equal(t, expect, name) -} - -func TestSharedConfigFilename(t *testing.T) { - env := stashEnv() - defer popEnv(env) - - os.Setenv("USERPROFILE", "profile_dir") - expect := filepath.Join("profile_dir", ".aws", "config") - name := sharedConfigFilename() - assert.Equal(t, expect, name) - - os.Setenv("HOME", "home_dir") - expect = filepath.Join("home_dir", ".aws", "config") - name = sharedConfigFilename() - assert.Equal(t, expect, name) - - expect = filepath.Join("path/to/config/file") - os.Setenv("AWS_CONFIG_FILE", expect) - name = sharedConfigFilename() - assert.Equal(t, expect, name) -} - func TestSetEnvValue(t *testing.T) { - env := stashEnv() - defer popEnv(env) + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) os.Setenv("empty_key", "") os.Setenv("second_key", "2") @@ -271,21 +273,7 @@ func TestSetEnvValue(t *testing.T) { "empty_key", "first_key", "second_key", "third_key", }) - assert.Equal(t, "2", dst) -} - -func stashEnv() []string { - env := os.Environ() - os.Clearenv() - - return env -} - -func popEnv(env []string) { - os.Clearenv() - - for _, e := range env { - p := strings.SplitN(e, "=", 2) - os.Setenv(p[0], p[1]) + if e, a := "2", dst; e != a { + t.Errorf("expect %s value from environment, got %s", e, a) } } diff --git a/aws/session/session.go b/aws/session/session.go index 34a292085c0..9f75d5ac588 100644 --- a/aws/session/session.go +++ b/aws/session/session.go @@ -243,6 +243,13 @@ func NewSessionWithOptions(opts Options) (*Session, error) { envCfg.EnableSharedConfig = true } + if len(envCfg.SharedCredentialsFile) == 0 { + envCfg.SharedCredentialsFile = defaults.SharedCredentialsFilename() + } + if len(envCfg.SharedConfigFile) == 0 { + envCfg.SharedConfigFile = defaults.SharedConfigFilename() + } + // Only use AWS_CA_BUNDLE if session option is not provided. if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil { f, err := os.Open(envCfg.CustomCABundle) diff --git a/aws/session/session_test.go b/aws/session/session_test.go index 25aed6892a8..d0ab360e265 100644 --- a/aws/session/session_test.go +++ b/aws/session/session_test.go @@ -14,12 +14,13 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/defaults" + "github.com/aws/aws-sdk-go/awstesting" "github.com/aws/aws-sdk-go/service/s3" ) func TestNewDefaultSession(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) s := New(&aws.Config{Region: aws.String("region")}) @@ -31,7 +32,7 @@ func TestNewDefaultSession(t *testing.T) { func TestNew_WithCustomCreds(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) customCreds := credentials.NewStaticCredentials("AKID", "SECRET", "TOKEN") s := New(&aws.Config{Credentials: customCreds}) @@ -49,7 +50,7 @@ func (w mockLogger) Log(args ...interface{}) { func TestNew_WithSessionLoadError(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "1") os.Setenv("AWS_CONFIG_FILE", testConfigFilename) @@ -72,7 +73,7 @@ func TestNew_WithSessionLoadError(t *testing.T) { func TestSessionCopy(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_REGION", "orig_region") @@ -100,7 +101,7 @@ func TestSessionClientConfig(t *testing.T) { func TestNewSession_NoCredentials(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) s, err := NewSession() assert.NoError(t, err) @@ -111,7 +112,7 @@ func TestNewSession_NoCredentials(t *testing.T) { func TestNewSessionWithOptions_OverrideProfile(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "1") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -134,7 +135,7 @@ func TestNewSessionWithOptions_OverrideProfile(t *testing.T) { func TestNewSessionWithOptions_OverrideSharedConfigEnable(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "0") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -157,7 +158,7 @@ func TestNewSessionWithOptions_OverrideSharedConfigEnable(t *testing.T) { func TestNewSessionWithOptions_OverrideSharedConfigDisable(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "1") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -180,7 +181,7 @@ func TestNewSessionWithOptions_OverrideSharedConfigDisable(t *testing.T) { func TestNewSessionWithOptions_OverrideSharedConfigFiles(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "1") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -258,7 +259,7 @@ func TestNewSessionWithOptions_Overrides(t *testing.T) { for _, c := range cases { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) for k, v := range c.InEnvs { os.Setenv(k, v) @@ -302,7 +303,7 @@ const assumeRoleRespMsg = ` func TestSesisonAssumeRole(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_REGION", "us-east-1") os.Setenv("AWS_SDK_LOAD_CONFIG", "1") @@ -325,7 +326,7 @@ func TestSesisonAssumeRole(t *testing.T) { func TestSessionAssumeRole_WithMFA(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_REGION", "us-east-1") os.Setenv("AWS_SDK_LOAD_CONFIG", "1") @@ -368,7 +369,7 @@ func TestSessionAssumeRole_WithMFA(t *testing.T) { func TestSessionAssumeRole_WithMFA_NoTokenProvider(t *testing.T) { oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_REGION", "us-east-1") os.Setenv("AWS_SDK_LOAD_CONFIG", "1") @@ -386,7 +387,7 @@ func TestSessionAssumeRole_DisableSharedConfig(t *testing.T) { // Backwards compatibility with Shared config disabled // assume role should not be built into the config. oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "0") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -406,7 +407,7 @@ func TestSessionAssumeRole_InvalidSourceProfile(t *testing.T) { // Backwards compatibility with Shared config disabled // assume role should not be built into the config. oldEnv := initSessionTestEnv() - defer popEnv(oldEnv) + defer awstesting.PopEnv(oldEnv) os.Setenv("AWS_SDK_LOAD_CONFIG", "1") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", testConfigFilename) @@ -419,7 +420,7 @@ func TestSessionAssumeRole_InvalidSourceProfile(t *testing.T) { } func initSessionTestEnv() (oldEnv []string) { - oldEnv = stashEnv() + oldEnv = awstesting.StashEnv() os.Setenv("AWS_CONFIG_FILE", "file_not_exists") os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "file_not_exists") diff --git a/awstesting/assert.go b/awstesting/assert.go index 5494dc7116a..5d095d202f5 100644 --- a/awstesting/assert.go +++ b/awstesting/assert.go @@ -149,8 +149,8 @@ func objectsAreEqual(expected, actual interface{}) bool { // Copied locally to prevent non-test build dependencies on testify func equal(t *testing.T, expected, actual interface{}, msgAndArgs ...interface{}) bool { if !objectsAreEqual(expected, actual) { - t.Errorf("Not Equal:\n\t%#v (expected)\n\t%#v (actual), %s", - expected, actual, messageFromMsgAndArgs(msgAndArgs)) + t.Errorf("%s\n%s", messageFromMsgAndArgs(msgAndArgs), + SprintExpectActual(expected, actual)) return false } @@ -188,3 +188,9 @@ func queryValueKeys(v url.Values) []string { sort.Strings(keys) return keys } + +// SprintExpectActual returns a string for test failure cases when the actual +// value is not the same as the expected. +func SprintExpectActual(expect, actual interface{}) string { + return fmt.Sprintf("expect: %+v\nactual: %+v\n", expect, actual) +} diff --git a/awstesting/util.go b/awstesting/util.go index fde4dcc4a87..3c146a23d09 100644 --- a/awstesting/util.go +++ b/awstesting/util.go @@ -2,6 +2,8 @@ package awstesting import ( "io" + "os" + "strings" "time" "github.com/aws/aws-sdk-go/private/util" @@ -92,3 +94,28 @@ func (c *FakeContext) Err() error { func (c *FakeContext) Value(key interface{}) interface{} { return nil } + +// StashEnv stashes the current environment variables and returns an array of +// all environment values as key=val strings. +func StashEnv() []string { + env := os.Environ() + os.Clearenv() + + return env +} + +// PopEnv takes the list of the environment values and injects them into the +// process's environment variable data. Clears any existing environment values +// that may already exist. +func PopEnv(env []string) { + os.Clearenv() + + for _, e := range env { + p := strings.SplitN(e, "=", 2) + k, v := p[0], "" + if len(p) > 1 { + v = p[1] + } + os.Setenv(k, v) + } +} diff --git a/internal/shareddefaults/shared_config.go b/internal/shareddefaults/shared_config.go new file mode 100644 index 00000000000..ebcbc2b40a3 --- /dev/null +++ b/internal/shareddefaults/shared_config.go @@ -0,0 +1,40 @@ +package shareddefaults + +import ( + "os" + "path/filepath" + "runtime" +) + +// SharedCredentialsFilename returns the SDK's default file path +// for the shared credentials file. +// +// Builds the shared config file path based on the OS's platform. +// +// - Linux/Unix: $HOME/.aws/credentials +// - Windows: %USERPROFILE%\.aws\credentials +func SharedCredentialsFilename() string { + return filepath.Join(UserHomeDir(), ".aws", "credentials") +} + +// SharedConfigFilename returns the SDK's default file path for +// the shared config file. +// +// Builds the shared config file path based on the OS's platform. +// +// - Linux/Unix: $HOME/.aws/config +// - Windows: %USERPROFILE%\.aws\config +func SharedConfigFilename() string { + return filepath.Join(UserHomeDir(), ".aws", "config") +} + +// UserHomeDir returns the home directory for the user the process is +// running under. +func UserHomeDir() string { + if runtime.GOOS == "windows" { // Windows + return os.Getenv("USERPROFILE") + } + + // *nix + return os.Getenv("HOME") +} diff --git a/internal/shareddefaults/shared_config_other_test.go b/internal/shareddefaults/shared_config_other_test.go new file mode 100644 index 00000000000..a2fd4558b05 --- /dev/null +++ b/internal/shareddefaults/shared_config_other_test.go @@ -0,0 +1,40 @@ +package shareddefaults_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/internal/shareddefaults" +) + +func TestSharedCredsFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("home_dir", ".aws", "credentials") + + name := shareddefaults.SharedCredentialsFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared creds filename, got %q", e, a) + } +} + +func TestSharedConfigFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("home_dir", ".aws", "config") + + name := shareddefaults.SharedConfigFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared config filename, got %q", e, a) + } +} diff --git a/internal/shareddefaults/shared_config_windows_test.go b/internal/shareddefaults/shared_config_windows_test.go new file mode 100644 index 00000000000..afe96b17deb --- /dev/null +++ b/internal/shareddefaults/shared_config_windows_test.go @@ -0,0 +1,40 @@ +package shareddefaults_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/aws/aws-sdk-go/awstesting" + "github.com/aws/aws-sdk-go/internal/shareddefaults" +) + +func TestSharedCredsFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("profile_dir", ".aws", "credentials") + + name := shareddefaults.SharedCredentialsFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared creds filename, got %q", e, a) + } +} + +func TestSharedConfigFilename(t *testing.T) { + env := awstesting.StashEnv() + defer awstesting.PopEnv(env) + + os.Setenv("HOME", "home_dir") + os.Setenv("USERPROFILE", "profile_dir") + + expect := filepath.Join("profile_dir", ".aws", "config") + + name := shareddefaults.SharedConfigFilename() + if e, a := expect, name; e != a { + t.Errorf("expect %q shared config filename, got %q", e, a) + } +}