55 "fmt"
66 "log"
77 "net/http"
8+ "net/url"
89 "os"
910
1011 "github.com/gophercloud/gophercloud/v2"
@@ -246,20 +247,40 @@ func (c *Config) Authenticate(ctx context.Context) error {
246247
247248// DetermineEndpoint is a helper method to determine if the user wants to
248249// override an endpoint returned from the catalog.
249- func (c * Config ) DetermineEndpoint (client * gophercloud.ServiceClient , service string ) * gophercloud.ServiceClient {
250- finalEndpoint := client .ResourceBaseURL ()
251-
252- if v , ok := c .EndpointOverrides [service ]; ok {
253- if endpoint , ok := v .(string ); ok && endpoint != "" {
254- finalEndpoint = endpoint
255- client .Endpoint = endpoint
256- client .ResourceBase = ""
257- }
250+ func (c * Config ) DetermineEndpoint (client * gophercloud.ServiceClient , eo gophercloud.EndpointOpts , service string ) (* gophercloud.ServiceClient , error ) {
251+ v , ok := c .EndpointOverrides [service ]
252+ if ! ok {
253+ return client , nil
254+ }
255+ val , ok := v .(string )
256+ if ! ok || val == "" {
257+ return client , nil
258258 }
259259
260- log .Printf ("[DEBUG] OpenStack Endpoint for %s: %s" , service , finalEndpoint )
260+ // overriden endpoint is a URL
261+ if u , err := url .Parse (val ); err == nil && u .Scheme != "" && u .Host != "" {
262+ eo .ApplyDefaults (service )
263+ client .ProviderClient = c .OsClient
264+ client .Endpoint = val
265+ client .ResourceBase = ""
266+ client .Type = service
267+ log .Printf ("[DEBUG] OpenStack Endpoint for %s: %s" , service , val )
268+ return client , nil
269+ }
270+
271+ // overriden endpoint is a new service type
272+ eo .ApplyDefaults (val )
273+ url , err := c .OsClient .EndpointLocator (eo )
274+ if err != nil {
275+ log .Printf ("[DEBUG] Cannot set a new OpenStack Endpoint %s alias: %v" , val , err )
276+ return client , err
277+ }
278+ client .ProviderClient = c .OsClient
279+ client .Endpoint = url
280+ client .Type = val
261281
262- return client
282+ log .Printf ("[DEBUG] OpenStack Endpoint for %s alias: %s" , val , url )
283+ return client , nil
263284}
264285
265286// DetermineRegion is a helper method to determine the region based on
@@ -285,19 +306,25 @@ func (c *Config) CommonServiceClientInit(ctx context.Context, newClient commonCo
285306 return nil , err
286307 }
287308
288- client , err := newClient ( c . OsClient , gophercloud.EndpointOpts {
309+ eo := gophercloud.EndpointOpts {
289310 Region : c .DetermineRegion (region ),
290311 Availability : clientconfig .GetEndpointType (c .EndpointType ),
291- })
292-
293- if err != nil {
312+ }
313+ client , err := newClient (c .OsClient , eo )
314+ if err , ok := err .(* gophercloud.ErrEndpointNotFound ); ok && client != nil {
315+ client , e := c .DetermineEndpoint (client , eo , service )
316+ if e != nil {
317+ return client , e
318+ }
319+ // if the endpoint is still not found, return the original error
320+ if client .ProviderClient == nil {
321+ return client , err
322+ }
323+ } else if err != nil {
294324 return client , err
295325 }
296326
297- // Check if an endpoint override was specified for the volume service.
298- client = c .DetermineEndpoint (client , service )
299-
300- return client , nil
327+ return c .DetermineEndpoint (client , eo , service )
301328}
302329
303330func (c * Config ) BlockStorageV1Client (ctx context.Context , region string ) (* gophercloud.ServiceClient , error ) {
@@ -328,86 +355,65 @@ func (c *Config) ImageV2Client(ctx context.Context, region string) (*gophercloud
328355 return c .CommonServiceClientInit (ctx , openstack .NewImageV2 , region , "image" )
329356}
330357
331- func (c * Config ) MessagingV2Client (ctx context.Context , region string ) (* gophercloud.ServiceClient , error ) {
358+ func (c * Config ) MessagingV2Client (ctx context.Context , clientID string , region string ) (* gophercloud.ServiceClient , error ) {
332359 if err := c .Authenticate (ctx ); err != nil {
333360 return nil , err
334361 }
335362
336- client , err := openstack . NewMessagingV2 ( c . OsClient , "" , gophercloud.EndpointOpts {
363+ eo := gophercloud.EndpointOpts {
337364 Region : c .DetermineRegion (region ),
338365 Availability : clientconfig .GetEndpointType (c .EndpointType ),
339- })
340-
341- if err != nil {
366+ }
367+ client , err := openstack .NewMessagingV2 (c .OsClient , clientID , eo )
368+ if err , ok := err .(* gophercloud.ErrEndpointNotFound ); ok && client != nil {
369+ client , e := c .DetermineEndpoint (client , eo , "messaging" )
370+ if e != nil {
371+ return client , e
372+ }
373+ // if the endpoint is still not found, return the original error
374+ if client .ProviderClient == nil {
375+ return client , err
376+ }
377+ } else if err != nil {
342378 return client , err
343379 }
344380
345- // Check if an endpoint override was specified for the messaging service.
346- client = c .DetermineEndpoint (client , "message" )
347-
348- return client , nil
381+ return c .DetermineEndpoint (client , eo , "messaging" )
349382}
350383
351384func (c * Config ) NetworkingV2Client (ctx context.Context , region string ) (* gophercloud.ServiceClient , error ) {
352385 return c .CommonServiceClientInit (ctx , openstack .NewNetworkV2 , region , "network" )
353386}
354387
355388func (c * Config ) ObjectStorageV1Client (ctx context.Context , region string ) (* gophercloud.ServiceClient , error ) {
356- var client * gophercloud.ServiceClient
357- var err error
389+ if ! c .Swauth {
390+ return c .CommonServiceClientInit (ctx , openstack .NewObjectStorageV1 , region , "object-store" )
391+ }
358392
359393 // If Swift Authentication is being used, return a swauth client.
360- // Otherwise, use a Keystone-based client.
361- if c .Swauth {
362- if ! c .DelayedAuth {
363- client , err = swauth .NewObjectStorageV1 (ctx , c .OsClient , swauth.AuthOpts {
364- User : c .Username ,
365- Key : c .Password ,
366- })
367- if err != nil {
368- return nil , err
369- }
370- } else {
371- c .MutexKV .Lock ("SwAuth" )
372- defer c .MutexKV .Unlock ("SwAuth" )
373-
374- if c .swAuthFailed != nil {
375- return nil , c .swAuthFailed
376- }
377-
378- if c .swClient == nil {
379- c .swClient , err = swauth .NewObjectStorageV1 (ctx , c .OsClient , swauth.AuthOpts {
380- User : c .Username ,
381- Key : c .Password ,
382- })
383-
384- if err != nil {
385- c .swAuthFailed = err
386- return nil , err
387- }
388- }
389-
390- client = c .swClient
391- }
392- } else {
393- if err := c .Authenticate (ctx ); err != nil {
394- return nil , err
395- }
396-
397- client , err = openstack .NewObjectStorageV1 (c .OsClient , gophercloud.EndpointOpts {
398- Region : c .DetermineRegion (region ),
399- Availability : clientconfig .GetEndpointType (c .EndpointType ),
394+ if ! c .DelayedAuth {
395+ return swauth .NewObjectStorageV1 (ctx , c .OsClient , swauth.AuthOpts {
396+ User : c .Username ,
397+ Key : c .Password ,
400398 })
399+ }
401400
402- if err != nil {
403- return client , err
404- }
401+ c .MutexKV .Lock ("SwAuth" )
402+ defer c .MutexKV .Unlock ("SwAuth" )
403+
404+ if c .swAuthFailed != nil {
405+ return nil , c .swAuthFailed
405406 }
406407
407- // Check if an endpoint override was specified for the object-store service.
408- client = c .DetermineEndpoint (client , "object-store" )
408+ if c .swClient == nil {
409+ c .swClient , c .swAuthFailed = swauth .NewObjectStorageV1 (ctx , c .OsClient , swauth.AuthOpts {
410+ User : c .Username ,
411+ Key : c .Password ,
412+ })
413+ return c .swClient , c .swAuthFailed
414+ }
409415
410- return client , nil
416+ return c . swClient , nil
411417}
412418
413419func (c * Config ) OrchestrationV1Client (ctx context.Context , region string ) (* gophercloud.ServiceClient , error ) {
0 commit comments