1package openstack
2
3import (
4	"github.com/gophercloud/gophercloud"
5	tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
6	tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
7)
8
9/*
10V2EndpointURL discovers the endpoint URL for a specific service from a
11ServiceCatalog acquired during the v2 identity service.
12
13The specified EndpointOpts are used to identify a unique, unambiguous endpoint
14to return. It's an error both when multiple endpoints match the provided
15criteria and when none do. The minimum that can be specified is a Type, but you
16will also often need to specify a Name and/or a Region depending on what's
17available on your OpenStack deployment.
18*/
19func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) {
20	// Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided.
21	var endpoints = make([]tokens2.Endpoint, 0, 1)
22	for _, entry := range catalog.Entries {
23		if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
24			for _, endpoint := range entry.Endpoints {
25				if opts.Region == "" || endpoint.Region == opts.Region {
26					endpoints = append(endpoints, endpoint)
27				}
28			}
29		}
30	}
31
32	// Report an error if the options were ambiguous.
33	if len(endpoints) > 1 {
34		err := &ErrMultipleMatchingEndpointsV2{}
35		err.Endpoints = endpoints
36		return "", err
37	}
38
39	// Extract the appropriate URL from the matching Endpoint.
40	for _, endpoint := range endpoints {
41		switch opts.Availability {
42		case gophercloud.AvailabilityPublic:
43			return gophercloud.NormalizeURL(endpoint.PublicURL), nil
44		case gophercloud.AvailabilityInternal:
45			return gophercloud.NormalizeURL(endpoint.InternalURL), nil
46		case gophercloud.AvailabilityAdmin:
47			return gophercloud.NormalizeURL(endpoint.AdminURL), nil
48		default:
49			err := &ErrInvalidAvailabilityProvided{}
50			err.Argument = "Availability"
51			err.Value = opts.Availability
52			return "", err
53		}
54	}
55
56	// Report an error if there were no matching endpoints.
57	err := &gophercloud.ErrEndpointNotFound{}
58	return "", err
59}
60
61/*
62V3EndpointURL discovers the endpoint URL for a specific service from a Catalog
63acquired during the v3 identity service.
64
65The specified EndpointOpts are used to identify a unique, unambiguous endpoint
66to return. It's an error both when multiple endpoints match the provided
67criteria and when none do. The minimum that can be specified is a Type, but you
68will also often need to specify a Name and/or a Region depending on what's
69available on your OpenStack deployment.
70*/
71func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpts) (string, error) {
72	// Extract Endpoints from the catalog entries that match the requested Type, Interface,
73	// Name if provided, and Region if provided.
74	var endpoints = make([]tokens3.Endpoint, 0, 1)
75	for _, entry := range catalog.Entries {
76		if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
77			for _, endpoint := range entry.Endpoints {
78				if opts.Availability != gophercloud.AvailabilityAdmin &&
79					opts.Availability != gophercloud.AvailabilityPublic &&
80					opts.Availability != gophercloud.AvailabilityInternal {
81					err := &ErrInvalidAvailabilityProvided{}
82					err.Argument = "Availability"
83					err.Value = opts.Availability
84					return "", err
85				}
86				if (opts.Availability == gophercloud.Availability(endpoint.Interface)) &&
87					(opts.Region == "" || endpoint.Region == opts.Region || endpoint.RegionID == opts.Region) {
88					endpoints = append(endpoints, endpoint)
89				}
90			}
91		}
92	}
93
94	// Report an error if the options were ambiguous.
95	if len(endpoints) > 1 {
96		return "", ErrMultipleMatchingEndpointsV3{Endpoints: endpoints}
97	}
98
99	// Extract the URL from the matching Endpoint.
100	for _, endpoint := range endpoints {
101		return gophercloud.NormalizeURL(endpoint.URL), nil
102	}
103
104	// Report an error if there were no matching endpoints.
105	err := &gophercloud.ErrEndpointNotFound{}
106	return "", err
107}
108