Skip to content

Commit 9b47b9c

Browse files
committed
clientconfig: Ignore OS_CLOUD if explicit cloud config provided
The current behavior of the 'GetCloudFromYAML' and 'AuthOptions' utilities is confusing and the source of much pulled hair. As discussed in the linked bug, the equivalent Python libraries, openstacksdk and (legacy) os_client_config, both default to reading 'OS_CLOUD' only if explicit cloud config has not been provided. However, we're actually overriding what the user provided if 'OS_CLOUD' is set. This is clearly incorrect. Correct things to prefer user-provide cloud configuration, falling back to the environment variable only if this is not provided. While we're here, correctly handle a nil 'opts' arguments in the 'GetCloudFromYAML' function. Previously this was done ad-hoc and was incomplete. Signed-off-by: Stephen Finucane <stephenfin@redhat.com> Closes: #164
1 parent d708520 commit 9b47b9c

2 files changed

Lines changed: 82 additions & 20 deletions

File tree

openstack/clientconfig/requests.go

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ func LoadPublicCloudsYAML() (map[string]Cloud, error) {
183183

184184
// GetCloudFromYAML will return a cloud entry from a clouds.yaml file.
185185
func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) {
186+
if opts == nil {
187+
opts = new(ClientOpts)
188+
}
189+
186190
if opts.YAMLOpts == nil {
187191
opts.YAMLOpts = new(YAMLOpts)
188192
}
@@ -197,19 +201,18 @@ func GetCloudFromYAML(opts *ClientOpts) (*Cloud, error) {
197201
// Determine which cloud to use.
198202
// First see if a cloud name was explicitly set in opts.
199203
var cloudName string
200-
if opts != nil && opts.Cloud != "" {
204+
if opts.Cloud != "" {
201205
cloudName = opts.Cloud
202-
}
203-
204-
// Next see if a cloud name was specified as an environment variable.
205-
// This is supposed to override an explicit opts setting.
206-
envPrefix := "OS_"
207-
if opts.EnvPrefix != "" {
208-
envPrefix = opts.EnvPrefix
209-
}
206+
} else {
207+
// If not, see if a cloud name was specified as an environment variable.
208+
envPrefix := "OS_"
209+
if opts.EnvPrefix != "" {
210+
envPrefix = opts.EnvPrefix
211+
}
210212

211-
if v := env.Getenv(envPrefix + "CLOUD"); v != "" {
212-
cloudName = v
213+
if v := env.Getenv(envPrefix + "CLOUD"); v != "" {
214+
cloudName = v
215+
}
213216
}
214217

215218
var cloud *Cloud
@@ -351,16 +354,17 @@ func AuthOptions(opts *ClientOpts) (*gophercloud.AuthOptions, error) {
351354
var cloudName string
352355
if opts.Cloud != "" {
353356
cloudName = opts.Cloud
354-
}
355-
356-
// Next see if a cloud name was specified as an environment variable.
357-
envPrefix := "OS_"
358-
if opts.EnvPrefix != "" {
359-
envPrefix = opts.EnvPrefix
360-
}
357+
} else {
358+
// If not, see if a cloud name was specified as an environment
359+
// variable.
360+
envPrefix := "OS_"
361+
if opts.EnvPrefix != "" {
362+
envPrefix = opts.EnvPrefix
363+
}
361364

362-
if v := env.Getenv(envPrefix + "CLOUD"); v != "" {
363-
cloudName = v
365+
if v := env.Getenv(envPrefix + "CLOUD"); v != "" {
366+
cloudName = v
367+
}
364368
}
365369

366370
// If a cloud name was determined, try to look it up in clouds.yaml.

openstack/clientconfig/testing/requests_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ func TestGetCloudFromYAML(t *testing.T) {
8484
}
8585
}
8686

87+
func TestGetCloudFromYAMLOSCLOUD(t *testing.T) {
88+
os.Setenv("OS_CLOUD", "california")
89+
90+
clientOpts := &clientconfig.ClientOpts{
91+
Cloud: "hawaii",
92+
}
93+
94+
actual, err := clientconfig.GetCloudFromYAML(clientOpts)
95+
th.AssertNoErr(t, err)
96+
th.AssertDeepEquals(t, &HawaiiCloudYAML, actual)
97+
98+
os.Unsetenv("OS_CLOUD")
99+
}
100+
101+
func TestGetCloudFromYAMLMissingClientOpts(t *testing.T) {
102+
os.Setenv("OS_CLOUD", "california")
103+
104+
actual, err := clientconfig.GetCloudFromYAML(nil)
105+
th.AssertNoErr(t, err)
106+
th.AssertDeepEquals(t, &CaliforniaCloudYAML, actual)
107+
108+
os.Unsetenv("OS_CLOUD")
109+
}
110+
87111
func TestAuthOptionsExplicitCloud(t *testing.T) {
88112
os.Unsetenv("OS_CLOUD")
89113

@@ -116,6 +140,40 @@ func TestAuthOptionsOSCLOUD(t *testing.T) {
116140
os.Unsetenv("FOO_CLOUD")
117141
}
118142

143+
func TestAuthOptionsExplicitCloudAndOSCLOUD(t *testing.T) {
144+
os.Setenv("FOO_CLOUD", "hawaii")
145+
146+
clientOpts := &clientconfig.ClientOpts{
147+
EnvPrefix: "FOO_",
148+
Cloud: "california",
149+
}
150+
151+
actual, err := clientconfig.AuthOptions(clientOpts)
152+
if err != nil {
153+
t.Fatal(err)
154+
}
155+
156+
// We should have ignored the cloud configuration option
157+
th.AssertDeepEquals(t, CaliforniaAuthOpts, actual)
158+
159+
os.Unsetenv("FOO_CLOUD")
160+
}
161+
162+
func TestAuthOptionsMissingClientOpts(t *testing.T) {
163+
os.Setenv("OS_CLOUD", "hawaii")
164+
165+
actual, err := clientconfig.AuthOptions(nil)
166+
if err != nil {
167+
t.Fatal(err)
168+
}
169+
170+
// We should have handled the missing config opts and fallen back to
171+
// defaults
172+
th.AssertDeepEquals(t, HawaiiAuthOpts, actual)
173+
174+
os.Unsetenv("OS_CLOUD")
175+
}
176+
119177
func TestAuthOptionsCreationFromCloudsYAML(t *testing.T) {
120178
os.Unsetenv("OS_CLOUD")
121179

0 commit comments

Comments
 (0)