github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/openstack/identity/v3/tokens/testing/requests_test.go (about) 1 package testing 2 3 import ( 4 "fmt" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/opentelekomcloud/gophertelekomcloud" 10 "github.com/opentelekomcloud/gophertelekomcloud/openstack/identity/v3/tokens" 11 "github.com/opentelekomcloud/gophertelekomcloud/testhelper" 12 ) 13 14 // authTokenPost verifies that providing certain AuthOptions and Scope results in an expected JSON structure. 15 func authTokenPost(t *testing.T, options tokens.AuthOptions, scope *tokens.Scope, requestJSON string) { 16 testhelper.SetupHTTP() 17 defer testhelper.TeardownHTTP() 18 19 client := golangsdk.ServiceClient{ 20 ProviderClient: &golangsdk.ProviderClient{}, 21 Endpoint: testhelper.Endpoint(), 22 } 23 24 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 25 testhelper.TestMethod(t, r, "POST") 26 testhelper.TestHeader(t, r, "Content-Type", "application/json") 27 testhelper.TestHeader(t, r, "Accept", "application/json") 28 testhelper.TestJSONRequest(t, r, requestJSON) 29 30 w.WriteHeader(http.StatusCreated) 31 _, _ = fmt.Fprint(w, `{ 32 "token": { 33 "expires_at": "2014-10-02T13:45:00.000000Z" 34 } 35 }`) 36 }) 37 38 if scope != nil { 39 options.Scope = *scope 40 } 41 42 expected := &tokens.Token{ 43 ExpiresAt: time.Date(2014, 10, 2, 13, 45, 0, 0, time.UTC), 44 } 45 actual, err := tokens.Create(&client, &options).Extract() 46 testhelper.AssertNoErr(t, err) 47 testhelper.CheckDeepEquals(t, expected, actual) 48 } 49 50 func authTokenPostErr(t *testing.T, options tokens.AuthOptions, scope *tokens.Scope, includeToken bool, expectedErr error) { 51 testhelper.SetupHTTP() 52 defer testhelper.TeardownHTTP() 53 54 client := golangsdk.ServiceClient{ 55 ProviderClient: &golangsdk.ProviderClient{}, 56 Endpoint: testhelper.Endpoint(), 57 } 58 if includeToken { 59 client.TokenID = "abcdef123456" 60 } 61 62 if scope != nil { 63 options.Scope = *scope 64 } 65 66 _, err := tokens.Create(&client, &options).Extract() 67 if err == nil { 68 t.Errorf("Create did NOT return an error") 69 } 70 if err != expectedErr { 71 t.Errorf("Create returned an unexpected error: wanted %v, got %v", expectedErr, err) 72 } 73 } 74 75 func TestCreateUserIDAndPassword(t *testing.T) { 76 authTokenPost(t, tokens.AuthOptions{UserID: "me", Password: "squirrel!"}, nil, ` 77 { 78 "auth": { 79 "identity": { 80 "methods": ["password"], 81 "password": { 82 "user": { "id": "me", "password": "squirrel!" } 83 } 84 } 85 } 86 } 87 `) 88 } 89 90 func TestCreateUsernameDomainIDPassword(t *testing.T) { 91 authTokenPost(t, tokens.AuthOptions{Username: "fakey", Password: "notpassword", DomainID: "abc123"}, nil, ` 92 { 93 "auth": { 94 "identity": { 95 "methods": ["password"], 96 "password": { 97 "user": { 98 "domain": { 99 "id": "abc123" 100 }, 101 "name": "fakey", 102 "password": "notpassword" 103 } 104 } 105 } 106 } 107 } 108 `) 109 } 110 111 func TestCreateUsernameDomainNamePassword(t *testing.T) { 112 authTokenPost(t, tokens.AuthOptions{Username: "frank", Password: "swordfish", DomainName: "spork.net"}, nil, ` 113 { 114 "auth": { 115 "identity": { 116 "methods": ["password"], 117 "password": { 118 "user": { 119 "domain": { 120 "name": "spork.net" 121 }, 122 "name": "frank", 123 "password": "swordfish" 124 } 125 } 126 } 127 } 128 } 129 `) 130 } 131 132 func TestCreateTokenID(t *testing.T) { 133 authTokenPost(t, tokens.AuthOptions{TokenID: "12345abcdef"}, nil, ` 134 { 135 "auth": { 136 "identity": { 137 "methods": ["token"], 138 "token": { 139 "id": "12345abcdef" 140 } 141 } 142 } 143 } 144 `) 145 } 146 147 func TestCreateProjectIDScope(t *testing.T) { 148 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 149 scope := &tokens.Scope{ProjectID: "123456"} 150 authTokenPost(t, options, scope, ` 151 { 152 "auth": { 153 "identity": { 154 "methods": ["password"], 155 "password": { 156 "user": { 157 "id": "fenris", 158 "password": "g0t0h311" 159 } 160 } 161 }, 162 "scope": { 163 "project": { 164 "id": "123456" 165 } 166 } 167 } 168 } 169 `) 170 } 171 172 func TestCreateDomainIDScope(t *testing.T) { 173 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 174 scope := &tokens.Scope{DomainID: "1000"} 175 authTokenPost(t, options, scope, ` 176 { 177 "auth": { 178 "identity": { 179 "methods": ["password"], 180 "password": { 181 "user": { 182 "id": "fenris", 183 "password": "g0t0h311" 184 } 185 } 186 }, 187 "scope": { 188 "domain": { 189 "id": "1000" 190 } 191 } 192 } 193 } 194 `) 195 } 196 197 func TestCreateDomainNameScope(t *testing.T) { 198 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 199 scope := &tokens.Scope{DomainName: "evil-plans"} 200 authTokenPost(t, options, scope, ` 201 { 202 "auth": { 203 "identity": { 204 "methods": ["password"], 205 "password": { 206 "user": { 207 "id": "fenris", 208 "password": "g0t0h311" 209 } 210 } 211 }, 212 "scope": { 213 "domain": { 214 "name": "evil-plans" 215 } 216 } 217 } 218 } 219 `) 220 } 221 222 func TestCreateProjectNameAndDomainIDScope(t *testing.T) { 223 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 224 scope := &tokens.Scope{ProjectName: "world-domination", DomainID: "1000"} 225 authTokenPost(t, options, scope, ` 226 { 227 "auth": { 228 "identity": { 229 "methods": ["password"], 230 "password": { 231 "user": { 232 "id": "fenris", 233 "password": "g0t0h311" 234 } 235 } 236 }, 237 "scope": { 238 "project": { 239 "domain": { 240 "id": "1000" 241 }, 242 "name": "world-domination" 243 } 244 } 245 } 246 } 247 `) 248 } 249 250 func TestCreateProjectNameAndDomainNameScope(t *testing.T) { 251 options := tokens.AuthOptions{UserID: "fenris", Password: "g0t0h311"} 252 scope := &tokens.Scope{ProjectName: "world-domination", DomainName: "evil-plans"} 253 authTokenPost(t, options, scope, ` 254 { 255 "auth": { 256 "identity": { 257 "methods": ["password"], 258 "password": { 259 "user": { 260 "id": "fenris", 261 "password": "g0t0h311" 262 } 263 } 264 }, 265 "scope": { 266 "project": { 267 "domain": { 268 "name": "evil-plans" 269 }, 270 "name": "world-domination" 271 } 272 } 273 } 274 } 275 `) 276 } 277 278 func TestCreateExtractsTokenFromResponse(t *testing.T) { 279 testhelper.SetupHTTP() 280 defer testhelper.TeardownHTTP() 281 282 client := golangsdk.ServiceClient{ 283 ProviderClient: &golangsdk.ProviderClient{}, 284 Endpoint: testhelper.Endpoint(), 285 } 286 287 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 288 w.Header().Add("X-Subject-Token", "aaa111") 289 290 w.WriteHeader(http.StatusCreated) 291 _, _ = fmt.Fprint(w, `{ 292 "token": { 293 "expires_at": "2014-10-02T13:45:00.000000Z" 294 } 295 }`) 296 }) 297 298 options := tokens.AuthOptions{UserID: "me", Password: "shhh"} 299 token, err := tokens.Create(&client, &options).Extract() 300 if err != nil { 301 t.Fatalf("Create returned an error: %v", err) 302 } 303 304 if token.ID != "aaa111" { 305 t.Errorf("Expected token to be aaa111, but was %s", token.ID) 306 } 307 } 308 309 func TestCreateFailureEmptyAuth(t *testing.T) { 310 authTokenPostErr(t, tokens.AuthOptions{}, nil, false, golangsdk.ErrMissingPassword{}) 311 } 312 313 func TestCreateFailureTokenIDUsername(t *testing.T) { 314 authTokenPostErr(t, tokens.AuthOptions{Username: "something", TokenID: "12345"}, nil, true, golangsdk.ErrUsernameWithToken{}) 315 } 316 317 func TestCreateFailureTokenIDUserID(t *testing.T) { 318 authTokenPostErr(t, tokens.AuthOptions{UserID: "something", TokenID: "12345"}, nil, true, golangsdk.ErrUserIDWithToken{}) 319 } 320 321 func TestCreateFailureMissingUser(t *testing.T) { 322 options := tokens.AuthOptions{Password: "supersecure"} 323 authTokenPostErr(t, options, nil, false, golangsdk.ErrUsernameOrUserID{}) 324 } 325 326 func TestCreateFailureBothUser(t *testing.T) { 327 options := tokens.AuthOptions{ 328 Password: "supersecure", 329 Username: "oops", 330 UserID: "redundancy", 331 } 332 authTokenPostErr(t, options, nil, false, golangsdk.ErrUsernameOrUserID{}) 333 } 334 335 func TestCreateFailureMissingDomain(t *testing.T) { 336 options := tokens.AuthOptions{ 337 Password: "supersecure", 338 Username: "notuniqueenough", 339 } 340 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainIDOrDomainName{}) 341 } 342 343 func TestCreateFailureBothDomain(t *testing.T) { 344 options := tokens.AuthOptions{ 345 Password: "supersecure", 346 Username: "someone", 347 DomainID: "hurf", 348 DomainName: "durf", 349 } 350 authTokenPostErr(t, options, nil, false, golangsdk.ErrDomainIDOrDomainName{}) 351 } 352 353 func TestCreateFailureScopeProjectNameAlone(t *testing.T) { 354 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 355 scope := &tokens.Scope{ProjectName: "notenough"} 356 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeDomainIDOrDomainName{}) 357 } 358 359 func TestCreateFailureScopeProjectNameAndID(t *testing.T) { 360 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 361 scope := &tokens.Scope{ProjectName: "whoops", ProjectID: "toomuch", DomainID: "1234"} 362 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDOrProjectName{}) 363 } 364 365 func TestCreateFailureScopeProjectIDAndDomainID(t *testing.T) { 366 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 367 scope := &tokens.Scope{ProjectID: "toomuch", DomainID: "notneeded"} 368 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDAlone{}) 369 } 370 371 func TestCreateFailureScopeProjectIDAndDomainNAme(t *testing.T) { 372 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 373 scope := &tokens.Scope{ProjectID: "toomuch", DomainName: "notneeded"} 374 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeProjectIDAlone{}) 375 } 376 377 func TestCreateFailureScopeDomainIDAndDomainName(t *testing.T) { 378 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 379 scope := &tokens.Scope{DomainID: "toomuch", DomainName: "notneeded"} 380 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeDomainIDOrDomainName{}) 381 } 382 383 /* 384 func TestCreateFailureEmptyScope(t *testing.T) { 385 options := tokens.AuthOptions{UserID: "myself", Password: "swordfish"} 386 scope := &tokens.Scope{} 387 authTokenPostErr(t, options, scope, false, golangsdk.ErrScopeEmpty{}) 388 } 389 */ 390 391 func TestGetRequest(t *testing.T) { 392 testhelper.SetupHTTP() 393 defer testhelper.TeardownHTTP() 394 395 client := golangsdk.ServiceClient{ 396 ProviderClient: &golangsdk.ProviderClient{ 397 TokenID: "12345abcdef", 398 }, 399 Endpoint: testhelper.Endpoint(), 400 } 401 402 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 403 testhelper.TestMethod(t, r, "GET") 404 testhelper.TestHeader(t, r, "Content-Type", "") 405 testhelper.TestHeader(t, r, "Accept", "application/json") 406 testhelper.TestHeader(t, r, "X-Auth-Token", "12345abcdef") 407 testhelper.TestHeader(t, r, "X-Subject-Token", "abcdef12345") 408 409 w.WriteHeader(http.StatusOK) 410 _, _ = fmt.Fprint(w, ` 411 { "token": { "expires_at": "2014-08-29T13:10:01.000000Z" } } 412 `) 413 }) 414 415 token, err := tokens.Get(&client, "abcdef12345").Extract() 416 if err != nil { 417 t.Errorf("Info returned an error: %v", err) 418 } 419 420 expected, _ := time.Parse(time.UnixDate, "Fri Aug 29 13:10:01 UTC 2014") 421 if token.ExpiresAt != expected { 422 t.Errorf("Expected expiration time %s, but was %s", expected.Format(time.UnixDate), token.ExpiresAt.Format(time.UnixDate)) 423 } 424 } 425 426 func prepareAuthTokenHandler(t *testing.T, expectedMethod string, status int) golangsdk.ServiceClient { 427 client := golangsdk.ServiceClient{ 428 ProviderClient: &golangsdk.ProviderClient{ 429 TokenID: "12345abcdef", 430 }, 431 Endpoint: testhelper.Endpoint(), 432 } 433 434 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 435 testhelper.TestMethod(t, r, expectedMethod) 436 testhelper.TestHeader(t, r, "Content-Type", "") 437 testhelper.TestHeader(t, r, "Accept", "application/json") 438 testhelper.TestHeader(t, r, "X-Auth-Token", "12345abcdef") 439 testhelper.TestHeader(t, r, "X-Subject-Token", "abcdef12345") 440 441 w.WriteHeader(status) 442 }) 443 444 return client 445 } 446 447 func TestValidateRequestSuccessful(t *testing.T) { 448 testhelper.SetupHTTP() 449 defer testhelper.TeardownHTTP() 450 client := prepareAuthTokenHandler(t, "HEAD", http.StatusNoContent) 451 452 ok, err := tokens.Validate(&client, "abcdef12345") 453 if err != nil { 454 t.Errorf("Unexpected error from Validate: %v", err) 455 } 456 457 if !ok { 458 t.Errorf("Validate returned false for a valid token") 459 } 460 } 461 462 func TestValidateRequestFailure(t *testing.T) { 463 testhelper.SetupHTTP() 464 defer testhelper.TeardownHTTP() 465 client := prepareAuthTokenHandler(t, "HEAD", http.StatusNotFound) 466 467 ok, err := tokens.Validate(&client, "abcdef12345") 468 if err != nil { 469 t.Errorf("Unexpected error from Validate: %v", err) 470 } 471 472 if ok { 473 t.Errorf("Validate returned true for an invalid token") 474 } 475 } 476 477 func TestValidateRequestError(t *testing.T) { 478 testhelper.SetupHTTP() 479 defer testhelper.TeardownHTTP() 480 client := prepareAuthTokenHandler(t, "HEAD", http.StatusMethodNotAllowed) 481 482 _, err := tokens.Validate(&client, "abcdef12345") 483 if err == nil { 484 t.Errorf("Missing expected error from Validate") 485 } 486 } 487 488 func TestRevokeRequestSuccessful(t *testing.T) { 489 testhelper.SetupHTTP() 490 defer testhelper.TeardownHTTP() 491 client := prepareAuthTokenHandler(t, "DELETE", http.StatusNoContent) 492 493 res := tokens.Revoke(&client, "abcdef12345") 494 testhelper.AssertNoErr(t, res.Err) 495 } 496 497 func TestRevokeRequestError(t *testing.T) { 498 testhelper.SetupHTTP() 499 defer testhelper.TeardownHTTP() 500 client := prepareAuthTokenHandler(t, "DELETE", http.StatusNotFound) 501 502 res := tokens.Revoke(&client, "abcdef12345") 503 if res.Err == nil { 504 t.Errorf("Missing expected error from Revoke") 505 } 506 } 507 508 func TestNoTokenInResponse(t *testing.T) { 509 testhelper.SetupHTTP() 510 defer testhelper.TeardownHTTP() 511 512 client := golangsdk.ServiceClient{ 513 ProviderClient: &golangsdk.ProviderClient{}, 514 Endpoint: testhelper.Endpoint(), 515 } 516 517 testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) { 518 w.WriteHeader(http.StatusCreated) 519 _, _ = fmt.Fprint(w, `{}`) 520 }) 521 522 options := tokens.AuthOptions{UserID: "me", Password: "squirrel!"} 523 _, err := tokens.Create(&client, &options).Extract() 524 testhelper.AssertNoErr(t, err) 525 }