// Auth performs an authentication request for a Swauth-based user. func Auth(c *gophercloud.ProviderClient, opts AuthOptsBuilder) (r GetAuthResult) { h := make(map[string]string) if opts != nil { headers, err := opts.ToAuthOptsMap() if err != nil { r.Err = err return } for k, v := range headers { h[k] = v } } resp, err := c.Request("GET", getURL(c), &gophercloud.RequestOpts{ MoreHeaders: h, OkCodes: []int{200}, }) if resp != nil { r.Header = resp.Header } r.Err = err return r }
// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service. func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { eo.ApplyDefaults("database") url, err := client.EndpointLocator(eo) if err != nil { return nil, err } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil }
// NewBlockStorageV2 creates a ServiceClient that may be used to access the v2 block storage service. func NewBlockStorageV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { eo.ApplyDefaults("volumev2") url, err := client.EndpointLocator(eo) if err != nil { return nil, err } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil }
// NewSharedFileSystemV2 creates a ServiceClient that may be used to access the v2 shared file system service. func NewSharedFileSystemV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { eo.ApplyDefaults("sharev2") url, err := client.EndpointLocator(eo) if err != nil { return nil, err } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil }
// NewImageServiceV2 creates a ServiceClient that may be used to access the v2 image service. func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { eo.ApplyDefaults("image") url, err := client.EndpointLocator(eo) if err != nil { return nil, err } return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url, ResourceBase: url + "v2/"}, nil }
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service. func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { endpoint := client.IdentityBase + "v3/" var err error if !reflect.DeepEqual(eo, gophercloud.EndpointOpts{}) { eo.ApplyDefaults("identity") endpoint, err = client.EndpointLocator(eo) if err != nil { return nil, err } } return &gophercloud.ServiceClient{ ProviderClient: client, Endpoint: endpoint, }, nil }
func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { v2Client, err := NewIdentityV2(client, eo) if err != nil { return err } if endpoint != "" { v2Client.Endpoint = endpoint } v2Opts := tokens2.AuthOptions{ IdentityEndpoint: options.IdentityEndpoint, Username: options.Username, Password: options.Password, TenantID: options.TenantID, TenantName: options.TenantName, AllowReauth: options.AllowReauth, TokenID: options.TokenID, } result := tokens2.Create(v2Client, v2Opts) token, err := result.ExtractToken() if err != nil { return err } catalog, err := result.ExtractServiceCatalog() if err != nil { return err } if options.AllowReauth { client.ReauthFunc = func() error { client.TokenID = "" return v2auth(client, endpoint, options, eo) } } client.TokenID = token.ID client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { return V2EndpointURL(catalog, opts) } return nil }
func v3auth(client *gophercloud.ProviderClient, endpoint string, opts tokens3.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error { // Override the generated service endpoint with the one returned by the version endpoint. v3Client, err := NewIdentityV3(client, eo) if err != nil { return err } if endpoint != "" { v3Client.Endpoint = endpoint } result := tokens3.Create(v3Client, opts) token, err := result.ExtractToken() if err != nil { return err } catalog, err := result.ExtractServiceCatalog() if err != nil { return err } client.TokenID = token.ID if opts.CanReauth() { client.ReauthFunc = func() error { client.TokenID = "" return v3auth(client, endpoint, opts, eo) } } client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { return V3EndpointURL(catalog, opts) } return nil }
func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error { // Override the generated service endpoint with the one returned by the version endpoint. v3Client, err := NewIdentityV3(client, eo) if err != nil { return err } if endpoint != "" { v3Client.Endpoint = endpoint } // copy the auth options to a local variable that we can change. `options` // needs to stay as-is for reauth purposes v3Options := options var scope *tokens3.Scope if options.TenantID != "" { scope = &tokens3.Scope{ ProjectID: options.TenantID, } v3Options.TenantID = "" v3Options.TenantName = "" } else { if options.TenantName != "" { scope = &tokens3.Scope{ ProjectName: options.TenantName, DomainID: options.DomainID, DomainName: options.DomainName, } v3Options.TenantName = "" } } v3Opts := tokens3.AuthOptions{ IdentityEndpoint: v3Options.IdentityEndpoint, Username: v3Options.Username, UserID: v3Options.UserID, Password: v3Options.Password, DomainID: v3Options.DomainID, DomainName: v3Options.DomainName, TenantID: v3Options.TenantID, TenantName: v3Options.TenantName, AllowReauth: v3Options.AllowReauth, TokenID: v3Options.TokenID, } result := tokens3.Create(v3Client, v3Opts, scope) token, err := result.ExtractToken() if err != nil { return err } catalog, err := result.ExtractServiceCatalog() if err != nil { return err } client.TokenID = token.ID if options.AllowReauth { client.ReauthFunc = func() error { client.TokenID = "" return v3auth(client, endpoint, options, eo) } } client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) { return V3EndpointURL(catalog, opts) } return nil }
// ChooseVersion queries the base endpoint of an API to choose the most recent non-experimental alternative from a service's // published versions. // It returns the highest-Priority Version among the alternatives that are provided, as well as its corresponding endpoint. func ChooseVersion(client *gophercloud.ProviderClient, recognized []*Version) (*Version, string, error) { type linkResp struct { Href string `json:"href"` Rel string `json:"rel"` } type valueResp struct { ID string `json:"id"` Status string `json:"status"` Links []linkResp `json:"links"` } type versionsResp struct { Values []valueResp `json:"values"` } type response struct { Versions versionsResp `json:"versions"` } normalize := func(endpoint string) string { if !strings.HasSuffix(endpoint, "/") { return endpoint + "/" } return endpoint } identityEndpoint := normalize(client.IdentityEndpoint) // If a full endpoint is specified, check version suffixes for a match first. for _, v := range recognized { if strings.HasSuffix(identityEndpoint, v.Suffix) { return v, identityEndpoint, nil } } var resp response _, err := client.Request("GET", client.IdentityBase, &gophercloud.RequestOpts{ JSONResponse: &resp, OkCodes: []int{200, 300}, }) if err != nil { return nil, "", err } byID := make(map[string]*Version) for _, version := range recognized { byID[version.ID] = version } var highest *Version var endpoint string for _, value := range resp.Versions.Values { href := "" for _, link := range value.Links { if link.Rel == "self" { href = normalize(link.Href) } } if matching, ok := byID[value.ID]; ok { // Prefer a version that exactly matches the provided endpoint. if href == identityEndpoint { if href == "" { return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase) } return matching, href, nil } // Otherwise, find the highest-priority version with a whitelisted status. if goodStatus[strings.ToLower(value.Status)] { if highest == nil || matching.Priority > highest.Priority { highest = matching endpoint = href } } } } if highest == nil { return nil, "", fmt.Errorf("No supported version available from endpoint %s", client.IdentityBase) } if endpoint == "" { return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", highest.ID, client.IdentityBase) } return highest, endpoint, nil }