66
66
authMode identity.Authenticator
68
68
auth AuthenticatingClient
69
70
// Service type to endpoint URLs for each available region
70
71
regionServiceURLs map[string]identity.ServiceURLs
71
73
// Service type to endpoint URLs for the authenticated region
72
74
serviceURLs identity.ServiceURLs
73
76
// The service types which must be available after authentication,
74
77
// or else services which use this client will not be able to function as expected.
75
78
requiredServiceTypes []string
210
213
missingServiceTypes, possibleRegions = c.possibleRegions(existingServiceTypes)
211
errorPrefix = fmt.Sprintf("the configured region %q does not allow access to all required services, namely: %q\n"+
212
"access to these services is missing: %q",
214
errorPrefix = fmt.Sprintf("the configured region %q does not allow access to all required services, namely: %s\n"+
215
"access to these services is missing: %s",
214
217
strings.Join(c.requiredServiceTypes, ", "),
215
218
strings.Join(missingServiceTypes, ", "))
217
220
if len(missingServiceTypes) > 0 {
218
221
if len(possibleRegions) > 0 {
219
return fmt.Errorf("%s\none of these regions may be suitable instead: %q",
222
return fmt.Errorf("%s\none of these regions may be suitable instead: %s",
221
224
strings.Join(possibleRegions, ", "))
232
235
// required service types. The service types which are accessible, accessibleServiceTypes, is passed in and the
233
236
// method returns what the missing service types are as well as valid regions.
234
237
func (c *authenticatingClient) possibleRegions(accessibleServiceTypes []string) (missingServiceTypes []string, possibleRegions []string) {
235
serviceTypeRegions := make(map[string][]string)
238
var serviceTypeRegions map[string][]string
236
239
// Figure out the missing service types and build up a map of all service types to regions
237
240
// obtained from the authentication response.
238
241
for _, serviceType := range c.requiredServiceTypes {
239
242
if !containsString(accessibleServiceTypes, serviceType) {
240
243
missingServiceTypes = append(missingServiceTypes, serviceType)
241
for region, serviceURLs := range c.regionServiceURLs {
242
for regionServiceType := range serviceURLs {
243
regions := serviceTypeRegions[regionServiceType]
244
if !containsString(regions, region) {
245
serviceTypeRegions[regionServiceType] = append(regions, region)
244
serviceTypeRegions = c.extractServiceTypeRegions()
251
248
// Look at the region lists for each missing service type and determine which subset of those could
252
249
// be used to allow access to all required service types. The most specific regions are used.
253
250
if len(missingServiceTypes) == 1 {
254
251
possibleRegions = serviceTypeRegions[missingServiceTypes[0]]
256
253
for _, serviceType := range missingServiceTypes {
257
regions := serviceTypeRegions[serviceType]
258
254
for _, serviceTypeCompare := range missingServiceTypes {
259
255
if serviceType == serviceTypeCompare {
262
for _, region := range regions {
263
regionsCompare := serviceTypeRegions[serviceTypeCompare]
264
if !containsBaseRegion(regionsCompare, region) && containsSuperRegion(regionsCompare, region) {
265
possibleRegions = append(possibleRegions, region)
258
possibleRegions = appendPossibleRegions(serviceType, serviceTypeCompare, serviceTypeRegions, possibleRegions)
266
// utility function to extract map of service types -> region
267
func (c *authenticatingClient) extractServiceTypeRegions() map[string][]string {
268
serviceTypeRegions := make(map[string][]string)
269
for region, serviceURLs := range c.regionServiceURLs {
270
for regionServiceType := range serviceURLs {
271
regions := serviceTypeRegions[regionServiceType]
272
if !containsString(regions, region) {
273
serviceTypeRegions[regionServiceType] = append(regions, region)
277
return serviceTypeRegions
280
// extract the common regions for each service type and append them to the possible regions slice.
281
func appendPossibleRegions(serviceType, serviceTypeCompare string, serviceTypeRegions map[string][]string,
282
possibleRegions []string) []string {
283
regions := serviceTypeRegions[serviceType]
284
for _, region := range regions {
285
regionsCompare := serviceTypeRegions[serviceTypeCompare]
286
if !containsBaseRegion(regionsCompare, region) && containsSuperRegion(regionsCompare, region) {
287
possibleRegions = append(possibleRegions, region)
290
return possibleRegions
275
293
// utility function to see if element exists in values slice.
276
294
func containsString(values []string, element string) bool {
277
295
for _, value := range values {