6
goosehttp "launchpad.net/goose/http"
11
type ErrorResponse struct {
12
Message string `json:"message"`
13
Code int `json:"code"`
14
Title string `json:"title"`
17
func (e *ErrorResponse) Error() string {
18
return fmt.Sprintf("Failed: %d %s: %s", e.Code, e.Title, e.Message)
21
type ErrorWrapper struct {
22
Error ErrorResponse `json:"error"`
25
9
type PasswordCredentials struct {
26
10
Username string `json:"username"`
27
11
Password string `json:"password"`
77
63
type AccessResponse struct {
78
ServiceCatalog []Service `json:"serviceCatalog"`
64
ServiceCatalog []ServiceResponse `json:"serviceCatalog"`
79
65
Token TokenResponse `json:"token"`
80
66
User UserResponse `json:"user"`
83
69
type UserPass struct {
70
client *goosehttp.GooseHTTPClient
86
func (l *UserPass) Auth(creds Credentials) (*AuthDetails, error) {
87
client := &http.Client{}
73
func (u *UserPass) Auth(creds *Credentials) (*AuthDetails, error) {
75
u.client = &goosehttp.GooseHTTPClient{http.Client{CheckRedirect: nil}}
88
77
auth := AuthWrapper{Auth: AuthRequest{
89
78
PasswordCredentials: PasswordCredentials{
90
79
Username: creds.User,
91
80
Password: creds.Secrets,
93
TenantName: "tenant-name"}}
94
auth_json, err := json.Marshal(auth)
95
request, err := http.NewRequest("POST", creds.URL+"/tokens", bytes.NewBuffer(auth_json))
99
request.Header.Set("Content-Type", "application/json")
100
response, err := client.Do(request)
104
content, err := ioutil.ReadAll(response.Body)
105
response.Body.Close()
109
if response.StatusCode != http.StatusOK {
110
// Check if we have a JSON representation of the failure, if so, return it
111
if response.Header.Get("Content-Type") == "application/json" {
112
var wrappedErr ErrorWrapper
113
if err := json.Unmarshal(content, &wrappedErr); err == nil {
114
return nil, &wrappedErr.Error
82
TenantName: creds.TenantName}}
84
var accessWrapper AccessWrapper
85
requestData := goosehttp.RequestData{ReqValue: auth, RespValue: &accessWrapper}
86
err := u.client.JsonRequest("POST", creds.URL, &requestData)
91
details := &AuthDetails{}
92
access := accessWrapper.Access
93
respToken := access.Token
94
if respToken.Id == "" {
95
return nil, fmt.Errorf("Did not get valid Token from auth request")
97
details.TokenId = respToken.Id
98
details.TenantId = respToken.Tenant.Id
99
details.UserId = access.User.Id
100
details.ServiceURLs = make(map[string]string, len(access.ServiceCatalog))
101
for _, service := range access.ServiceCatalog {
102
for i, e := range service.Endpoints {
103
if e.Region != creds.Region {
104
service.Endpoints = append(service.Endpoints[:i], service.Endpoints[i+1:]...)
117
// We weren't able to parse the response, so just return our own error
118
return nil, fmt.Errorf("Failed to Authenticate (code %d %s): %s",
119
response.StatusCode, response.Status, content)
121
if response.Header.Get("Content-Type") != "application/json" {
122
return nil, fmt.Errorf("Failed to Authenticate. Did not get JSON back: %s", content)
124
var access AccessWrapper
125
if err := json.Unmarshal(content, &access); err != nil {
128
details := &AuthDetails{}
129
details.Token = access.Access.Token.Id
130
if details.Token == "" {
131
return nil, fmt.Errorf("Did not get valid Token from auth request")
133
details.ServiceURLs = make(map[string]string, len(access.Access.ServiceCatalog))
134
for _, service := range access.Access.ServiceCatalog {
135
107
details.ServiceURLs[service.Type] = service.Endpoints[0].PublicURL