github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudlets/v3/policy_activation_test.go (about) 1 package v3 2 3 import ( 4 "context" 5 "encoding/json" 6 "io" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestListPolicyActivations(t *testing.T) { 17 t.Parallel() 18 19 var policyID int64 = 1234 20 21 tests := map[string]struct { 22 params ListPolicyActivationsRequest 23 responseStatus int 24 responseBody string 25 expectedPath string 26 expectedResponse *PolicyActivations 27 withError bool 28 assertError func(*testing.T, error) 29 }{ 30 "200 OK": { 31 params: ListPolicyActivationsRequest{ 32 PolicyID: policyID, 33 }, 34 responseStatus: http.StatusOK, 35 expectedPath: "/cloudlets/v3/policies/1234/activations", 36 expectedResponse: &PolicyActivations{ 37 PolicyActivations: []PolicyActivation{ 38 { 39 CreatedBy: "testUser", 40 CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"), 41 FinishDate: nil, 42 ID: 234, 43 Links: []Link{ 44 { 45 Href: "/cloudlets/v3/policies/1234/activations/234", 46 Rel: "self", 47 }, 48 }, 49 Network: StagingNetwork, 50 Operation: OperationDeactivation, 51 PolicyID: policyID, 52 PolicyVersion: 1, 53 PolicyVersionDeleted: false, 54 Status: ActivationStatusInProgress, 55 }, 56 { 57 CreatedBy: "testUser", 58 CreatedDate: *newTimeFromString(t, "2023-10-23T11:21:19.896Z"), 59 FinishDate: newTimeFromString(t, "2023-10-23T11:22:57.589Z"), 60 ID: 123, 61 Links: []Link{ 62 { 63 Href: "/cloudlets/v3/policies/1234/activations/123", 64 Rel: "self", 65 }, 66 }, 67 Network: StagingNetwork, 68 Operation: OperationActivation, 69 PolicyID: policyID, 70 PolicyVersion: 1, 71 PolicyVersionDeleted: false, 72 Status: ActivationStatusSuccess, 73 }, 74 }, 75 Links: []Link{ 76 { 77 Href: "/cloudlets/v3/policies/1234/activations?page=0&size=1000", 78 Rel: "self", 79 }, 80 }, 81 Page: Page{ 82 Number: 0, 83 Size: 1000, 84 TotalElements: 2, 85 TotalPages: 1, 86 }, 87 }, 88 responseBody: ` 89 { 90 "content": [ 91 { 92 "createdBy": "testUser", 93 "createdDate": "2023-10-25T10:33:47.982Z", 94 "finishDate": null, 95 "id": 234, 96 "links": [ 97 { 98 "href": "/cloudlets/v3/policies/1234/activations/234", 99 "rel": "self" 100 } 101 ], 102 "network": "STAGING", 103 "operation": "DEACTIVATION", 104 "policyId": 1234, 105 "policyVersion": 1, 106 "policyVersionDeleted": false, 107 "status": "IN_PROGRESS" 108 }, 109 { 110 "createdBy": "testUser", 111 "createdDate": "2023-10-23T11:21:19.896Z", 112 "finishDate": "2023-10-23T11:22:57.589Z", 113 "id": 123, 114 "links": [ 115 { 116 "href": "/cloudlets/v3/policies/1234/activations/123", 117 "rel": "self" 118 } 119 ], 120 "network": "STAGING", 121 "operation": "ACTIVATION", 122 "policyId": 1234, 123 "policyVersion": 1, 124 "policyVersionDeleted": false, 125 "status": "SUCCESS" 126 } 127 ], 128 "links": [ 129 { 130 "href": "/cloudlets/v3/policies/1234/activations?page=0&size=1000", 131 "rel": "self" 132 } 133 ], 134 "page": { 135 "number": 0, 136 "size": 1000, 137 "totalElements": 2, 138 "totalPages": 1 139 } 140 }`, 141 }, 142 "200 OK with query": { 143 params: ListPolicyActivationsRequest{ 144 PolicyID: policyID, 145 Page: 1, 146 Size: 10, 147 }, 148 responseStatus: http.StatusOK, 149 expectedPath: "/cloudlets/v3/policies/1234/activations?page=1&size=10", 150 expectedResponse: &PolicyActivations{ 151 PolicyActivations: []PolicyActivation{}, 152 Links: []Link{ 153 { 154 Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10", 155 Rel: "first", 156 }, 157 { 158 Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10", 159 Rel: "prev", 160 }, 161 { 162 Href: "/cloudlets/v3/policies/1234/activations?page=1&size=10", 163 Rel: "self", 164 }, 165 { 166 Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10", 167 Rel: "last", 168 }, 169 }, 170 Page: Page{ 171 Number: 1, 172 Size: 10, 173 TotalElements: 2, 174 TotalPages: 1, 175 }, 176 }, 177 responseBody: ` 178 { 179 "content": [], 180 "links": [ 181 { 182 "href": "/cloudlets/v3/policies/1234/activations?page=0&size=10", 183 "rel": "first" 184 }, 185 { 186 "href": "/cloudlets/v3/policies/1234/activations?page=0&size=10", 187 "rel": "prev" 188 }, 189 { 190 "href": "/cloudlets/v3/policies/1234/activations?page=1&size=10", 191 "rel": "self" 192 }, 193 { 194 "href": "/cloudlets/v3/policies/1234/activations?page=0&size=10", 195 "rel": "last" 196 } 197 ], 198 "page": { 199 "number": 1, 200 "size": 10, 201 "totalElements": 2, 202 "totalPages": 1 203 } 204 }`, 205 }, 206 "500 Internal Server Error": { 207 params: ListPolicyActivationsRequest{ 208 PolicyID: policyID, 209 }, 210 responseStatus: http.StatusInternalServerError, 211 expectedPath: "/cloudlets/v3/policies/1234/activations", 212 responseBody: ` 213 { 214 "type": "internal_error", 215 "title": "Internal Server Error", 216 "status": 500, 217 "requestId": "1", 218 "requestTime": "12:00", 219 "clientIp": "1.1.1.1", 220 "serverIp": "2.2.2.2", 221 "method": "GET" 222 }`, 223 withError: true, 224 assertError: func(t *testing.T, err error) { 225 want := &Error{ 226 Type: "internal_error", 227 Title: "Internal Server Error", 228 Status: http.StatusInternalServerError, 229 RequestID: "1", 230 RequestTime: "12:00", 231 ClientIP: "1.1.1.1", 232 ServerIP: "2.2.2.2", 233 Method: "GET", 234 } 235 assert.ErrorIs(t, err, want) 236 }, 237 }, 238 "request validation failed": { 239 params: ListPolicyActivationsRequest{ 240 Page: -1, 241 Size: 5, 242 }, 243 withError: true, 244 assertError: func(t *testing.T, err error) { 245 assert.ErrorContains(t, err, "Page: must be no less than 0") 246 assert.ErrorContains(t, err, "PolicyID: cannot be blank") 247 assert.ErrorContains(t, err, "Size: must be no less than 10") 248 }, 249 }, 250 } 251 252 for name, tc := range tests { 253 name, tc := name, tc 254 t.Run(name, func(t *testing.T) { 255 t.Parallel() 256 257 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 258 assert.Equal(t, tc.expectedPath, r.URL.String()) 259 assert.Equal(t, http.MethodGet, r.Method) 260 w.WriteHeader(tc.responseStatus) 261 _, err := w.Write([]byte(tc.responseBody)) 262 assert.NoError(t, err) 263 })) 264 client := mockAPIClient(t, mockServer) 265 result, err := client.ListPolicyActivations(context.Background(), tc.params) 266 267 if tc.withError { 268 tc.assertError(t, err) 269 return 270 } 271 require.NoError(t, err) 272 assert.Equal(t, tc.expectedResponse, result) 273 }) 274 } 275 } 276 277 func TestActivatePolicy(t *testing.T) { 278 t.Parallel() 279 280 var policyID int64 = 1234 281 282 tests := map[string]struct { 283 params ActivatePolicyRequest 284 responseStatus int 285 responseBody string 286 expectedPath string 287 expectedReqBody string 288 expectedResponse *PolicyActivation 289 withError bool 290 assertError func(*testing.T, error) 291 }{ 292 "202 Accepted": { 293 params: ActivatePolicyRequest{ 294 PolicyID: policyID, 295 Network: StagingNetwork, 296 PolicyVersion: 1, 297 }, 298 responseStatus: http.StatusAccepted, 299 expectedPath: "/cloudlets/v3/policies/1234/activations", 300 expectedResponse: &PolicyActivation{ 301 CreatedBy: "testUser", 302 CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"), 303 FinishDate: nil, 304 ID: 123, 305 Links: []Link{ 306 { 307 Href: "/cloudlets/v3/policies/1234/activations/123", 308 Rel: "self", 309 }, 310 }, 311 Network: StagingNetwork, 312 Operation: OperationActivation, 313 PolicyID: policyID, 314 PolicyVersion: 1, 315 PolicyVersionDeleted: false, 316 Status: ActivationStatusInProgress, 317 }, 318 expectedReqBody: ` 319 { 320 "network": "STAGING", 321 "policyVersion": 1, 322 "operation": "ACTIVATION" 323 }`, 324 responseBody: ` 325 { 326 "createdBy": "testUser", 327 "createdDate": "2023-10-25T10:33:47.982Z", 328 "finishDate": null, 329 "id": 123, 330 "links": [ 331 { 332 "href": "/cloudlets/v3/policies/1234/activations/123", 333 "rel": "self" 334 } 335 ], 336 "network": "STAGING", 337 "operation": "ACTIVATION", 338 "policyId": 1234, 339 "policyVersion": 1, 340 "policyVersionDeleted": false, 341 "status": "IN_PROGRESS" 342 }`, 343 }, 344 "500 Internal Server Error": { 345 params: ActivatePolicyRequest{ 346 PolicyID: policyID, 347 Network: StagingNetwork, 348 PolicyVersion: 1, 349 }, 350 responseStatus: http.StatusInternalServerError, 351 expectedPath: "/cloudlets/v3/policies/1234/activations", 352 expectedReqBody: ` 353 { 354 "network": "STAGING", 355 "policyVersion": 1, 356 "operation": "ACTIVATION" 357 }`, 358 responseBody: ` 359 { 360 "type": "internal_error", 361 "title": "Internal Server Error", 362 "status": 500, 363 "requestId": "1", 364 "requestTime": "12:00", 365 "clientIp": "1.1.1.1", 366 "serverIp": "2.2.2.2", 367 "method": "GET" 368 }`, 369 withError: true, 370 assertError: func(t *testing.T, err error) { 371 want := &Error{ 372 Type: "internal_error", 373 Title: "Internal Server Error", 374 Status: http.StatusInternalServerError, 375 RequestID: "1", 376 RequestTime: "12:00", 377 ClientIP: "1.1.1.1", 378 ServerIP: "2.2.2.2", 379 Method: "GET", 380 } 381 assert.ErrorIs(t, err, want) 382 }, 383 }, 384 "request validation failed": { 385 params: ActivatePolicyRequest{}, 386 withError: true, 387 assertError: func(t *testing.T, err error) { 388 assert.ErrorContains(t, err, "PolicyID: cannot be blank") 389 assert.ErrorContains(t, err, "PolicyVersion: cannot be blank") 390 assert.ErrorContains(t, err, "Network: cannot be blank") 391 }, 392 }, 393 } 394 395 for name, tc := range tests { 396 name, tc := name, tc 397 t.Run(name, func(t *testing.T) { 398 t.Parallel() 399 400 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 401 assert.Equal(t, tc.expectedPath, r.URL.String()) 402 assert.Equal(t, http.MethodPost, r.Method) 403 w.WriteHeader(tc.responseStatus) 404 _, err := w.Write([]byte(tc.responseBody)) 405 assert.NoError(t, err) 406 if tc.expectedReqBody != "" { 407 body, err := io.ReadAll(r.Body) 408 assert.NoError(t, err) 409 assert.JSONEq(t, tc.expectedReqBody, string(body)) 410 } 411 })) 412 client := mockAPIClient(t, mockServer) 413 result, err := client.ActivatePolicy(context.Background(), tc.params) 414 415 if tc.withError { 416 tc.assertError(t, err) 417 return 418 } 419 require.NoError(t, err) 420 assert.Equal(t, tc.expectedResponse, result) 421 }) 422 } 423 } 424 425 func TestDeactivatePolicy(t *testing.T) { 426 t.Parallel() 427 428 var policyID int64 = 1234 429 430 tests := map[string]struct { 431 params DeactivatePolicyRequest 432 responseStatus int 433 responseBody string 434 expectedPath string 435 expectedReqBody string 436 expectedResponse *PolicyActivation 437 withError bool 438 assertError func(*testing.T, error) 439 }{ 440 "202 Accepted": { 441 params: DeactivatePolicyRequest{ 442 PolicyID: policyID, 443 Network: StagingNetwork, 444 PolicyVersion: 1, 445 }, 446 responseStatus: http.StatusAccepted, 447 expectedPath: "/cloudlets/v3/policies/1234/activations", 448 expectedResponse: &PolicyActivation{ 449 CreatedBy: "testUser", 450 CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"), 451 FinishDate: nil, 452 ID: 123, 453 Links: []Link{ 454 { 455 Href: "/cloudlets/v3/policies/1234/activations/123", 456 Rel: "self", 457 }, 458 }, 459 Network: StagingNetwork, 460 Operation: OperationDeactivation, 461 PolicyID: policyID, 462 PolicyVersion: 1, 463 PolicyVersionDeleted: false, 464 Status: ActivationStatusInProgress, 465 }, 466 expectedReqBody: ` 467 { 468 "network": "STAGING", 469 "policyVersion": 1, 470 "operation": "DEACTIVATION" 471 }`, 472 responseBody: ` 473 { 474 "createdBy": "testUser", 475 "createdDate": "2023-10-25T10:33:47.982Z", 476 "finishDate": null, 477 "id": 123, 478 "links": [ 479 { 480 "href": "/cloudlets/v3/policies/1234/activations/123", 481 "rel": "self" 482 } 483 ], 484 "network": "STAGING", 485 "operation": "DEACTIVATION", 486 "policyId": 1234, 487 "policyVersion": 1, 488 "policyVersionDeleted": false, 489 "status": "IN_PROGRESS" 490 }`, 491 }, 492 "500 Internal Server Error": { 493 params: DeactivatePolicyRequest{ 494 PolicyID: policyID, 495 Network: ProductionNetwork, 496 PolicyVersion: 1, 497 }, 498 responseStatus: http.StatusInternalServerError, 499 expectedPath: "/cloudlets/v3/policies/1234/activations", 500 expectedReqBody: ` 501 { 502 "network": "PRODUCTION", 503 "policyVersion": 1, 504 "operation": "DEACTIVATION" 505 }`, 506 responseBody: ` 507 { 508 "type": "internal_error", 509 "title": "Internal Server Error", 510 "status": 500, 511 "requestId": "1", 512 "requestTime": "12:00", 513 "clientIp": "1.1.1.1", 514 "serverIp": "2.2.2.2", 515 "method": "GET" 516 }`, 517 withError: true, 518 assertError: func(t *testing.T, err error) { 519 want := &Error{ 520 Type: "internal_error", 521 Title: "Internal Server Error", 522 Status: http.StatusInternalServerError, 523 RequestID: "1", 524 RequestTime: "12:00", 525 ClientIP: "1.1.1.1", 526 ServerIP: "2.2.2.2", 527 Method: "GET", 528 } 529 assert.ErrorIs(t, err, want) 530 }, 531 }, 532 "request validation failed": { 533 params: DeactivatePolicyRequest{ 534 Network: "OTHER", 535 }, 536 withError: true, 537 assertError: func(t *testing.T, err error) { 538 assert.ErrorContains(t, err, "PolicyID: cannot be blank") 539 assert.ErrorContains(t, err, "PolicyVersion: cannot be blank") 540 assert.ErrorContains(t, err, "Network: value 'OTHER' is invalid. Must be one of: 'STAGING' or 'PRODUCTION'") 541 }, 542 }, 543 } 544 545 for name, tc := range tests { 546 name, tc := name, tc 547 t.Run(name, func(t *testing.T) { 548 t.Parallel() 549 550 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 551 assert.Equal(t, tc.expectedPath, r.URL.String()) 552 assert.Equal(t, http.MethodPost, r.Method) 553 w.WriteHeader(tc.responseStatus) 554 _, err := w.Write([]byte(tc.responseBody)) 555 assert.NoError(t, err) 556 if tc.expectedReqBody != "" { 557 body, err := io.ReadAll(r.Body) 558 assert.NoError(t, err) 559 assert.JSONEq(t, tc.expectedReqBody, string(body)) 560 } 561 })) 562 client := mockAPIClient(t, mockServer) 563 result, err := client.DeactivatePolicy(context.Background(), tc.params) 564 565 if tc.withError { 566 tc.assertError(t, err) 567 return 568 } 569 require.NoError(t, err) 570 assert.Equal(t, tc.expectedResponse, result) 571 }) 572 } 573 } 574 575 func TestGetPolicyActivation(t *testing.T) { 576 t.Parallel() 577 578 var policyID int64 = 1234 579 var activationID int64 = 123 580 581 tests := map[string]struct { 582 params GetPolicyActivationRequest 583 responseStatus int 584 responseBody string 585 expectedPath string 586 expectedResponse *PolicyActivation 587 withError bool 588 assertError func(*testing.T, error) 589 }{ 590 "200 OK": { 591 params: GetPolicyActivationRequest{ 592 PolicyID: policyID, 593 ActivationID: activationID, 594 }, 595 responseStatus: http.StatusOK, 596 expectedPath: "/cloudlets/v3/policies/1234/activations/123", 597 expectedResponse: &PolicyActivation{ 598 CreatedBy: "testUser", 599 CreatedDate: *newTimeFromString(t, "2023-10-23T11:21:19.896Z"), 600 FinishDate: newTimeFromString(t, "2023-10-23T11:22:57.589Z"), 601 ID: activationID, 602 Links: []Link{ 603 { 604 Href: "/cloudlets/v3/policies/1234/activations/123", 605 Rel: "self", 606 }, 607 }, 608 Network: StagingNetwork, 609 Operation: OperationActivation, 610 PolicyID: policyID, 611 PolicyVersion: 1, 612 PolicyVersionDeleted: false, 613 Status: ActivationStatusSuccess, 614 }, 615 responseBody: ` 616 { 617 "createdBy": "testUser", 618 "createdDate": "2023-10-23T11:21:19.896Z", 619 "finishDate": "2023-10-23T11:22:57.589Z", 620 "id": 123, 621 "links": [ 622 { 623 "href": "/cloudlets/v3/policies/1234/activations/123", 624 "rel": "self" 625 } 626 ], 627 "network": "STAGING", 628 "operation": "ACTIVATION", 629 "policyId": 1234, 630 "policyVersion": 1, 631 "policyVersionDeleted": false, 632 "status": "SUCCESS" 633 }`, 634 }, 635 "404 Not Found": { 636 params: GetPolicyActivationRequest{ 637 PolicyID: policyID, 638 ActivationID: 1, 639 }, 640 responseStatus: http.StatusNotFound, 641 expectedPath: "/cloudlets/v3/policies/1234/activations/1", 642 responseBody: ` 643 { 644 "instance": "testInstance", 645 "status": 404, 646 "title": "Not found", 647 "type": "/cloudlets/v3/error-types/not-found", 648 "errors": [ 649 { 650 "detail": "Activation with id '1' not found.", 651 "title": "Not found" 652 } 653 ] 654 }`, 655 withError: true, 656 assertError: func(t *testing.T, err error) { 657 want := &Error{ 658 Type: "/cloudlets/v3/error-types/not-found", 659 Title: "Not found", 660 Status: http.StatusNotFound, 661 Instance: "testInstance", 662 Errors: json.RawMessage(`[{"detail": "Activation with id '1' not found.", "title": "Not found"}]`), 663 } 664 assert.ErrorIs(t, err, want) 665 }, 666 }, 667 "500 Internal Server Error": { 668 params: GetPolicyActivationRequest{ 669 PolicyID: policyID, 670 ActivationID: activationID, 671 }, 672 responseStatus: http.StatusInternalServerError, 673 expectedPath: "/cloudlets/v3/policies/1234/activations/123", 674 responseBody: ` 675 { 676 "type": "internal_error", 677 "title": "Internal Server Error", 678 "status": 500, 679 "requestId": "1", 680 "requestTime": "12:00", 681 "clientIp": "1.1.1.1", 682 "serverIp": "2.2.2.2", 683 "method": "GET" 684 }`, 685 withError: true, 686 assertError: func(t *testing.T, err error) { 687 want := &Error{ 688 Type: "internal_error", 689 Title: "Internal Server Error", 690 Status: http.StatusInternalServerError, 691 RequestID: "1", 692 RequestTime: "12:00", 693 ClientIP: "1.1.1.1", 694 ServerIP: "2.2.2.2", 695 Method: "GET", 696 } 697 assert.ErrorIs(t, err, want) 698 }, 699 }, 700 "request validation failed": { 701 params: GetPolicyActivationRequest{}, 702 withError: true, 703 assertError: func(t *testing.T, err error) { 704 assert.ErrorContains(t, err, "PolicyID: cannot be blank") 705 assert.ErrorContains(t, err, "ActivationID: cannot be blank") 706 }, 707 }, 708 } 709 710 for name, tc := range tests { 711 name, tc := name, tc 712 t.Run(name, func(t *testing.T) { 713 t.Parallel() 714 715 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 716 assert.Equal(t, tc.expectedPath, r.URL.String()) 717 assert.Equal(t, http.MethodGet, r.Method) 718 w.WriteHeader(tc.responseStatus) 719 _, err := w.Write([]byte(tc.responseBody)) 720 assert.NoError(t, err) 721 })) 722 client := mockAPIClient(t, mockServer) 723 result, err := client.GetPolicyActivation(context.Background(), tc.params) 724 725 if tc.withError { 726 tc.assertError(t, err) 727 return 728 } 729 require.NoError(t, err) 730 assert.Equal(t, tc.expectedResponse, result) 731 }) 732 } 733 } 734 735 func newTimeFromString(t *testing.T, s string) *time.Time { 736 parsedTime, err := time.Parse(time.RFC3339Nano, s) 737 require.NoError(t, err) 738 return &parsedTime 739 }