Updated to latest gophercloud/utils with app cred support.

This commit is contained in:
Kevin Bulebush 2019-02-09 22:04:12 -05:00
parent 4025d1da2e
commit 947a172a80
6 changed files with 196 additions and 108 deletions

2
go.mod
View File

@ -62,7 +62,7 @@ require (
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d
github.com/gophercloud/gophercloud v0.0.0-20180903124057-ea7289ebdf06
github.com/gophercloud/utils v0.0.0-20180806215700-d6e28a8b3199
github.com/gophercloud/utils v0.0.0-20190124192022-a5c25e7a53a6
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777 // indirect
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect

4
go.sum
View File

@ -135,8 +135,8 @@ github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d h1:rXQlD9GXkjA/PQZhmEa
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gophercloud/gophercloud v0.0.0-20180903124057-ea7289ebdf06 h1:m7Rt/8En7PLrM7PQpykdZBPKUdgZWN6MwiA/ChVIoxs=
github.com/gophercloud/gophercloud v0.0.0-20180903124057-ea7289ebdf06/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gophercloud/utils v0.0.0-20180806215700-d6e28a8b3199 h1:mmwryCmmFkCxL3t5r6syrbk1eyP6tP9q/whDdAiM9Mw=
github.com/gophercloud/utils v0.0.0-20180806215700-d6e28a8b3199/go.mod h1:wjDF8z83zTeg5eMLml5EBSlAhbF7G8DobyI1YsMuyzw=
github.com/gophercloud/utils v0.0.0-20190124192022-a5c25e7a53a6 h1:Cw/B8Bu7Rryomxf7bjc8zNfIyLgjxsDd91n0eGRWpuo=
github.com/gophercloud/utils v0.0.0-20190124192022-a5c25e7a53a6/go.mod h1:wjDF8z83zTeg5eMLml5EBSlAhbF7G8DobyI1YsMuyzw=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v0.0.0-20170319172727-a91eba7f9777 h1:JIM+OacoOJRU30xpjMf8sulYqjr0ViA3WDrTX6j/yDI=

View File

@ -9,7 +9,7 @@ import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v2"
)
// AuthType respresents a valid method of authentication.
@ -30,6 +30,9 @@ const (
AuthV3Password AuthType = "v3password"
// AuthV3Token defines version 3 of the token
AuthV3Token AuthType = "v3token"
// AuthV3ApplicationCredential defines version 3 of the application credential
AuthV3ApplicationCredential AuthType = "v3applicationcredential"
)
// ClientOpts represents options to customize the way a client is
@ -333,6 +336,8 @@ func determineIdentityAPI(cloud *Cloud, opts *ClientOpts) string {
identityAPI = "3"
case AuthV3Token:
identityAPI = "3"
case AuthV3ApplicationCredential:
identityAPI = "3"
}
}
@ -353,40 +358,52 @@ func v2auth(cloud *Cloud, opts *ClientOpts) (*gophercloud.AuthOptions, error) {
envPrefix = opts.EnvPrefix
}
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
cloud.AuthInfo.AuthURL = v
if cloud.AuthInfo.AuthURL == "" {
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
cloud.AuthInfo.AuthURL = v
}
}
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
cloud.AuthInfo.Token = v
if cloud.AuthInfo.Token == "" {
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
cloud.AuthInfo.Token = v
}
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
cloud.AuthInfo.Token = v
}
}
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
cloud.AuthInfo.Token = v
if cloud.AuthInfo.Username == "" {
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
cloud.AuthInfo.Username = v
}
}
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
cloud.AuthInfo.Username = v
if cloud.AuthInfo.Password == "" {
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
cloud.AuthInfo.Password = v
}
}
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
cloud.AuthInfo.Password = v
if cloud.AuthInfo.ProjectID == "" {
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
}
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
if cloud.AuthInfo.ProjectName == "" {
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
}
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
}
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
}
}
ao := &gophercloud.AuthOptions{
@ -409,109 +426,161 @@ func v3auth(cloud *Cloud, opts *ClientOpts) (*gophercloud.AuthOptions, error) {
envPrefix = opts.EnvPrefix
}
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
cloud.AuthInfo.AuthURL = v
if cloud.AuthInfo.AuthURL == "" {
if v := os.Getenv(envPrefix + "AUTH_URL"); v != "" {
cloud.AuthInfo.AuthURL = v
}
}
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
cloud.AuthInfo.Token = v
if cloud.AuthInfo.Token == "" {
if v := os.Getenv(envPrefix + "TOKEN"); v != "" {
cloud.AuthInfo.Token = v
}
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
cloud.AuthInfo.Token = v
}
}
if v := os.Getenv(envPrefix + "AUTH_TOKEN"); v != "" {
cloud.AuthInfo.Token = v
if cloud.AuthInfo.Username == "" {
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
cloud.AuthInfo.Username = v
}
}
if v := os.Getenv(envPrefix + "USERNAME"); v != "" {
cloud.AuthInfo.Username = v
if cloud.AuthInfo.UserID == "" {
if v := os.Getenv(envPrefix + "USER_ID"); v != "" {
cloud.AuthInfo.UserID = v
}
}
if v := os.Getenv(envPrefix + "USER_ID"); v != "" {
cloud.AuthInfo.UserID = v
if cloud.AuthInfo.Password == "" {
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
cloud.AuthInfo.Password = v
}
}
if v := os.Getenv(envPrefix + "PASSWORD"); v != "" {
cloud.AuthInfo.Password = v
if cloud.AuthInfo.ProjectID == "" {
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
}
}
if v := os.Getenv(envPrefix + "TENANT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
if cloud.AuthInfo.ProjectName == "" {
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
}
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
}
}
if v := os.Getenv(envPrefix + "PROJECT_ID"); v != "" {
cloud.AuthInfo.ProjectID = v
if cloud.AuthInfo.DomainID == "" {
if v := os.Getenv(envPrefix + "DOMAIN_ID"); v != "" {
cloud.AuthInfo.DomainID = v
}
}
if v := os.Getenv(envPrefix + "TENANT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
if cloud.AuthInfo.DomainName == "" {
if v := os.Getenv(envPrefix + "DOMAIN_NAME"); v != "" {
cloud.AuthInfo.DomainName = v
}
}
if v := os.Getenv(envPrefix + "PROJECT_NAME"); v != "" {
cloud.AuthInfo.ProjectName = v
if cloud.AuthInfo.DefaultDomain == "" {
if v := os.Getenv(envPrefix + "DEFAULT_DOMAIN"); v != "" {
cloud.AuthInfo.DefaultDomain = v
}
}
if v := os.Getenv(envPrefix + "DOMAIN_ID"); v != "" {
cloud.AuthInfo.DomainID = v
if cloud.AuthInfo.ProjectDomainID == "" {
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_ID"); v != "" {
cloud.AuthInfo.ProjectDomainID = v
}
}
if v := os.Getenv(envPrefix + "DOMAIN_NAME"); v != "" {
cloud.AuthInfo.DomainName = v
if cloud.AuthInfo.ProjectDomainName == "" {
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_NAME"); v != "" {
cloud.AuthInfo.ProjectDomainName = v
}
}
if v := os.Getenv(envPrefix + "DEFAULT_DOMAIN"); v != "" {
cloud.AuthInfo.DefaultDomain = v
if cloud.AuthInfo.UserDomainID == "" {
if v := os.Getenv(envPrefix + "USER_DOMAIN_ID"); v != "" {
cloud.AuthInfo.UserDomainID = v
}
}
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_ID"); v != "" {
cloud.AuthInfo.ProjectDomainID = v
if cloud.AuthInfo.UserDomainName == "" {
if v := os.Getenv(envPrefix + "USER_DOMAIN_NAME"); v != "" {
cloud.AuthInfo.UserDomainName = v
}
}
if v := os.Getenv(envPrefix + "PROJECT_DOMAIN_NAME"); v != "" {
cloud.AuthInfo.ProjectDomainName = v
if cloud.AuthInfo.ApplicationCredentialID == "" {
if v := os.Getenv(envPrefix + "APPLICATION_CREDENTIAL_ID"); v != "" {
cloud.AuthInfo.ApplicationCredentialID = v
}
}
if v := os.Getenv(envPrefix + "USER_DOMAIN_ID"); v != "" {
cloud.AuthInfo.UserDomainID = v
if cloud.AuthInfo.ApplicationCredentialName == "" {
if v := os.Getenv(envPrefix + "APPLICATION_CREDENTIAL_NAME"); v != "" {
cloud.AuthInfo.ApplicationCredentialName = v
}
}
if v := os.Getenv(envPrefix + "USER_DOMAIN_NAME"); v != "" {
cloud.AuthInfo.UserDomainName = v
if cloud.AuthInfo.ApplicationCredentialSecret == "" {
if v := os.Getenv(envPrefix + "APPLICATION_CREDENTIAL_SECRET"); v != "" {
cloud.AuthInfo.ApplicationCredentialSecret = v
}
}
// Build a scope and try to do it correctly.
// https://github.com/openstack/os-client-config/blob/master/os_client_config/config.py#L595
scope := new(gophercloud.AuthScope)
if !isProjectScoped(cloud.AuthInfo) {
if cloud.AuthInfo.DomainID != "" {
scope.DomainID = cloud.AuthInfo.DomainID
} else if cloud.AuthInfo.DomainName != "" {
scope.DomainName = cloud.AuthInfo.DomainName
}
} else {
// If Domain* is set, but UserDomain* or ProjectDomain* aren't,
// then use Domain* as the default setting.
cloud = setDomainIfNeeded(cloud)
if cloud.AuthInfo.ProjectID != "" {
scope.ProjectID = cloud.AuthInfo.ProjectID
// Application credentials don't support scope
if !isApplicationCredential(cloud.AuthInfo) {
if !isProjectScoped(cloud.AuthInfo) {
if cloud.AuthInfo.DomainID != "" {
scope.DomainID = cloud.AuthInfo.DomainID
} else if cloud.AuthInfo.DomainName != "" {
scope.DomainName = cloud.AuthInfo.DomainName
}
} else {
scope.ProjectName = cloud.AuthInfo.ProjectName
scope.DomainID = cloud.AuthInfo.ProjectDomainID
scope.DomainName = cloud.AuthInfo.ProjectDomainName
// If Domain* is set, but UserDomain* or ProjectDomain* aren't,
// then use Domain* as the default setting.
cloud = setDomainIfNeeded(cloud)
if cloud.AuthInfo.ProjectID != "" {
scope.ProjectID = cloud.AuthInfo.ProjectID
} else {
scope.ProjectName = cloud.AuthInfo.ProjectName
scope.DomainID = cloud.AuthInfo.ProjectDomainID
scope.DomainName = cloud.AuthInfo.ProjectDomainName
}
}
}
ao := &gophercloud.AuthOptions{
Scope: scope,
IdentityEndpoint: cloud.AuthInfo.AuthURL,
TokenID: cloud.AuthInfo.Token,
Username: cloud.AuthInfo.Username,
UserID: cloud.AuthInfo.UserID,
Password: cloud.AuthInfo.Password,
TenantID: cloud.AuthInfo.ProjectID,
TenantName: cloud.AuthInfo.ProjectName,
DomainID: cloud.AuthInfo.UserDomainID,
DomainName: cloud.AuthInfo.UserDomainName,
Scope: scope,
IdentityEndpoint: cloud.AuthInfo.AuthURL,
TokenID: cloud.AuthInfo.Token,
Username: cloud.AuthInfo.Username,
UserID: cloud.AuthInfo.UserID,
Password: cloud.AuthInfo.Password,
TenantID: cloud.AuthInfo.ProjectID,
TenantName: cloud.AuthInfo.ProjectName,
DomainID: cloud.AuthInfo.UserDomainID,
DomainName: cloud.AuthInfo.UserDomainName,
ApplicationCredentialID: cloud.AuthInfo.ApplicationCredentialID,
ApplicationCredentialName: cloud.AuthInfo.ApplicationCredentialName,
ApplicationCredentialSecret: cloud.AuthInfo.ApplicationCredentialSecret,
}
// If an auth_type of "token" was specified, then make sure
@ -591,24 +660,23 @@ func NewServiceClient(service string, opts *ClientOpts) (*gophercloud.ServiceCli
}
// Determine the region to use.
// First, see if the cloud entry has one.
// First, check if the REGION_NAME environment variable is set.
var region string
if v := os.Getenv(envPrefix + "REGION_NAME"); v != "" {
region = v
}
// Next, check if the cloud entry sets a region.
if v := cloud.RegionName; v != "" {
region = v
}
// Next, see if one was specified in the ClientOpts.
// Finally, see if one was specified in the ClientOpts.
// If so, this takes precedence.
if v := opts.RegionName; v != "" {
region = v
}
// Finally, see if there's an environment variable.
// This should always override prior settings.
if v := os.Getenv(envPrefix + "REGION_NAME"); v != "" {
region = v
}
eo := gophercloud.EndpointOpts{
Region: region,
}
@ -722,3 +790,11 @@ func setDomainIfNeeded(cloud *Cloud) *Cloud {
return cloud
}
// isApplicationCredential determines if an application credential is used to auth.
func isApplicationCredential(authInfo *AuthInfo) bool {
if authInfo.ApplicationCredentialID == "" && authInfo.ApplicationCredentialName == "" && authInfo.ApplicationCredentialSecret == "" {
return false
}
return true
}

View File

@ -61,6 +61,15 @@ type AuthInfo struct {
// Password is the password of the user.
Password string `yaml:"password"`
// Application Credential ID to login with.
ApplicationCredentialID string `yaml:"application_credential_id"`
// Application Credential name to login with.
ApplicationCredentialName string `yaml:"application_credential_name"`
// Application Credential secret to login with.
ApplicationCredentialSecret string `yaml:"application_credential_secret"`
// ProjectName is the common/human-readable name of a project.
// Users can be scoped to a project.
// ProjectName on its own is not enough to ensure a unique scope. It must

View File

@ -128,16 +128,13 @@ func findAndReadYAML(yamlFile string) ([]byte, error) {
}
// unix user config directory: ~/.config/openstack.
currentUser, err := user.Current()
if err != nil {
return nil, fmt.Errorf("unable to get current user: %s", err)
}
homeDir := currentUser.HomeDir
if homeDir != "" {
filename := filepath.Join(homeDir, ".config/openstack/"+yamlFile)
if ok := fileExists(filename); ok {
return ioutil.ReadFile(filename)
if currentUser, err := user.Current(); err == nil {
homeDir := currentUser.HomeDir
if homeDir != "" {
filename := filepath.Join(homeDir, ".config/openstack/"+yamlFile)
if ok := fileExists(filename); ok {
return ioutil.ReadFile(filename)
}
}
}

12
vendor/vendor.json vendored
View File

@ -961,10 +961,16 @@
"revisionTime": "2018-05-31T02:06:30Z"
},
{
"checksumSHA1": "BYHuEArNKnTCbp/LTCwQSlaIY4Y=",
"checksumSHA1": "df+06zNEC3V7qgnTaVLtH0uktmI=",
"path": "github.com/gophercloud/utils",
"revision": "a5c25e7a53a63b89622852e35d7200c85f7cbe56",
"revisionTime": "2019-01-24T19:20:22Z"
},
{
"checksumSHA1": "+lG+bluykADYk0Zzq8sdh7KIyxY=",
"path": "github.com/gophercloud/utils/openstack/clientconfig",
"revision": "d6e28a8b3199a79da5e74e3dde1eb878ff525f1a",
"revisionTime": "2018-08-06T21:57:00Z"
"revision": "a5c25e7a53a63b89622852e35d7200c85f7cbe56",
"revisionTime": "2019-01-24T19:20:22Z"
},
{
"checksumSHA1": "xSmii71kfQASGNG2C8ttmHx9KTE=",