func()

in cluster-autoscaler/cloudprovider/magnum/gophercloud/auth_options.go [136:348]


func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
	type domainReq struct {
		ID   *string `json:"id,omitempty"`
		Name *string `json:"name,omitempty"`
	}

	type projectReq struct {
		Domain *domainReq `json:"domain,omitempty"`
		Name   *string    `json:"name,omitempty"`
		ID     *string    `json:"id,omitempty"`
	}

	type userReq struct {
		ID       *string    `json:"id,omitempty"`
		Name     *string    `json:"name,omitempty"`
		Password string     `json:"password,omitempty"`
		Domain   *domainReq `json:"domain,omitempty"`
	}

	type passwordReq struct {
		User userReq `json:"user"`
	}

	type tokenReq struct {
		ID string `json:"id"`
	}

	type applicationCredentialReq struct {
		ID     *string  `json:"id,omitempty"`
		Name   *string  `json:"name,omitempty"`
		User   *userReq `json:"user,omitempty"`
		Secret *string  `json:"secret,omitempty"`
	}

	type identityReq struct {
		Methods               []string                  `json:"methods"`
		Password              *passwordReq              `json:"password,omitempty"`
		Token                 *tokenReq                 `json:"token,omitempty"`
		ApplicationCredential *applicationCredentialReq `json:"application_credential,omitempty"`
	}

	type authReq struct {
		Identity identityReq `json:"identity"`
	}

	type request struct {
		Auth authReq `json:"auth"`
	}

	// Populate the request structure based on the provided arguments. Create and return an error
	// if insufficient or incompatible information is present.
	var req request

	if opts.Password == "" {
		if opts.TokenID != "" {
			// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
			// parameters.
			if opts.Username != "" {
				return nil, ErrUsernameWithToken{}
			}
			if opts.UserID != "" {
				return nil, ErrUserIDWithToken{}
			}
			if opts.DomainID != "" {
				return nil, ErrDomainIDWithToken{}
			}
			if opts.DomainName != "" {
				return nil, ErrDomainNameWithToken{}
			}

			// Configure the request for Token authentication.
			req.Auth.Identity.Methods = []string{"token"}
			req.Auth.Identity.Token = &tokenReq{
				ID: opts.TokenID,
			}

		} else if opts.ApplicationCredentialID != "" {
			// Configure the request for ApplicationCredentialID authentication.
			// https://github.com/openstack/keystoneauth/blob/stable/rocky/keystoneauth1/identity/v3/application_credential.py#L48-L67
			// There are three kinds of possible application_credential requests
			// 1. application_credential id + secret
			// 2. application_credential name + secret + user_id
			// 3. application_credential name + secret + username + domain_id / domain_name
			if opts.ApplicationCredentialSecret == "" {
				return nil, ErrAppCredMissingSecret{}
			}
			req.Auth.Identity.Methods = []string{"application_credential"}
			req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{
				ID:     &opts.ApplicationCredentialID,
				Secret: &opts.ApplicationCredentialSecret,
			}
		} else if opts.ApplicationCredentialName != "" {
			if opts.ApplicationCredentialSecret == "" {
				return nil, ErrAppCredMissingSecret{}
			}

			var userRequest *userReq

			if opts.UserID != "" {
				// UserID could be used without the domain information
				userRequest = &userReq{
					ID: &opts.UserID,
				}
			}

			if userRequest == nil && opts.Username == "" {
				// Make sure that Username or UserID are provided
				return nil, ErrUsernameOrUserID{}
			}

			if userRequest == nil && opts.DomainID != "" {
				userRequest = &userReq{
					Name:   &opts.Username,
					Domain: &domainReq{ID: &opts.DomainID},
				}
			}

			if userRequest == nil && opts.DomainName != "" {
				userRequest = &userReq{
					Name:   &opts.Username,
					Domain: &domainReq{Name: &opts.DomainName},
				}
			}

			// Make sure that DomainID or DomainName are provided among Username
			if userRequest == nil {
				return nil, ErrDomainIDOrDomainName{}
			}

			req.Auth.Identity.Methods = []string{"application_credential"}
			req.Auth.Identity.ApplicationCredential = &applicationCredentialReq{
				Name:   &opts.ApplicationCredentialName,
				User:   userRequest,
				Secret: &opts.ApplicationCredentialSecret,
			}
		} else {
			// If no password or token ID or ApplicationCredential are available, authentication can't continue.
			return nil, ErrMissingPassword{}
		}
	} else {
		// Password authentication.
		req.Auth.Identity.Methods = []string{"password"}

		// At least one of Username and UserID must be specified.
		if opts.Username == "" && opts.UserID == "" {
			return nil, ErrUsernameOrUserID{}
		}

		if opts.Username != "" {
			// If Username is provided, UserID may not be provided.
			if opts.UserID != "" {
				return nil, ErrUsernameOrUserID{}
			}

			// Either DomainID or DomainName must also be specified.
			if opts.DomainID == "" && opts.DomainName == "" {
				return nil, ErrDomainIDOrDomainName{}
			}

			if opts.DomainID != "" {
				if opts.DomainName != "" {
					return nil, ErrDomainIDOrDomainName{}
				}

				// Configure the request for Username and Password authentication with a DomainID.
				req.Auth.Identity.Password = &passwordReq{
					User: userReq{
						Name:     &opts.Username,
						Password: opts.Password,
						Domain:   &domainReq{ID: &opts.DomainID},
					},
				}
			}

			if opts.DomainName != "" {
				// Configure the request for Username and Password authentication with a DomainName.
				req.Auth.Identity.Password = &passwordReq{
					User: userReq{
						Name:     &opts.Username,
						Password: opts.Password,
						Domain:   &domainReq{Name: &opts.DomainName},
					},
				}
			}
		}

		if opts.UserID != "" {
			// If UserID is specified, neither DomainID nor DomainName may be.
			if opts.DomainID != "" {
				return nil, ErrDomainIDWithUserID{}
			}
			if opts.DomainName != "" {
				return nil, ErrDomainNameWithUserID{}
			}

			// Configure the request for UserID and Password authentication.
			req.Auth.Identity.Password = &passwordReq{
				User: userReq{ID: &opts.UserID, Password: opts.Password},
			}
		}
	}

	b, err := BuildRequestBody(req, "")
	if err != nil {
		return nil, err
	}

	if len(scope) != 0 {
		b["auth"].(map[string]interface{})["scope"] = scope
	}

	return b, nil
}