// V2EndpointURL discovers the endpoint URL for a specific service from a ServiceCatalog acquired // during the v2 identity service. The specified EndpointOpts are used to identify a unique, // unambiguous endpoint to return. It's an error both when multiple endpoints match the provided // criteria and when none do. The minimum that can be specified is a Type, but you will also often // need to specify a Name and/or a Region depending on what's available on your OpenStack // deployment. func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) { // Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided. var endpoints = make([]tokens2.Endpoint, 0, 1) for _, entry := range catalog.Entries { if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) { for _, endpoint := range entry.Endpoints { if opts.Region == "" || endpoint.Region == opts.Region { endpoints = append(endpoints, endpoint) } } } } // Report an error if the options were ambiguous. if len(endpoints) > 1 { err := &ErrMultipleMatchingEndpointsV2{} err.Endpoints = endpoints return "", err } // Extract the appropriate URL from the matching Endpoint. for _, endpoint := range endpoints { switch opts.Availability { case gophercloud.AvailabilityPublic: return gophercloud.NormalizeURL(endpoint.PublicURL), nil case gophercloud.AvailabilityInternal: return gophercloud.NormalizeURL(endpoint.InternalURL), nil case gophercloud.AvailabilityAdmin: return gophercloud.NormalizeURL(endpoint.AdminURL), nil default: err := &ErrInvalidAvailabilityProvided{} err.Argument = "Availability" err.Value = opts.Availability return "", err } } // Report an error if there were no matching endpoints. err := &gophercloud.ErrEndpointNotFound{} return "", err }
func TestNormalizeURL(t *testing.T) { urls := []string{ "NoSlashAtEnd", "SlashAtEnd/", } expected := []string{ "NoSlashAtEnd/", "SlashAtEnd/", } for i := 0; i < len(expected); i++ { th.CheckEquals(t, expected[i], gophercloud.NormalizeURL(urls[i])) } }
// NewClient prepares an unauthenticated ProviderClient instance. // Most users will probably prefer using the AuthenticatedClient function instead. // This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly, // for example. func NewClient(endpoint string) (*gophercloud.ProviderClient, error) { u, err := url.Parse(endpoint) if err != nil { return nil, err } hadPath := u.Path != "" u.Path, u.RawQuery, u.Fragment = "", "", "" base := u.String() endpoint = gophercloud.NormalizeURL(endpoint) base = gophercloud.NormalizeURL(base) if hadPath { return &gophercloud.ProviderClient{ IdentityBase: base, IdentityEndpoint: endpoint, }, nil } return &gophercloud.ProviderClient{ IdentityBase: base, IdentityEndpoint: "", }, nil }
// NewObjectStorageV1 creates a Swauth-authenticated *gophercloud.ServiceClient // client that can issue ObjectStorage-based API calls. func NewObjectStorageV1(pc *gophercloud.ProviderClient, authOpts AuthOpts) (*gophercloud.ServiceClient, error) { auth, err := Auth(pc, authOpts).Extract() if err != nil { return nil, err } swiftClient := &gophercloud.ServiceClient{ ProviderClient: pc, Endpoint: gophercloud.NormalizeURL(auth.StorageURL), } swiftClient.TokenID = auth.Token return swiftClient, nil }
// V3EndpointURL discovers the endpoint URL for a specific service from a Catalog acquired // during the v3 identity service. The specified EndpointOpts are used to identify a unique, // unambiguous endpoint to return. It's an error both when multiple endpoints match the provided // criteria and when none do. The minimum that can be specified is a Type, but you will also often // need to specify a Name and/or a Region depending on what's available on your OpenStack // deployment. func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) { // Extract Endpoints from the catalog entries that match the requested Type, Interface, // Name if provided, and Region if provided. var endpoints = make([]tokens3.Endpoint, 0, 1) for _, entry := range catalog.Entries { if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) { for _, endpoint := range entry.Endpoints { if opts.Availability != gophercloud.AvailabilityAdmin && opts.Availability != gophercloud.AvailabilityPublic && opts.Availability != gophercloud.AvailabilityInternal { err := &ErrInvalidAvailabilityProvided{} err.Argument = "Availability" err.Value = opts.Availability return "", err } if (opts.Availability == gophercloud.Availability(endpoint.Interface)) && (opts.Region == "" || endpoint.Region == opts.Region) { endpoints = append(endpoints, endpoint) } } } } // Report an error if the options were ambiguous. if len(endpoints) > 1 { return "", ErrMultipleMatchingEndpointsV3{Endpoints: endpoints} } // Extract the URL from the matching Endpoint. for _, endpoint := range endpoints { return gophercloud.NormalizeURL(endpoint.URL), nil } // Report an error if there were no matching endpoints. err := &gophercloud.ErrEndpointNotFound{} return "", err }