github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/gtm/property_test.go (about) 1 package gtm 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "errors" 8 "net/http" 9 "net/http/httptest" 10 "testing" 11 12 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/session" 13 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestGTM_ListProperties(t *testing.T) { 19 var result PropertyList 20 21 respData, err := loadTestData("TestGTM_ListProperties.resp.json") 22 if err != nil { 23 t.Fatal(err) 24 } 25 26 if err := json.NewDecoder(bytes.NewBuffer(respData)).Decode(&result); err != nil { 27 t.Fatal(err) 28 } 29 30 tests := map[string]struct { 31 domain string 32 responseStatus int 33 responseBody string 34 expectedPath string 35 expectedResponse []*Property 36 withError error 37 headers http.Header 38 }{ 39 "200 OK": { 40 domain: "example.akadns.net", 41 headers: http.Header{ 42 "Content-Type": []string{"application/vnd.config-gtm.v1.4+json;charset=UTF-8"}, 43 }, 44 responseStatus: http.StatusOK, 45 responseBody: string(respData), 46 expectedPath: "/config-gtm/v1/domains/example.akadns.net/properties", 47 expectedResponse: result.PropertyItems, 48 }, 49 "500 internal server error": { 50 domain: "example.akadns.net", 51 headers: http.Header{}, 52 responseStatus: http.StatusInternalServerError, 53 responseBody: ` 54 { 55 "type": "internal_error", 56 "title": "Internal Server Error", 57 "detail": "Error fetching propertys", 58 "status": 500 59 }`, 60 expectedPath: "/config-gtm/v1/domains/example.akadns.net/properties", 61 withError: &Error{ 62 Type: "internal_error", 63 Title: "Internal Server Error", 64 Detail: "Error fetching propertys", 65 StatusCode: http.StatusInternalServerError, 66 }, 67 }, 68 } 69 70 for name, test := range tests { 71 t.Run(name, func(t *testing.T) { 72 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 73 assert.Equal(t, test.expectedPath, r.URL.String()) 74 assert.Equal(t, http.MethodGet, r.Method) 75 w.WriteHeader(test.responseStatus) 76 _, err := w.Write([]byte(test.responseBody)) 77 assert.NoError(t, err) 78 })) 79 client := mockAPIClient(t, mockServer) 80 result, err := client.ListProperties( 81 session.ContextWithOptions( 82 context.Background(), 83 session.WithContextHeaders(test.headers)), test.domain) 84 if test.withError != nil { 85 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 86 return 87 } 88 require.NoError(t, err) 89 assert.Equal(t, test.expectedResponse, result) 90 }) 91 } 92 } 93 94 func TestGTM_GetProperty(t *testing.T) { 95 var result Property 96 97 respData, err := loadTestData("TestGTM_GetProperty.resp.json") 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 if err := json.NewDecoder(bytes.NewBuffer(respData)).Decode(&result); err != nil { 103 t.Fatal(err) 104 } 105 106 tests := map[string]struct { 107 name string 108 domain string 109 responseStatus int 110 responseBody []byte 111 expectedPath string 112 expectedResponse *Property 113 withError error 114 }{ 115 "200 OK": { 116 name: "www", 117 domain: "example.akadns.net", 118 responseStatus: http.StatusOK, 119 responseBody: respData, 120 expectedPath: "/config-gtm/v1/domains/example.akadns.net/properties/www", 121 expectedResponse: &result, 122 }, 123 "500 internal server error": { 124 name: "www", 125 domain: "example.akadns.net", 126 responseStatus: http.StatusInternalServerError, 127 responseBody: []byte(` 128 { 129 "type": "internal_error", 130 "title": "Internal Server Error", 131 "detail": "Error fetching property" 132 }`), 133 expectedPath: "/config-gtm/v1/domains/example.akadns.net/properties/www", 134 withError: &Error{ 135 Type: "internal_error", 136 Title: "Internal Server Error", 137 Detail: "Error fetching property", 138 StatusCode: http.StatusInternalServerError, 139 }, 140 }, 141 } 142 143 for name, test := range tests { 144 t.Run(name, func(t *testing.T) { 145 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 146 assert.Equal(t, test.expectedPath, r.URL.String()) 147 assert.Equal(t, http.MethodGet, r.Method) 148 w.WriteHeader(test.responseStatus) 149 _, err := w.Write(test.responseBody) 150 assert.NoError(t, err) 151 })) 152 client := mockAPIClient(t, mockServer) 153 result, err := client.GetProperty(context.Background(), test.name, test.domain) 154 if test.withError != nil { 155 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 156 return 157 } 158 require.NoError(t, err) 159 assert.Equal(t, test.expectedResponse, result) 160 }) 161 } 162 } 163 164 func TestGTM_CreateProperty(t *testing.T) { 165 tests := map[string]struct { 166 domain string 167 property *Property 168 responseStatus int 169 responseBody string 170 expectedPath string 171 expectedResponse *PropertyResponse 172 withError bool 173 assertError func(*testing.T, error) 174 headers http.Header 175 }{ 176 "201 Created": { 177 property: &Property{ 178 BalanceByDownloadScore: false, 179 HandoutMode: "normal", 180 IPv6: false, 181 Name: "origin", 182 ScoreAggregationType: "mean", 183 StaticTTL: 600, 184 Type: "weighted-round-robin", 185 UseComputedTargets: false, 186 LivenessTests: []*LivenessTest{ 187 { 188 DisableNonstandardPortWarning: false, 189 HTTPError3xx: true, 190 HTTPError4xx: true, 191 HTTPError5xx: true, 192 Name: "health-check", 193 TestInterval: 60, 194 TestObject: "/status", 195 TestObjectPort: 80, 196 TestObjectProtocol: "HTTP", 197 TestTimeout: 25.0, 198 }, 199 }, 200 TrafficTargets: []*TrafficTarget{ 201 { 202 DatacenterID: 3134, 203 Enabled: true, 204 Weight: 50.0, 205 Servers: []string{"1.2.3.5"}, 206 }, 207 { 208 DatacenterID: 3133, 209 Enabled: true, 210 Weight: 50.0, 211 Servers: []string{"1.2.3.4"}, 212 Precedence: nil, 213 }, 214 }, 215 }, 216 domain: "example.akadns.net", 217 headers: http.Header{ 218 "Content-Type": []string{"application/vnd.config-gtm.v1.4+json;charset=UTF-8"}, 219 }, 220 responseStatus: http.StatusCreated, 221 responseBody: ` 222 { 223 "resource": { 224 "backupCName": null, 225 "backupIp": null, 226 "balanceByDownloadScore": false, 227 "cname": null, 228 "comments": null, 229 "dynamicTTL": 300, 230 "failbackDelay": 0, 231 "failoverDelay": 0, 232 "handoutMode": "normal", 233 "healthMax": null, 234 "healthMultiplier": null, 235 "healthThreshold": null, 236 "ipv6": false, 237 "lastModified": null, 238 "loadImbalancePercentage": null, 239 "mapName": null, 240 "maxUnreachablePenalty": null, 241 "name": "origin", 242 "scoreAggregationType": "mean", 243 "staticTTL": 600, 244 "stickinessBonusConstant": 0, 245 "stickinessBonusPercentage": 0, 246 "type": "weighted-round-robin", 247 "unreachableThreshold": null, 248 "useComputedTargets": false, 249 "mxRecords": [], 250 "links": [ 251 { 252 "href": "/config-gtm/v1/domains/example.akadns.net/properties/origin", 253 "rel": "self" 254 } 255 ], 256 "livenessTests": [ 257 { 258 "disableNonstandardPortWarning": false, 259 "hostHeader": "foo.example.com", 260 "httpError3xx": true, 261 "httpError4xx": true, 262 "httpError5xx": true, 263 "name": "health-check", 264 "requestString": null, 265 "responseString": null, 266 "sslClientCertificate": null, 267 "sslClientPrivateKey": null, 268 "testInterval": 60, 269 "testObject": "/status", 270 "testObjectPassword": null, 271 "testObjectPort": 80, 272 "testObjectProtocol": "HTTP", 273 "testObjectUsername": null, 274 "testTimeout": 25.0 275 } 276 ], 277 "trafficTargets": [ 278 { 279 "datacenterId": 3134, 280 "enabled": true, 281 "handoutCName": null, 282 "name": null, 283 "weight": 50.0, 284 "servers": [ 285 "1.2.3.5" 286 ], 287 "precedence": null 288 }, 289 { 290 "datacenterId": 3133, 291 "enabled": true, 292 "handoutCName": null, 293 "name": null, 294 "weight": 50.0, 295 "servers": [ 296 "1.2.3.4" 297 ], 298 "precedence": null 299 } 300 ] 301 }, 302 "status": { 303 "changeId": "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 304 "message": "Change Pending", 305 "passingValidation": true, 306 "propagationStatus": "PENDING", 307 "propagationStatusDate": "2014-04-15T11:30:27.000+0000", 308 "links": [ 309 { 310 "href": "/config-gtm/v1/domains/example.akadns.net/status/current", 311 "rel": "self" 312 } 313 ] 314 } 315 } 316 `, 317 expectedResponse: &PropertyResponse{ 318 Resource: &Property{ 319 BalanceByDownloadScore: false, 320 HandoutMode: "normal", 321 IPv6: false, 322 Name: "origin", 323 ScoreAggregationType: "mean", 324 StaticTTL: 600, 325 DynamicTTL: 300, 326 Type: "weighted-round-robin", 327 UseComputedTargets: false, 328 LivenessTests: []*LivenessTest{ 329 { 330 DisableNonstandardPortWarning: false, 331 HTTPError3xx: true, 332 HTTPError4xx: true, 333 HTTPError5xx: true, 334 Name: "health-check", 335 TestInterval: 60, 336 TestObject: "/status", 337 TestObjectPort: 80, 338 TestObjectProtocol: "HTTP", 339 TestTimeout: 25.0, 340 }, 341 }, 342 TrafficTargets: []*TrafficTarget{ 343 { 344 DatacenterID: 3134, 345 Enabled: true, 346 Weight: 50.0, 347 Servers: []string{"1.2.3.5"}, 348 }, 349 { 350 DatacenterID: 3133, 351 Enabled: true, 352 Weight: 50.0, 353 Servers: []string{"1.2.3.4"}, 354 }, 355 }, 356 Links: []*Link{ 357 { 358 Href: "/config-gtm/v1/domains/example.akadns.net/properties/origin", 359 Rel: "self", 360 }, 361 }, 362 }, 363 Status: &ResponseStatus{ 364 ChangeID: "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 365 Message: "Change Pending", 366 PassingValidation: true, 367 PropagationStatus: "PENDING", 368 PropagationStatusDate: "2014-04-15T11:30:27.000+0000", 369 Links: &[]Link{ 370 { 371 Href: "/config-gtm/v1/domains/example.akadns.net/status/current", 372 Rel: "self", 373 }, 374 }, 375 }, 376 }, 377 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 378 }, 379 "201 Created - ranked-failover": { 380 property: &Property{ 381 BalanceByDownloadScore: false, 382 HandoutMode: "normal", 383 IPv6: false, 384 Name: "origin", 385 ScoreAggregationType: "mean", 386 StaticTTL: 600, 387 Type: "ranked-failover", 388 UseComputedTargets: false, 389 LivenessTests: []*LivenessTest{ 390 { 391 DisableNonstandardPortWarning: false, 392 HTTPError3xx: true, 393 HTTPError4xx: true, 394 HTTPError5xx: true, 395 HTTPMethod: tools.StringPtr("GET"), 396 HTTPRequestBody: tools.StringPtr("TestBody"), 397 Name: "health-check", 398 TestInterval: 60, 399 TestObject: "/status", 400 TestObjectPort: 80, 401 TestObjectProtocol: "HTTP", 402 TestTimeout: 25.0, 403 Pre2023SecurityPosture: true, 404 AlternateCACertificates: []string{"test1"}, 405 }, 406 }, 407 TrafficTargets: []*TrafficTarget{ 408 { 409 DatacenterID: 3134, 410 Enabled: true, 411 Weight: 50.0, 412 Servers: []string{"1.2.3.5"}, 413 Precedence: tools.IntPtr(255), 414 }, 415 { 416 DatacenterID: 3133, 417 Enabled: true, 418 Weight: 50.0, 419 Servers: []string{"1.2.3.4"}, 420 Precedence: nil, 421 }, 422 }, 423 }, 424 domain: "example.akadns.net", 425 headers: http.Header{ 426 "Content-Type": []string{"application/vnd.config-gtm.v1.4+json;charset=UTF-8"}, 427 }, 428 responseStatus: http.StatusCreated, 429 responseBody: ` 430 { 431 "resource": { 432 "backupCName": null, 433 "backupIp": null, 434 "balanceByDownloadScore": false, 435 "cname": null, 436 "comments": null, 437 "dynamicTTL": 300, 438 "failbackDelay": 0, 439 "failoverDelay": 0, 440 "handoutMode": "normal", 441 "healthMax": null, 442 "healthMultiplier": null, 443 "healthThreshold": null, 444 "ipv6": false, 445 "lastModified": null, 446 "loadImbalancePercentage": null, 447 "mapName": null, 448 "maxUnreachablePenalty": null, 449 "name": "origin", 450 "scoreAggregationType": "mean", 451 "staticTTL": 600, 452 "stickinessBonusConstant": 0, 453 "stickinessBonusPercentage": 0, 454 "type": "weighted-round-robin", 455 "unreachableThreshold": null, 456 "useComputedTargets": false, 457 "mxRecords": [], 458 "links": [ 459 { 460 "href": "/config-gtm/v1/domains/example.akadns.net/properties/origin", 461 "rel": "self" 462 } 463 ], 464 "livenessTests": [ 465 { 466 "disableNonstandardPortWarning": false, 467 "hostHeader": "foo.example.com", 468 "httpError3xx": true, 469 "httpError4xx": true, 470 "httpError5xx": true, 471 "httpMethod": "GET", 472 "httpRequestBody": "TestBody", 473 "pre2023SecurityPosture": true, 474 "alternateCACertificates": ["test1"], 475 "name": "health-check", 476 "requestString": null, 477 "responseString": null, 478 "sslClientCertificate": null, 479 "sslClientPrivateKey": null, 480 "testInterval": 60, 481 "testObject": "/status", 482 "testObjectPassword": null, 483 "testObjectPort": 80, 484 "testObjectProtocol": "HTTP", 485 "testObjectUsername": null, 486 "testTimeout": 25.0 487 } 488 ], 489 "trafficTargets": [ 490 { 491 "datacenterId": 3134, 492 "enabled": true, 493 "handoutCName": null, 494 "name": null, 495 "weight": 50.0, 496 "servers": [ 497 "1.2.3.5" 498 ], 499 "precedence": 255 500 }, 501 { 502 "datacenterId": 3133, 503 "enabled": true, 504 "handoutCName": null, 505 "name": null, 506 "weight": 50.0, 507 "servers": [ 508 "1.2.3.4" 509 ], 510 "precedence": null 511 } 512 ] 513 }, 514 "status": { 515 "changeId": "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 516 "message": "Change Pending", 517 "passingValidation": true, 518 "propagationStatus": "PENDING", 519 "propagationStatusDate": "2014-04-15T11:30:27.000+0000", 520 "links": [ 521 { 522 "href": "/config-gtm/v1/domains/example.akadns.net/status/current", 523 "rel": "self" 524 } 525 ] 526 } 527 } 528 `, 529 expectedResponse: &PropertyResponse{ 530 Resource: &Property{ 531 BalanceByDownloadScore: false, 532 HandoutMode: "normal", 533 IPv6: false, 534 Name: "origin", 535 ScoreAggregationType: "mean", 536 StaticTTL: 600, 537 DynamicTTL: 300, 538 Type: "weighted-round-robin", 539 UseComputedTargets: false, 540 LivenessTests: []*LivenessTest{ 541 { 542 DisableNonstandardPortWarning: false, 543 HTTPError3xx: true, 544 HTTPError4xx: true, 545 HTTPError5xx: true, 546 HTTPMethod: tools.StringPtr("GET"), 547 HTTPRequestBody: tools.StringPtr("TestBody"), 548 Pre2023SecurityPosture: true, 549 AlternateCACertificates: []string{"test1"}, 550 Name: "health-check", 551 TestInterval: 60, 552 TestObject: "/status", 553 TestObjectPort: 80, 554 TestObjectProtocol: "HTTP", 555 TestTimeout: 25.0, 556 }, 557 }, 558 TrafficTargets: []*TrafficTarget{ 559 { 560 DatacenterID: 3134, 561 Enabled: true, 562 Weight: 50.0, 563 Servers: []string{"1.2.3.5"}, 564 Precedence: tools.IntPtr(255), 565 }, 566 { 567 DatacenterID: 3133, 568 Enabled: true, 569 Weight: 50.0, 570 Servers: []string{"1.2.3.4"}, 571 Precedence: nil, 572 }, 573 }, 574 Links: []*Link{ 575 { 576 Href: "/config-gtm/v1/domains/example.akadns.net/properties/origin", 577 Rel: "self", 578 }, 579 }, 580 }, 581 Status: &ResponseStatus{ 582 ChangeID: "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 583 Message: "Change Pending", 584 PassingValidation: true, 585 PropagationStatus: "PENDING", 586 PropagationStatusDate: "2014-04-15T11:30:27.000+0000", 587 Links: &[]Link{ 588 { 589 Href: "/config-gtm/v1/domains/example.akadns.net/status/current", 590 Rel: "self", 591 }, 592 }, 593 }, 594 }, 595 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 596 }, 597 "validation error - missing precedence for ranked-failover property type": { 598 property: &Property{ 599 Type: "ranked-failover", 600 Name: "property", 601 HandoutMode: "normal", 602 ScoreAggregationType: "mean", 603 TrafficTargets: []*TrafficTarget{ 604 { 605 DatacenterID: 1, 606 Enabled: false, 607 Precedence: nil, 608 }, 609 { 610 DatacenterID: 2, 611 Enabled: false, 612 Precedence: nil, 613 }, 614 }, 615 }, 616 withError: true, 617 assertError: func(t *testing.T, err error) { 618 assert.ErrorContains(t, err, "TrafficTargets: property cannot have multiple primary traffic targets (targets with lowest precedence)") 619 }, 620 }, 621 "validation error - precedence value over the limit": { 622 property: &Property{ 623 Type: "ranked-failover", 624 Name: "property", 625 HandoutMode: "normal", 626 ScoreAggregationType: "mean", 627 TrafficTargets: []*TrafficTarget{ 628 { 629 DatacenterID: 1, 630 Enabled: false, 631 Precedence: tools.IntPtr(256), 632 }, 633 }, 634 }, 635 withError: true, 636 assertError: func(t *testing.T, err error) { 637 assert.ErrorContains(t, err, "property validation failed. TrafficTargets: 'Precedence' value has to be between 0 and 255") 638 }, 639 }, 640 "500 internal server error": { 641 property: &Property{ 642 Name: "testName", 643 HandoutMode: "normal", 644 ScoreAggregationType: "mean", 645 Type: "failover", 646 }, 647 domain: "example.akadns.net", 648 responseStatus: http.StatusInternalServerError, 649 responseBody: ` 650 { 651 "type": "internal_error", 652 "title": "Internal Server Error", 653 "detail": "Error creating domain" 654 }`, 655 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 656 withError: true, 657 assertError: func(t *testing.T, err error) { 658 want := &Error{ 659 Type: "internal_error", 660 Title: "Internal Server Error", 661 Detail: "Error creating domain", 662 StatusCode: http.StatusInternalServerError, 663 } 664 assert.ErrorIs(t, err, want) 665 }, 666 }, 667 } 668 669 for name, test := range tests { 670 t.Run(name, func(t *testing.T) { 671 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 672 assert.Equal(t, http.MethodPut, r.Method) 673 w.WriteHeader(test.responseStatus) 674 if len(test.responseBody) > 0 { 675 _, err := w.Write([]byte(test.responseBody)) 676 assert.NoError(t, err) 677 } 678 })) 679 client := mockAPIClient(t, mockServer) 680 result, err := client.CreateProperty( 681 session.ContextWithOptions( 682 context.Background(), 683 session.WithContextHeaders(test.headers)), test.property, test.domain) 684 if test.withError { 685 test.assertError(t, err) 686 return 687 } 688 require.NoError(t, err) 689 assert.Equal(t, test.expectedResponse, result) 690 }) 691 } 692 } 693 694 func TestGTM_UpdateProperty(t *testing.T) { 695 tests := map[string]struct { 696 property *Property 697 domain string 698 responseStatus int 699 responseBody string 700 expectedPath string 701 expectedResponse *ResponseStatus 702 withError bool 703 assertError func(*testing.T, error) 704 headers http.Header 705 }{ 706 "200 Success": { 707 property: &Property{ 708 BalanceByDownloadScore: false, 709 HandoutMode: "normal", 710 IPv6: false, 711 Name: "origin", 712 ScoreAggregationType: "mean", 713 StaticTTL: 600, 714 Type: "weighted-round-robin", 715 UseComputedTargets: false, 716 LivenessTests: []*LivenessTest{ 717 { 718 DisableNonstandardPortWarning: false, 719 HTTPError3xx: true, 720 HTTPError4xx: true, 721 HTTPError5xx: true, 722 Name: "health-check", 723 TestInterval: 60, 724 TestObject: "/status", 725 TestObjectPort: 80, 726 TestObjectProtocol: "HTTP", 727 TestTimeout: 25.0, 728 }, 729 }, 730 TrafficTargets: []*TrafficTarget{ 731 { 732 DatacenterID: 3134, 733 Enabled: true, 734 Weight: 50.0, 735 Servers: []string{"1.2.3.5"}, 736 Precedence: tools.IntPtr(255), 737 }, 738 { 739 DatacenterID: 3133, 740 Enabled: true, 741 Weight: 50.0, 742 Servers: []string{"1.2.3.4"}, 743 Precedence: nil, 744 }, 745 }, 746 }, 747 domain: "example.akadns.net", 748 headers: http.Header{ 749 "Content-Type": []string{"application/vnd.config-gtm.v1.4+json;charset=UTF-8"}, 750 }, 751 responseStatus: http.StatusCreated, 752 responseBody: ` 753 { 754 "resource": { 755 "backupCName": null, 756 "backupIp": null, 757 "balanceByDownloadScore": false, 758 "cname": null, 759 "comments": null, 760 "dynamicTTL": 300, 761 "failbackDelay": 0, 762 "failoverDelay": 0, 763 "handoutMode": "normal", 764 "healthMax": null, 765 "healthMultiplier": null, 766 "healthThreshold": null, 767 "ipv6": false, 768 "lastModified": null, 769 "loadImbalancePercentage": null, 770 "mapName": null, 771 "maxUnreachablePenalty": null, 772 "name": "origin", 773 "scoreAggregationType": "mean", 774 "staticTTL": 600, 775 "stickinessBonusConstant": 0, 776 "stickinessBonusPercentage": 0, 777 "type": "weighted-round-robin", 778 "unreachableThreshold": null, 779 "useComputedTargets": false, 780 "mxRecords": [], 781 "links": [ 782 { 783 "href": "/config-gtm/v1/domains/example.akadns.net/properties/origin", 784 "rel": "self" 785 } 786 ], 787 "livenessTests": [ 788 { 789 "disableNonstandardPortWarning": false, 790 "hostHeader": "foo.example.com", 791 "httpError3xx": true, 792 "httpError4xx": true, 793 "httpError5xx": true, 794 "name": "health-check", 795 "requestString": null, 796 "responseString": null, 797 "sslClientCertificate": null, 798 "sslClientPrivateKey": null, 799 "testInterval": 60, 800 "testObject": "/status", 801 "testObjectPassword": null, 802 "testObjectPort": 80, 803 "testObjectProtocol": "HTTP", 804 "testObjectUsername": null, 805 "testTimeout": 25.0 806 } 807 ], 808 "trafficTargets": [ 809 { 810 "datacenterId": 3134, 811 "enabled": true, 812 "handoutCName": null, 813 "name": null, 814 "weight": 50.0, 815 "servers": [ 816 "1.2.3.5" 817 ], 818 "precedence": 255 819 }, 820 { 821 "datacenterId": 3133, 822 "enabled": true, 823 "handoutCName": null, 824 "name": null, 825 "weight": 50.0, 826 "servers": [ 827 "1.2.3.4" 828 ], 829 "precedence": null 830 } 831 ] 832 }, 833 "status": { 834 "changeId": "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 835 "message": "Change Pending", 836 "passingValidation": true, 837 "propagationStatus": "PENDING", 838 "propagationStatusDate": "2014-04-15T11:30:27.000+0000", 839 "links": [ 840 { 841 "href": "/config-gtm/v1/domains/example.akadns.net/status/current", 842 "rel": "self" 843 } 844 ] 845 } 846 } 847 `, 848 expectedResponse: &ResponseStatus{ 849 ChangeID: "eee0c3b4-0e45-4f4b-822c-7dbc60764d18", 850 Message: "Change Pending", 851 PassingValidation: true, 852 PropagationStatus: "PENDING", 853 PropagationStatusDate: "2014-04-15T11:30:27.000+0000", 854 Links: &[]Link{ 855 { 856 Href: "/config-gtm/v1/domains/example.akadns.net/status/current", 857 Rel: "self", 858 }, 859 }, 860 }, 861 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 862 }, 863 "validation error - missing precedence for ranked-failover property type": { 864 property: &Property{ 865 Type: "ranked-failover", 866 Name: "property", 867 HandoutMode: "normal", 868 ScoreAggregationType: "mean", 869 TrafficTargets: []*TrafficTarget{ 870 { 871 DatacenterID: 1, 872 Enabled: false, 873 Precedence: nil, 874 }, 875 { 876 DatacenterID: 2, 877 Enabled: false, 878 Precedence: nil, 879 }, 880 }, 881 }, 882 withError: true, 883 assertError: func(t *testing.T, err error) { 884 assert.ErrorContains(t, err, "TrafficTargets: property cannot have multiple primary traffic targets (targets with lowest precedence)") 885 }, 886 }, 887 "validation error - no traffic targets": { 888 property: &Property{ 889 Type: "ranked-failover", 890 Name: "property", 891 HandoutMode: "normal", 892 ScoreAggregationType: "mean", 893 }, 894 withError: true, 895 assertError: func(t *testing.T, err error) { 896 assert.ErrorContains(t, err, "property validation failed. TrafficTargets: no traffic targets are enabled") 897 }, 898 }, 899 "500 internal server error": { 900 property: &Property{ 901 Name: "testName", 902 HandoutMode: "normal", 903 ScoreAggregationType: "mean", 904 Type: "failover", 905 }, 906 domain: "example.akadns.net", 907 responseStatus: http.StatusInternalServerError, 908 responseBody: ` 909 { 910 "type": "internal_error", 911 "title": "Internal Server Error", 912 "detail": "Error creating zone" 913 }`, 914 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 915 withError: true, 916 assertError: func(t *testing.T, err error) { 917 want := &Error{ 918 Type: "internal_error", 919 Title: "Internal Server Error", 920 Detail: "Error creating zone", 921 StatusCode: http.StatusInternalServerError, 922 } 923 assert.ErrorIs(t, err, want) 924 }, 925 }, 926 } 927 928 for name, test := range tests { 929 t.Run(name, func(t *testing.T) { 930 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 931 assert.Equal(t, http.MethodPut, r.Method) 932 w.WriteHeader(test.responseStatus) 933 if len(test.responseBody) > 0 { 934 _, err := w.Write([]byte(test.responseBody)) 935 assert.NoError(t, err) 936 } 937 })) 938 client := mockAPIClient(t, mockServer) 939 result, err := client.UpdateProperty( 940 session.ContextWithOptions( 941 context.Background(), 942 session.WithContextHeaders(test.headers)), test.property, test.domain) 943 if test.withError { 944 test.assertError(t, err) 945 return 946 } 947 require.NoError(t, err) 948 assert.Equal(t, test.expectedResponse, result) 949 }) 950 } 951 } 952 953 func TestGTM_DeleteProperty(t *testing.T) { 954 var result PropertyResponse 955 var req Property 956 957 respData, err := loadTestData("TestGTM_CreateProperty.resp.json") 958 if err != nil { 959 t.Fatal(err) 960 } 961 962 if err := json.NewDecoder(bytes.NewBuffer(respData)).Decode(&result); err != nil { 963 t.Fatal(err) 964 } 965 966 reqData, err := loadTestData("TestGTM_CreateProperty.req.json") 967 if err != nil { 968 t.Fatal(err) 969 } 970 971 if err := json.NewDecoder(bytes.NewBuffer(reqData)).Decode(&req); err != nil { 972 t.Fatal(err) 973 } 974 975 tests := map[string]struct { 976 prop *Property 977 domain string 978 responseStatus int 979 responseBody []byte 980 expectedPath string 981 expectedResponse *ResponseStatus 982 withError error 983 headers http.Header 984 }{ 985 "200 Success": { 986 prop: &req, 987 domain: "example.akadns.net", 988 headers: http.Header{ 989 "Content-Type": []string{"application/vnd.config-gtm.v1.4+json;charset=UTF-8"}, 990 }, 991 responseStatus: http.StatusOK, 992 responseBody: respData, 993 expectedResponse: result.Status, 994 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 995 }, 996 "500 internal server error": { 997 prop: &req, 998 domain: "example.akadns.net", 999 responseStatus: http.StatusInternalServerError, 1000 responseBody: []byte(` 1001 { 1002 "type": "internal_error", 1003 "title": "Internal Server Error", 1004 "detail": "Error creating zone" 1005 }`), 1006 expectedPath: "/config-gtm/v1/domains/example.akadns.net?contractId=1-2ABCDE", 1007 withError: &Error{ 1008 Type: "internal_error", 1009 Title: "Internal Server Error", 1010 Detail: "Error creating zone", 1011 StatusCode: http.StatusInternalServerError, 1012 }, 1013 }, 1014 } 1015 1016 for name, test := range tests { 1017 t.Run(name, func(t *testing.T) { 1018 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1019 assert.Equal(t, http.MethodDelete, r.Method) 1020 w.WriteHeader(test.responseStatus) 1021 if len(test.responseBody) > 0 { 1022 _, err := w.Write(test.responseBody) 1023 assert.NoError(t, err) 1024 } 1025 })) 1026 client := mockAPIClient(t, mockServer) 1027 result, err := client.DeleteProperty( 1028 session.ContextWithOptions( 1029 context.Background(), 1030 session.WithContextHeaders(test.headers)), test.prop, test.domain) 1031 if test.withError != nil { 1032 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 1033 return 1034 } 1035 require.NoError(t, err) 1036 assert.Equal(t, test.expectedResponse, result) 1037 }) 1038 } 1039 }