Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e0b454d

Browse filesBrowse files
EmilienMkayrus
authored andcommitted
Merge pull request #3209 from shiftstack/proper-service-discovery
Configure and respect service type aliases
1 parent fe8ded1 commit e0b454d
Copy full SHA for e0b454d

File tree

6 files changed

+83
-18
lines changed
Filter options

6 files changed

+83
-18
lines changed

‎endpoint_search.go

Copy file name to clipboardExpand all lines: endpoint_search.go
+59-2Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package gophercloud
22

3+
import "slices"
4+
35
// Availability indicates to whom a specific service endpoint is accessible:
46
// the internet at large, internal networks only, or only to administrators.
57
// Different identity services use different terminology for these. Identity v2
@@ -22,6 +24,31 @@ const (
2224
AvailabilityInternal Availability = "internal"
2325
)
2426

27+
// ServiceTypeAliases contains a mapping of service types to any aliases, as
28+
// defined by the OpenStack Service Types Authority. Only service types that
29+
// we support are included.
30+
var ServiceTypeAliases = map[string][]string{
31+
"application-container": {"container"},
32+
"baremetal": {"bare-metal"},
33+
"baremetal-introspection": {},
34+
"block-storage": {"block-store", "volume", "volumev2", "volumev3"},
35+
"compute": {},
36+
"container-infrastructure-management": {"container-infrastructure", "container-infra"},
37+
"database": {},
38+
"dns": {},
39+
"identity": {},
40+
"image": {},
41+
"key-manager": {},
42+
"load-balancer": {},
43+
"message": {"messaging"},
44+
"networking": {},
45+
"object-store": {},
46+
"orchestration": {},
47+
"placement": {},
48+
"shared-file-system": {"sharev2", "share"},
49+
"workflow": {"workflowv2"},
50+
}
51+
2552
// EndpointOpts specifies search criteria used by queries against an
2653
// OpenStack service catalog. The options must contain enough information to
2754
// unambiguously identify one, and only one, endpoint within the catalog.
@@ -30,15 +57,23 @@ const (
3057
// package, like "openstack.NewComputeV2()".
3158
type EndpointOpts struct {
3259
// Type [required] is the service type for the client (e.g., "compute",
33-
// "object-store"). Generally, this will be supplied by the service client
34-
// function, but a user-given value will be honored if provided.
60+
// "object-store"), as defined by the OpenStack Service Types Authority.
61+
// This will generally be supplied by the service client function, but a
62+
// user-given value will be honored if provided.
3563
Type string
3664

3765
// Name [optional] is the service name for the client (e.g., "nova") as it
3866
// appears in the service catalog. Services can have the same Type but a
3967
// different Name, which is why both Type and Name are sometimes needed.
4068
Name string
4169

70+
// Aliases [optional] is the set of aliases of the service type (e.g.
71+
// "volumev2"/"volumev3", "volume" and "block-store" for the
72+
// "block-storage" service type), as defined by the OpenStack Service Types
73+
// Authority. As with Type, this will generally be supplied by the service
74+
// client function, but a user-given value will be honored if provided.
75+
Aliases []string
76+
4277
// Region [required] is the geographic region in which the endpoint resides,
4378
// generally specifying which datacenter should house your resources.
4479
// Required only for services that span multiple regions.
@@ -73,4 +108,26 @@ func (eo *EndpointOpts) ApplyDefaults(t string) {
73108
if eo.Availability == "" {
74109
eo.Availability = AvailabilityPublic
75110
}
111+
if len(eo.Aliases) == 0 {
112+
if aliases, ok := ServiceTypeAliases[eo.Type]; ok {
113+
// happy path: user requested a service type by its official name
114+
eo.Aliases = aliases
115+
} else {
116+
// unhappy path: user requested a service type by its alias or an
117+
// invalid/unsupported service type
118+
// TODO(stephenfin): This should probably be an error in v3
119+
for t, aliases := range ServiceTypeAliases {
120+
if slices.Contains(aliases, eo.Type) {
121+
// we intentionally override the service type, even if it
122+
// was explicitly requested by the user
123+
eo.Type = t
124+
eo.Aliases = aliases
125+
}
126+
}
127+
}
128+
}
129+
}
130+
131+
func (eo *EndpointOpts) Types() []string {
132+
return append([]string{eo.Type}, eo.Aliases...)
76133
}

‎openstack/blockstorage/noauth/requests.go

Copy file name to clipboardExpand all lines: openstack/blockstorage/noauth/requests.go
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func initClientOpts(client *gophercloud.ProviderClient, eo EndpointOpts, clientT
5151

5252
// NewBlockStorageNoAuthV2 creates a ServiceClient that may be used to access "noauth" v2 block storage service.
5353
func NewBlockStorageNoAuthV2(client *gophercloud.ProviderClient, eo EndpointOpts) (*gophercloud.ServiceClient, error) {
54-
return initClientOpts(client, eo, "volumev2")
54+
return initClientOpts(client, eo, "block-storage")
5555
}
5656

5757
// NewBlockStorageNoAuthV3 creates a ServiceClient that may be used to access "noauth" v3 block storage service.
5858
func NewBlockStorageNoAuthV3(client *gophercloud.ProviderClient, eo EndpointOpts) (*gophercloud.ServiceClient, error) {
59-
return initClientOpts(client, eo, "volumev3")
59+
return initClientOpts(client, eo, "block-storage")
6060
}

‎openstack/client.go

Copy file name to clipboardExpand all lines: openstack/client.go
+9-7Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOp
344344
}, nil
345345
}
346346

347+
// TODO(stephenfin): Allow passing aliases to all New${SERVICE}V${VERSION} methods in v3
347348
func initClientOpts(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts, clientType string) (*gophercloud.ServiceClient, error) {
348349
sc := new(gophercloud.ServiceClient)
349350
eo.ApplyDefaults(clientType)
@@ -393,6 +394,7 @@ func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpt
393394
return sc, err
394395
}
395396

397+
// TODO(stephenfin): Remove this in v3. We no longer support the V1 Block Storage service.
396398
// NewBlockStorageV1 creates a ServiceClient that may be used to access the v1
397399
// block storage service.
398400
func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
@@ -402,17 +404,17 @@ func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
402404
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2
403405
// block storage service.
404406
func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
405-
return initClientOpts(client, eo, "volumev2")
407+
return initClientOpts(client, eo, "block-storage")
406408
}
407409

408410
// NewBlockStorageV3 creates a ServiceClient that may be used to access the v3 block storage service.
409411
func NewBlockStorageV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
410-
return initClientOpts(client, eo, "volumev3")
412+
return initClientOpts(client, eo, "block-storage")
411413
}
412414

413415
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service.
414416
func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
415-
return initClientOpts(client, eo, "sharev2")
417+
return initClientOpts(client, eo, "shared-file-system")
416418
}
417419

418420
// NewOrchestrationV1 creates a ServiceClient that may be used to access the v1
@@ -457,14 +459,14 @@ func NewLoadBalancerV2(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
457459
// NewMessagingV2 creates a ServiceClient that may be used with the v2 messaging
458460
// service.
459461
func NewMessagingV2(client *gophercloud.ProviderClient, clientID string, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
460-
sc, err := initClientOpts(client, eo, "messaging")
462+
sc, err := initClientOpts(client, eo, "message")
461463
sc.MoreHeaders = map[string]string{"Client-ID": clientID}
462464
return sc, err
463465
}
464466

465467
// NewContainerV1 creates a ServiceClient that may be used with v1 container package
466468
func NewContainerV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
467-
return initClientOpts(client, eo, "container")
469+
return initClientOpts(client, eo, "application-container")
468470
}
469471

470472
// NewKeyManagerV1 creates a ServiceClient that may be used with the v1 key
@@ -478,12 +480,12 @@ func NewKeyManagerV1(client *gophercloud.ProviderClient, eo gophercloud.Endpoint
478480
// NewContainerInfraV1 creates a ServiceClient that may be used with the v1 container infra management
479481
// package.
480482
func NewContainerInfraV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
481-
return initClientOpts(client, eo, "container-infra")
483+
return initClientOpts(client, eo, "container-infrastructure-management")
482484
}
483485

484486
// NewWorkflowV2 creates a ServiceClient that may be used with the v2 workflow management package.
485487
func NewWorkflowV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
486-
return initClientOpts(client, eo, "workflowv2")
488+
return initClientOpts(client, eo, "workflow")
487489
}
488490

489491
// NewPlacementV1 creates a ServiceClient that may be used with the placement package.

‎openstack/endpoint_location.go

Copy file name to clipboardExpand all lines: openstack/endpoint_location.go
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package openstack
22

33
import (
4+
"slices"
5+
46
"github.com/gophercloud/gophercloud/v2"
57
tokens2 "github.com/gophercloud/gophercloud/v2/openstack/identity/v2/tokens"
68
tokens3 "github.com/gophercloud/gophercloud/v2/openstack/identity/v3/tokens"
@@ -20,7 +22,7 @@ func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpt
2022
// Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided.
2123
var endpoints = make([]tokens2.Endpoint, 0, 1)
2224
for _, entry := range catalog.Entries {
23-
if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
25+
if (slices.Contains(opts.Types(), entry.Type)) && (opts.Name == "" || entry.Name == opts.Name) {
2426
for _, endpoint := range entry.Endpoints {
2527
if opts.Region == "" || endpoint.Region == opts.Region {
2628
endpoints = append(endpoints, endpoint)
@@ -74,7 +76,7 @@ func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpt
7476
// Name if provided, and Region if provided.
7577
var endpoints = make([]tokens3.Endpoint, 0, 1)
7678
for _, entry := range catalog.Entries {
77-
if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
79+
if (slices.Contains(opts.Types(), entry.Type)) && (opts.Name == "" || entry.Name == opts.Name) {
7880
for _, endpoint := range entry.Endpoints {
7981
if opts.Availability != gophercloud.AvailabilityAdmin &&
8082
opts.Availability != gophercloud.AvailabilityPublic &&

‎service_client.go

Copy file name to clipboardExpand all lines: service_client.go
+7-3Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,25 @@ func (client *ServiceClient) Head(ctx context.Context, url string, opts *Request
115115
}
116116

117117
func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) {
118+
serviceType := client.Type
119+
118120
switch client.Type {
119121
case "compute":
120122
opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
121-
case "sharev2":
123+
case "shared-file-system", "sharev2", "share":
122124
opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion
123-
case "volume":
125+
case "block-storage", "block-store", "volume", "volumev3":
124126
opts.MoreHeaders["X-OpenStack-Volume-API-Version"] = client.Microversion
127+
// cinder should accept block-storage but (as of Dalmatian) does not
128+
serviceType = "volume"
125129
case "baremetal":
126130
opts.MoreHeaders["X-OpenStack-Ironic-API-Version"] = client.Microversion
127131
case "baremetal-introspection":
128132
opts.MoreHeaders["X-OpenStack-Ironic-Inspector-API-Version"] = client.Microversion
129133
}
130134

131135
if client.Type != "" {
132-
opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion
136+
opts.MoreHeaders["OpenStack-API-Version"] = serviceType + " " + client.Microversion
133137
}
134138
}
135139

‎testing/endpoint_search_test.go

Copy file name to clipboardExpand all lines: testing/endpoint_search_test.go
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import (
1010
func TestApplyDefaultsToEndpointOpts(t *testing.T) {
1111
eo := gophercloud.EndpointOpts{Availability: gophercloud.AvailabilityPublic}
1212
eo.ApplyDefaults("compute")
13-
expected := gophercloud.EndpointOpts{Availability: gophercloud.AvailabilityPublic, Type: "compute"}
13+
expected := gophercloud.EndpointOpts{Availability: gophercloud.AvailabilityPublic, Type: "compute", Aliases: []string{}}
1414
th.CheckDeepEquals(t, expected, eo)
1515

1616
eo = gophercloud.EndpointOpts{Type: "compute"}
1717
eo.ApplyDefaults("object-store")
18-
expected = gophercloud.EndpointOpts{Availability: gophercloud.AvailabilityPublic, Type: "compute"}
18+
expected = gophercloud.EndpointOpts{Availability: gophercloud.AvailabilityPublic, Type: "compute", Aliases: []string{}}
1919
th.CheckDeepEquals(t, expected, eo)
2020
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.