github.com/akamai/AkamaiOPEN-edgegrid-golang/v4@v4.1.0/pkg/papi/include_rule_test.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestGetIncludeRuleTree(t *testing.T) { 16 tests := map[string]struct { 17 params GetIncludeRuleTreeRequest 18 responseStatus int 19 responseBody string 20 expectedPath string 21 expectedResponse *GetIncludeRuleTreeResponse 22 withError error 23 }{ 24 "200 OK - get include": { 25 params: GetIncludeRuleTreeRequest{ 26 IncludeID: "inc_123456", 27 IncludeVersion: 2, 28 ContractID: "test_contract", 29 GroupID: "test_group", 30 ValidateMode: "fast", 31 ValidateRules: false, 32 }, 33 responseStatus: http.StatusOK, 34 responseBody: ` 35 { 36 "accountId": "test_account", 37 "contractId": "test_contract", 38 "groupId": "test_group", 39 "includeId": "inc_123456", 40 "includeVersion": 2, 41 "includeName": "test_include", 42 "includeType": "MICROSERVICES", 43 "etag": "etag", 44 "ruleFormat": "v2020-11-02", 45 "rules": { 46 "name": "default", 47 "criteria": [], 48 "children": [ 49 { 50 "name": "Compress Text Content", 51 "criteria": [ 52 { 53 "name": "contentType", 54 "options": { 55 "matchOperator": "IS_ONE_OF", 56 "matchWildcard": true, 57 "matchCaseSensitive": false, 58 "values": [ 59 "text/html*", 60 "text/css*", 61 "application/x-javascript*" 62 ] 63 } 64 } 65 ], 66 "behaviors": [ 67 { 68 "name": "gzipResponse", 69 "options": { "behavior": "ALWAYS" } 70 } 71 ] 72 } 73 ], 74 "options": { 75 "is_secure": false 76 }, 77 "behaviors": [ 78 { 79 "name": "origin", 80 "options": { 81 "httpPort": 80, 82 "enableTrueClientIp": false, 83 "compress": true, 84 "cacheKeyHostname": "ORIGIN_HOSTNAME", 85 "forwardHostHeader": "REQUEST_HOST_HEADER", 86 "hostname": "origin.test.com", 87 "originType": "CUSTOMER" 88 } 89 }, 90 { 91 "name": "cpCode", 92 "options": { 93 "value": { 94 "id": 12345, 95 "name": "my CP code" 96 } 97 } 98 } 99 ], 100 "customOverride": { 101 "overrideId": "cbo_12345", 102 "name": "mdc" 103 }, 104 "variables": [ 105 { 106 "name": "VAR_NAME", 107 "value": "default value", 108 "description": "This is a sample Property Manager variable.", 109 "hidden": false, 110 "sensitive": false 111 } 112 ] 113 } 114 }`, 115 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 116 expectedResponse: &GetIncludeRuleTreeResponse{ 117 Response: Response{ 118 AccountID: "test_account", 119 ContractID: "test_contract", 120 GroupID: "test_group", 121 }, 122 IncludeID: "inc_123456", 123 IncludeVersion: 2, 124 IncludeName: "test_include", 125 IncludeType: IncludeTypeMicroServices, 126 Etag: "etag", 127 RuleFormat: "v2020-11-02", 128 Rules: Rules{ 129 Behaviors: []RuleBehavior{ 130 { 131 Name: "origin", 132 Options: RuleOptionsMap{ 133 "httpPort": float64(80), 134 "enableTrueClientIp": false, 135 "compress": true, 136 "cacheKeyHostname": "ORIGIN_HOSTNAME", 137 "forwardHostHeader": "REQUEST_HOST_HEADER", 138 "hostname": "origin.test.com", 139 "originType": "CUSTOMER", 140 }, 141 }, 142 { 143 Name: "cpCode", 144 Options: RuleOptionsMap{ 145 "value": map[string]interface{}{ 146 "id": float64(12345), 147 "name": "my CP code", 148 }, 149 }, 150 }, 151 }, 152 Children: []Rules{ 153 { 154 Behaviors: []RuleBehavior{ 155 { 156 Name: "gzipResponse", 157 Options: RuleOptionsMap{ 158 "behavior": "ALWAYS", 159 }, 160 }, 161 }, 162 Criteria: []RuleBehavior{ 163 { 164 Locked: false, 165 Name: "contentType", 166 Options: RuleOptionsMap{ 167 "matchOperator": "IS_ONE_OF", 168 "matchWildcard": true, 169 "matchCaseSensitive": false, 170 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 171 }, 172 }, 173 }, 174 Name: "Compress Text Content", 175 }, 176 }, 177 Criteria: []RuleBehavior{}, 178 Name: "default", 179 Options: RuleOptions{IsSecure: false}, 180 CustomOverride: &RuleCustomOverride{ 181 OverrideID: "cbo_12345", 182 Name: "mdc", 183 }, 184 Variables: []RuleVariable{ 185 { 186 Description: "This is a sample Property Manager variable.", 187 Hidden: false, 188 Name: "VAR_NAME", 189 Sensitive: false, 190 Value: "default value", 191 }, 192 }, 193 }, 194 }, 195 }, 196 "200 OK - get include with ruleFormat": { 197 params: GetIncludeRuleTreeRequest{ 198 IncludeID: "inc_123456", 199 IncludeVersion: 2, 200 ContractID: "test_contract", 201 GroupID: "test_group", 202 RuleFormat: "v2020-11-02", 203 ValidateMode: "fast", 204 ValidateRules: false, 205 }, 206 responseStatus: http.StatusOK, 207 responseBody: ` 208 { 209 "accountId": "test_account", 210 "contractId": "test_contract", 211 "groupId": "test_group", 212 "includeId": "inc_123456", 213 "includeVersion": 2, 214 "includeName": "test_include", 215 "includeType": "MICROSERVICES", 216 "etag": "etag", 217 "ruleFormat": "v2020-11-02", 218 "rules": { 219 "name": "default", 220 "criteria": [], 221 "children": [ 222 { 223 "name": "Compress Text Content", 224 "criteria": [ 225 { 226 "name": "contentType", 227 "options": { 228 "matchOperator": "IS_ONE_OF", 229 "matchWildcard": true, 230 "matchCaseSensitive": false, 231 "values": [ 232 "text/html*", 233 "text/css*", 234 "application/x-javascript*" 235 ] 236 } 237 } 238 ], 239 "behaviors": [ 240 { 241 "name": "gzipResponse", 242 "options": { "behavior": "ALWAYS" } 243 } 244 ] 245 } 246 ], 247 "options": { 248 "is_secure": false 249 }, 250 "behaviors": [ 251 { 252 "name": "origin", 253 "options": { 254 "httpPort": 80, 255 "enableTrueClientIp": false, 256 "compress": true, 257 "cacheKeyHostname": "ORIGIN_HOSTNAME", 258 "forwardHostHeader": "REQUEST_HOST_HEADER", 259 "hostname": "origin.test.com", 260 "originType": "CUSTOMER" 261 } 262 }, 263 { 264 "name": "cpCode", 265 "options": { 266 "value": { 267 "id": 12345, 268 "name": "my CP code" 269 } 270 } 271 } 272 ], 273 "customOverride": { 274 "overrideId": "cbo_12345", 275 "name": "mdc" 276 }, 277 "variables": [ 278 { 279 "name": "VAR_NAME", 280 "value": "default value", 281 "description": "This is a sample Property Manager variable.", 282 "hidden": false, 283 "sensitive": false 284 } 285 ] 286 } 287 }`, 288 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 289 expectedResponse: &GetIncludeRuleTreeResponse{ 290 Response: Response{ 291 AccountID: "test_account", 292 ContractID: "test_contract", 293 GroupID: "test_group", 294 }, 295 IncludeID: "inc_123456", 296 IncludeVersion: 2, 297 IncludeName: "test_include", 298 IncludeType: IncludeTypeMicroServices, 299 Etag: "etag", 300 RuleFormat: "v2020-11-02", 301 Rules: Rules{ 302 Behaviors: []RuleBehavior{ 303 { 304 Name: "origin", 305 Options: RuleOptionsMap{ 306 "httpPort": float64(80), 307 "enableTrueClientIp": false, 308 "compress": true, 309 "cacheKeyHostname": "ORIGIN_HOSTNAME", 310 "forwardHostHeader": "REQUEST_HOST_HEADER", 311 "hostname": "origin.test.com", 312 "originType": "CUSTOMER", 313 }, 314 }, 315 { 316 Name: "cpCode", 317 Options: RuleOptionsMap{ 318 "value": map[string]interface{}{ 319 "id": float64(12345), 320 "name": "my CP code", 321 }, 322 }, 323 }, 324 }, 325 Children: []Rules{ 326 { 327 Behaviors: []RuleBehavior{ 328 { 329 Name: "gzipResponse", 330 Options: RuleOptionsMap{ 331 "behavior": "ALWAYS", 332 }, 333 }, 334 }, 335 Criteria: []RuleBehavior{ 336 { 337 Locked: false, 338 Name: "contentType", 339 Options: RuleOptionsMap{ 340 "matchOperator": "IS_ONE_OF", 341 "matchWildcard": true, 342 "matchCaseSensitive": false, 343 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 344 }, 345 }, 346 }, 347 Name: "Compress Text Content", 348 }, 349 }, 350 Criteria: []RuleBehavior{}, 351 Name: "default", 352 Options: RuleOptions{IsSecure: false}, 353 CustomOverride: &RuleCustomOverride{ 354 OverrideID: "cbo_12345", 355 Name: "mdc", 356 }, 357 Variables: []RuleVariable{ 358 { 359 Description: "This is a sample Property Manager variable.", 360 Hidden: false, 361 Name: "VAR_NAME", 362 Sensitive: false, 363 Value: "default value", 364 }, 365 }, 366 }, 367 }, 368 }, 369 "500 Internal Server Error": { 370 params: GetIncludeRuleTreeRequest{ 371 IncludeID: "inc_123456", 372 IncludeVersion: 2, 373 ContractID: "test_contract", 374 GroupID: "test_group", 375 ValidateMode: "fast", 376 ValidateRules: false, 377 }, 378 responseStatus: http.StatusInternalServerError, 379 responseBody: ` 380 { 381 "type": "internal_error", 382 "title": "Internal Server Error", 383 "detail": "Error fetching rule tree", 384 "status": 500 385 }`, 386 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 387 withError: &Error{ 388 Type: "internal_error", 389 Title: "Internal Server Error", 390 Detail: "Error fetching rule tree", 391 StatusCode: http.StatusInternalServerError, 392 }, 393 }, 394 "validation error - missing includeId": { 395 params: GetIncludeRuleTreeRequest{ 396 IncludeVersion: 2, 397 ContractID: "test_contract", 398 GroupID: "test_group", 399 ValidateMode: "fast", 400 ValidateRules: false, 401 }, 402 withError: ErrStructValidation, 403 }, 404 "validation error - missing includeVersion": { 405 params: GetIncludeRuleTreeRequest{ 406 IncludeID: "inc_123456", 407 ContractID: "test_contract", 408 GroupID: "test_group", 409 ValidateMode: "fast", 410 ValidateRules: false, 411 }, 412 withError: ErrStructValidation, 413 }, 414 "validation error - missing contractId": { 415 params: GetIncludeRuleTreeRequest{ 416 IncludeID: "inc_123456", 417 IncludeVersion: 2, 418 GroupID: "test_group", 419 ValidateMode: "fast", 420 ValidateRules: false, 421 }, 422 withError: ErrStructValidation, 423 }, 424 "validation error - missing groupId": { 425 params: GetIncludeRuleTreeRequest{ 426 IncludeID: "inc_123456", 427 IncludeVersion: 2, 428 ContractID: "test_contract", 429 ValidateMode: "fast", 430 ValidateRules: false, 431 }, 432 withError: ErrStructValidation, 433 }, 434 "validation error - invalid validation mode": { 435 params: GetIncludeRuleTreeRequest{ 436 IncludeID: "inc_123456", 437 IncludeVersion: 2, 438 ContractID: "test_contract", 439 GroupID: "test_group", 440 ValidateMode: "test", 441 ValidateRules: false, 442 }, 443 withError: ErrStructValidation, 444 }, 445 "validation error - invalid ruleFormat": { 446 params: GetIncludeRuleTreeRequest{ 447 IncludeID: "inc_123456", 448 IncludeVersion: 2, 449 ContractID: "test_contract", 450 GroupID: "test_group", 451 RuleFormat: "invalid", 452 ValidateMode: "fast", 453 ValidateRules: false, 454 }, 455 withError: ErrStructValidation, 456 }, 457 } 458 459 for name, test := range tests { 460 t.Run(name, func(t *testing.T) { 461 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 462 assert.Equal(t, test.expectedPath, r.URL.String()) 463 assert.Equal(t, http.MethodGet, r.Method) 464 w.WriteHeader(test.responseStatus) 465 _, err := w.Write([]byte(test.responseBody)) 466 if test.params.RuleFormat != "" { 467 assert.Equal(t, r.Header.Get("Accept"), fmt.Sprintf("application/vnd.akamai.papirules.%s+json", test.params.RuleFormat)) 468 } 469 assert.NoError(t, err) 470 })) 471 client := mockAPIClient(t, mockServer) 472 result, err := client.GetIncludeRuleTree(context.Background(), test.params) 473 if test.withError != nil { 474 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 475 return 476 } 477 require.NoError(t, err) 478 assert.Equal(t, test.expectedResponse, result) 479 }) 480 } 481 } 482 483 func TestUpdateIncludeRuleTree(t *testing.T) { 484 tests := map[string]struct { 485 params UpdateIncludeRuleTreeRequest 486 responseStatus int 487 responseBody string 488 responseHeaders map[string]string 489 expectedPath string 490 expectedResponse *UpdateIncludeRuleTreeResponse 491 withError error 492 }{ 493 "200 OK - update rule tree": { 494 params: UpdateIncludeRuleTreeRequest{ 495 IncludeID: "inc_123456", 496 IncludeVersion: 2, 497 ContractID: "test_contract", 498 GroupID: "test_group", 499 DryRun: true, 500 ValidateMode: "fast", 501 ValidateRules: false, 502 Rules: RulesUpdate{ 503 Comments: "version comment", 504 Rules: Rules{ 505 Comments: "default comment", 506 Behaviors: []RuleBehavior{ 507 { 508 Name: "origin", 509 Options: RuleOptionsMap{ 510 "httpPort": float64(80), 511 "enableTrueClientIp": false, 512 "compress": true, 513 "cacheKeyHostname": "ORIGIN_HOSTNAME", 514 "forwardHostHeader": "REQUEST_HOST_HEADER", 515 "hostname": "origin.test.com", 516 "originType": "CUSTOMER", 517 }, 518 }, 519 { 520 Name: "cpCode", 521 Options: RuleOptionsMap{ 522 "value": map[string]interface{}{ 523 "id": float64(12345), 524 "name": "my CP code", 525 }, 526 }, 527 }, 528 }, 529 Children: []Rules{ 530 { 531 Behaviors: []RuleBehavior{ 532 { 533 Name: "gzipResponse", 534 Options: RuleOptionsMap{ 535 "behavior": "ALWAYS", 536 }, 537 }, 538 }, 539 Criteria: []RuleBehavior{ 540 { 541 Locked: false, 542 Name: "contentType", 543 Options: RuleOptionsMap{ 544 "matchOperator": "IS_ONE_OF", 545 "matchWildcard": true, 546 "matchCaseSensitive": false, 547 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 548 }, 549 }, 550 }, 551 Name: "Compress Text Content", 552 }, 553 }, 554 Criteria: []RuleBehavior{}, 555 Name: "default", 556 Options: RuleOptions{IsSecure: false}, 557 CustomOverride: &RuleCustomOverride{ 558 OverrideID: "cbo_12345", 559 Name: "mdc", 560 }, 561 Variables: []RuleVariable{ 562 { 563 Description: "This is a sample Property Manager variable.", 564 Hidden: false, 565 Name: "VAR_NAME", 566 Sensitive: false, 567 Value: "default value", 568 }, 569 }, 570 }, 571 }, 572 }, 573 responseStatus: http.StatusOK, 574 responseHeaders: map[string]string{ 575 "x-limit-elements-per-property-limit": "3000", 576 "x-limit-elements-per-property-remaining": "3000", 577 "x-limit-max-nested-rules-per-include-limit": "4", 578 "x-limit-max-nested-rules-per-include-remaining": "4", 579 }, 580 responseBody: ` 581 { 582 "accountId": "test_account", 583 "contractId": "test_contract", 584 "groupId": "test_group", 585 "includeId": "inc_123456", 586 "includeVersion": 2, 587 "includeName": "test_include", 588 "includeType": "MICROSERVICES", 589 "etag": "etag", 590 "ruleFormat": "v2020-11-02", 591 "comments": "version comment", 592 "rules": { 593 "name": "default", 594 "comments": "default comment", 595 "criteria": [], 596 "children": [ 597 { 598 "name": "Compress Text Content", 599 "criteria": [ 600 { 601 "name": "contentType", 602 "options": { 603 "matchOperator": "IS_ONE_OF", 604 "matchWildcard": true, 605 "matchCaseSensitive": false, 606 "values": [ 607 "text/html*", 608 "text/css*", 609 "application/x-javascript*" 610 ] 611 } 612 } 613 ], 614 "behaviors": [ 615 { 616 "name": "gzipResponse", 617 "options": { "behavior": "ALWAYS" } 618 } 619 ] 620 } 621 ], 622 "options": { 623 "is_secure": false 624 }, 625 "behaviors": [ 626 { 627 "name": "origin", 628 "options": { 629 "httpPort": 80, 630 "enableTrueClientIp": false, 631 "compress": true, 632 "cacheKeyHostname": "ORIGIN_HOSTNAME", 633 "forwardHostHeader": "REQUEST_HOST_HEADER", 634 "hostname": "origin.test.com", 635 "originType": "CUSTOMER" 636 } 637 }, 638 { 639 "name": "cpCode", 640 "options": { 641 "value": { 642 "id": 12345, 643 "name": "my CP code" 644 } 645 } 646 }, 647 { 648 "name": "matchAdvanced", 649 "options": { 650 "value": { 651 "id": 12345, 652 "name": "my advanced match" 653 } 654 }, 655 "locked": true, 656 "uuid": "fd6a63bc-120a-4891-a5f2-c479765d5553", 657 "templateUuid": "bedbac99-4ce1-43a3-96cc-b84c8cd30176" 658 } 659 ], 660 "customOverride": { 661 "overrideId": "cbo_12345", 662 "name": "mdc" 663 }, 664 "templateUuid": "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 665 "templateLink": "/platformtoolkit/service/ruletemplate/30582260/1?accountId=1-1TJZFB&gid=61726&ck=16.3.1.1", 666 "variables": [ 667 { 668 "name": "VAR_NAME", 669 "value": "default value", 670 "description": "This is a sample Property Manager variable.", 671 "hidden": false, 672 "sensitive": false 673 } 674 ] 675 }, 676 "errors": [ 677 { 678 "type": "https://problems.example.net/papi/v0/validation/attribute_required", 679 "errorLocation": "#/rules/behaviors/0/options/reason", 680 "detail": "The Reason ID option on the Control Access behavior is required." 681 } 682 ] 683 }`, 684 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&dryRun=true&groupId=test_group&validateMode=fast&validateRules=false", 685 expectedResponse: &UpdateIncludeRuleTreeResponse{ 686 Response: Response{ 687 AccountID: "test_account", 688 ContractID: "test_contract", 689 GroupID: "test_group", 690 Errors: []*Error{ 691 { 692 Type: "https://problems.example.net/papi/v0/validation/attribute_required", 693 ErrorLocation: "#/rules/behaviors/0/options/reason", 694 Detail: "The Reason ID option on the Control Access behavior is required.", 695 }, 696 }, 697 }, 698 ResponseHeaders: UpdateIncludeResponseHeaders{ 699 ElementsPerPropertyRemaining: "3000", 700 ElementsPerPropertyTotal: "3000", 701 MaxNestedRulesPerIncludeRemaining: "4", 702 MaxNestedRulesPerIncludeTotal: "4", 703 }, 704 IncludeID: "inc_123456", 705 IncludeVersion: 2, 706 IncludeName: "test_include", 707 IncludeType: IncludeTypeMicroServices, 708 Etag: "etag", 709 RuleFormat: "v2020-11-02", 710 Comments: "version comment", 711 Rules: Rules{ 712 Comments: "default comment", 713 Behaviors: []RuleBehavior{ 714 { 715 Name: "origin", 716 Options: RuleOptionsMap{ 717 "httpPort": float64(80), 718 "enableTrueClientIp": false, 719 "compress": true, 720 "cacheKeyHostname": "ORIGIN_HOSTNAME", 721 "forwardHostHeader": "REQUEST_HOST_HEADER", 722 "hostname": "origin.test.com", 723 "originType": "CUSTOMER", 724 }, 725 }, 726 { 727 Name: "cpCode", 728 Options: RuleOptionsMap{ 729 "value": map[string]interface{}{ 730 "id": float64(12345), 731 "name": "my CP code", 732 }, 733 }, 734 }, 735 { 736 Name: "matchAdvanced", 737 Options: RuleOptionsMap{ 738 "value": map[string]interface{}{ 739 "id": float64(12345), 740 "name": "my advanced match", 741 }, 742 }, 743 Locked: true, 744 UUID: "fd6a63bc-120a-4891-a5f2-c479765d5553", 745 TemplateUuid: "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 746 }, 747 }, 748 Children: []Rules{ 749 { 750 Behaviors: []RuleBehavior{ 751 { 752 Name: "gzipResponse", 753 Options: RuleOptionsMap{ 754 "behavior": "ALWAYS", 755 }, 756 }, 757 }, 758 Criteria: []RuleBehavior{ 759 { 760 Locked: false, 761 Name: "contentType", 762 Options: RuleOptionsMap{ 763 "matchOperator": "IS_ONE_OF", 764 "matchWildcard": true, 765 "matchCaseSensitive": false, 766 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 767 }, 768 }, 769 }, 770 Name: "Compress Text Content", 771 }, 772 }, 773 Criteria: []RuleBehavior{}, 774 Name: "default", 775 Options: RuleOptions{IsSecure: false}, 776 CustomOverride: &RuleCustomOverride{ 777 OverrideID: "cbo_12345", 778 Name: "mdc", 779 }, 780 TemplateUuid: "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 781 TemplateLink: "/platformtoolkit/service/ruletemplate/30582260/1?accountId=1-1TJZFB&gid=61726&ck=16.3.1.1", 782 Variables: []RuleVariable{ 783 { 784 Description: "This is a sample Property Manager variable.", 785 Hidden: false, 786 Name: "VAR_NAME", 787 Sensitive: false, 788 Value: "default value", 789 }, 790 }, 791 }, 792 }, 793 }, 794 "500 Internal Server Error": { 795 params: UpdateIncludeRuleTreeRequest{ 796 IncludeID: "inc_123456", 797 IncludeVersion: 2, 798 ContractID: "test_contract", 799 GroupID: "test_group", 800 DryRun: true, 801 ValidateMode: "fast", 802 ValidateRules: false, 803 Rules: RulesUpdate{ 804 Comments: "version comment", 805 Rules: Rules{ 806 Comments: "default comment", 807 Behaviors: []RuleBehavior{ 808 { 809 Name: "origin", 810 Options: RuleOptionsMap{ 811 "httpPort": float64(80), 812 "enableTrueClientIp": false, 813 "compress": true, 814 "cacheKeyHostname": "ORIGIN_HOSTNAME", 815 "forwardHostHeader": "REQUEST_HOST_HEADER", 816 "hostname": "origin.test.com", 817 "originType": "CUSTOMER", 818 }, 819 }, 820 { 821 Name: "cpCode", 822 Options: RuleOptionsMap{ 823 "value": map[string]interface{}{ 824 "id": float64(12345), 825 "name": "my CP code", 826 }, 827 }, 828 }, 829 }, 830 Children: []Rules{ 831 { 832 Behaviors: []RuleBehavior{ 833 { 834 Name: "gzipResponse", 835 Options: RuleOptionsMap{ 836 "behavior": "ALWAYS", 837 }, 838 }, 839 }, 840 Criteria: []RuleBehavior{ 841 { 842 Locked: false, 843 Name: "contentType", 844 Options: RuleOptionsMap{ 845 "matchOperator": "IS_ONE_OF", 846 "matchWildcard": true, 847 "matchCaseSensitive": false, 848 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 849 }, 850 }, 851 }, 852 Name: "Compress Text Content", 853 }, 854 }, 855 Criteria: []RuleBehavior{}, 856 Name: "default", 857 Options: RuleOptions{IsSecure: false}, 858 CustomOverride: &RuleCustomOverride{ 859 OverrideID: "cbo_12345", 860 Name: "mdc", 861 }, 862 Variables: []RuleVariable{ 863 { 864 Description: "This is a sample Property Manager variable.", 865 Hidden: false, 866 Name: "VAR_NAME", 867 Sensitive: false, 868 Value: "default value", 869 }, 870 }, 871 }, 872 }, 873 }, 874 responseStatus: http.StatusInternalServerError, 875 responseBody: ` 876 { 877 "type": "internal_error", 878 "title": "Internal Server Error", 879 "detail": "Error updating rule tree", 880 "status": 500 881 }`, 882 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&dryRun=true&groupId=test_group&validateMode=fast&validateRules=false", 883 withError: &Error{ 884 Type: "internal_error", 885 Title: "Internal Server Error", 886 Detail: "Error updating rule tree", 887 StatusCode: http.StatusInternalServerError, 888 }, 889 }, 890 "validation error - missing includeId": { 891 params: UpdateIncludeRuleTreeRequest{ 892 IncludeVersion: 2, 893 ContractID: "test_contract", 894 GroupID: "test_group", 895 DryRun: true, 896 ValidateMode: "fast", 897 ValidateRules: false, 898 Rules: RulesUpdate{ 899 Comments: "version comment", 900 Rules: Rules{ 901 Comments: "default comment", 902 Behaviors: []RuleBehavior{ 903 { 904 Name: "origin", 905 Options: RuleOptionsMap{ 906 "httpPort": float64(80), 907 "enableTrueClientIp": false, 908 "compress": true, 909 "cacheKeyHostname": "ORIGIN_HOSTNAME", 910 "forwardHostHeader": "REQUEST_HOST_HEADER", 911 "hostname": "origin.test.com", 912 "originType": "CUSTOMER", 913 }, 914 }, 915 { 916 Name: "cpCode", 917 Options: RuleOptionsMap{ 918 "value": map[string]interface{}{ 919 "id": float64(12345), 920 "name": "my CP code", 921 }, 922 }, 923 }, 924 }, 925 Children: []Rules{ 926 { 927 Behaviors: []RuleBehavior{ 928 { 929 Name: "gzipResponse", 930 Options: RuleOptionsMap{ 931 "behavior": "ALWAYS", 932 }, 933 }, 934 }, 935 Criteria: []RuleBehavior{ 936 { 937 Locked: false, 938 Name: "contentType", 939 Options: RuleOptionsMap{ 940 "matchOperator": "IS_ONE_OF", 941 "matchWildcard": true, 942 "matchCaseSensitive": false, 943 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 944 }, 945 }, 946 }, 947 Name: "Compress Text Content", 948 }, 949 }, 950 Criteria: []RuleBehavior{}, 951 Name: "default", 952 Options: RuleOptions{IsSecure: false}, 953 CustomOverride: &RuleCustomOverride{ 954 OverrideID: "cbo_12345", 955 Name: "mdc", 956 }, 957 Variables: []RuleVariable{ 958 { 959 Description: "This is a sample Property Manager variable.", 960 Hidden: false, 961 Name: "VAR_NAME", 962 Sensitive: false, 963 Value: "default value", 964 }, 965 }, 966 }, 967 }, 968 }, 969 withError: ErrStructValidation, 970 }, 971 "validation error - missing includeVersion": { 972 params: UpdateIncludeRuleTreeRequest{ 973 IncludeID: "inc_123456", 974 ContractID: "test_contract", 975 GroupID: "test_group", 976 DryRun: true, 977 ValidateMode: "fast", 978 ValidateRules: false, 979 Rules: RulesUpdate{ 980 Comments: "version comment", 981 Rules: Rules{ 982 Comments: "default comment", 983 Behaviors: []RuleBehavior{ 984 { 985 Name: "origin", 986 Options: RuleOptionsMap{ 987 "httpPort": float64(80), 988 "enableTrueClientIp": false, 989 "compress": true, 990 "cacheKeyHostname": "ORIGIN_HOSTNAME", 991 "forwardHostHeader": "REQUEST_HOST_HEADER", 992 "hostname": "origin.test.com", 993 "originType": "CUSTOMER", 994 }, 995 }, 996 { 997 Name: "cpCode", 998 Options: RuleOptionsMap{ 999 "value": map[string]interface{}{ 1000 "id": float64(12345), 1001 "name": "my CP code", 1002 }, 1003 }, 1004 }, 1005 }, 1006 Children: []Rules{ 1007 { 1008 Behaviors: []RuleBehavior{ 1009 { 1010 Name: "gzipResponse", 1011 Options: RuleOptionsMap{ 1012 "behavior": "ALWAYS", 1013 }, 1014 }, 1015 }, 1016 Criteria: []RuleBehavior{ 1017 { 1018 Locked: false, 1019 Name: "contentType", 1020 Options: RuleOptionsMap{ 1021 "matchOperator": "IS_ONE_OF", 1022 "matchWildcard": true, 1023 "matchCaseSensitive": false, 1024 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1025 }, 1026 }, 1027 }, 1028 Name: "Compress Text Content", 1029 }, 1030 }, 1031 Criteria: []RuleBehavior{}, 1032 Name: "default", 1033 Options: RuleOptions{IsSecure: false}, 1034 CustomOverride: &RuleCustomOverride{ 1035 OverrideID: "cbo_12345", 1036 Name: "mdc", 1037 }, 1038 Variables: []RuleVariable{ 1039 { 1040 Description: "This is a sample Property Manager variable.", 1041 Hidden: false, 1042 Name: "VAR_NAME", 1043 Sensitive: false, 1044 Value: "default value", 1045 }, 1046 }, 1047 }, 1048 }, 1049 }, 1050 withError: ErrStructValidation, 1051 }, 1052 "validation error - missing contractId": { 1053 params: UpdateIncludeRuleTreeRequest{ 1054 IncludeID: "inc_123456", 1055 IncludeVersion: 2, 1056 GroupID: "test_group", 1057 DryRun: true, 1058 ValidateMode: "fast", 1059 ValidateRules: false, 1060 Rules: RulesUpdate{ 1061 Comments: "version comment", 1062 Rules: Rules{ 1063 Comments: "default comment", 1064 Behaviors: []RuleBehavior{ 1065 { 1066 Name: "origin", 1067 Options: RuleOptionsMap{ 1068 "httpPort": float64(80), 1069 "enableTrueClientIp": false, 1070 "compress": true, 1071 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1072 "forwardHostHeader": "REQUEST_HOST_HEADER", 1073 "hostname": "origin.test.com", 1074 "originType": "CUSTOMER", 1075 }, 1076 }, 1077 { 1078 Name: "cpCode", 1079 Options: RuleOptionsMap{ 1080 "value": map[string]interface{}{ 1081 "id": float64(12345), 1082 "name": "my CP code", 1083 }, 1084 }, 1085 }, 1086 }, 1087 Children: []Rules{ 1088 { 1089 Behaviors: []RuleBehavior{ 1090 { 1091 Name: "gzipResponse", 1092 Options: RuleOptionsMap{ 1093 "behavior": "ALWAYS", 1094 }, 1095 }, 1096 }, 1097 Criteria: []RuleBehavior{ 1098 { 1099 Locked: false, 1100 Name: "contentType", 1101 Options: RuleOptionsMap{ 1102 "matchOperator": "IS_ONE_OF", 1103 "matchWildcard": true, 1104 "matchCaseSensitive": false, 1105 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1106 }, 1107 }, 1108 }, 1109 Name: "Compress Text Content", 1110 }, 1111 }, 1112 Criteria: []RuleBehavior{}, 1113 Name: "default", 1114 Options: RuleOptions{IsSecure: false}, 1115 CustomOverride: &RuleCustomOverride{ 1116 OverrideID: "cbo_12345", 1117 Name: "mdc", 1118 }, 1119 Variables: []RuleVariable{ 1120 { 1121 Description: "This is a sample Property Manager variable.", 1122 Hidden: false, 1123 Name: "VAR_NAME", 1124 Sensitive: false, 1125 Value: "default value", 1126 }, 1127 }, 1128 }, 1129 }, 1130 }, 1131 withError: ErrStructValidation, 1132 }, 1133 "validation error - missing groupId": { 1134 params: UpdateIncludeRuleTreeRequest{ 1135 IncludeID: "inc_123456", 1136 IncludeVersion: 2, 1137 ContractID: "test_contract", 1138 DryRun: true, 1139 ValidateMode: "fast", 1140 ValidateRules: false, 1141 Rules: RulesUpdate{ 1142 Comments: "version comment", 1143 Rules: Rules{ 1144 Comments: "default comment", 1145 Behaviors: []RuleBehavior{ 1146 { 1147 Name: "origin", 1148 Options: RuleOptionsMap{ 1149 "httpPort": float64(80), 1150 "enableTrueClientIp": false, 1151 "compress": true, 1152 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1153 "forwardHostHeader": "REQUEST_HOST_HEADER", 1154 "hostname": "origin.test.com", 1155 "originType": "CUSTOMER", 1156 }, 1157 }, 1158 { 1159 Name: "cpCode", 1160 Options: RuleOptionsMap{ 1161 "value": map[string]interface{}{ 1162 "id": float64(12345), 1163 "name": "my CP code", 1164 }, 1165 }, 1166 }, 1167 }, 1168 Children: []Rules{ 1169 { 1170 Behaviors: []RuleBehavior{ 1171 { 1172 Name: "gzipResponse", 1173 Options: RuleOptionsMap{ 1174 "behavior": "ALWAYS", 1175 }, 1176 }, 1177 }, 1178 Criteria: []RuleBehavior{ 1179 { 1180 Locked: false, 1181 Name: "contentType", 1182 Options: RuleOptionsMap{ 1183 "matchOperator": "IS_ONE_OF", 1184 "matchWildcard": true, 1185 "matchCaseSensitive": false, 1186 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1187 }, 1188 }, 1189 }, 1190 Name: "Compress Text Content", 1191 }, 1192 }, 1193 Criteria: []RuleBehavior{}, 1194 Name: "default", 1195 Options: RuleOptions{IsSecure: false}, 1196 CustomOverride: &RuleCustomOverride{ 1197 OverrideID: "cbo_12345", 1198 Name: "mdc", 1199 }, 1200 Variables: []RuleVariable{ 1201 { 1202 Description: "This is a sample Property Manager variable.", 1203 Hidden: false, 1204 Name: "VAR_NAME", 1205 Sensitive: false, 1206 Value: "default value", 1207 }, 1208 }, 1209 }, 1210 }, 1211 }, 1212 withError: ErrStructValidation, 1213 }, 1214 "validation error - invalid validation mode": { 1215 params: UpdateIncludeRuleTreeRequest{ 1216 IncludeID: "inc_123456", 1217 IncludeVersion: 2, 1218 ContractID: "test_contract", 1219 GroupID: "test_group", 1220 DryRun: true, 1221 ValidateMode: "test", 1222 ValidateRules: false, 1223 Rules: RulesUpdate{ 1224 Comments: "version comment", 1225 Rules: Rules{ 1226 Comments: "default comment", 1227 Behaviors: []RuleBehavior{ 1228 { 1229 Name: "origin", 1230 Options: RuleOptionsMap{ 1231 "httpPort": float64(80), 1232 "enableTrueClientIp": false, 1233 "compress": true, 1234 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1235 "forwardHostHeader": "REQUEST_HOST_HEADER", 1236 "hostname": "origin.test.com", 1237 "originType": "CUSTOMER", 1238 }, 1239 }, 1240 { 1241 Name: "cpCode", 1242 Options: RuleOptionsMap{ 1243 "value": map[string]interface{}{ 1244 "id": float64(12345), 1245 "name": "my CP code", 1246 }, 1247 }, 1248 }, 1249 }, 1250 Children: []Rules{ 1251 { 1252 Behaviors: []RuleBehavior{ 1253 { 1254 Name: "gzipResponse", 1255 Options: RuleOptionsMap{ 1256 "behavior": "ALWAYS", 1257 }, 1258 }, 1259 }, 1260 Criteria: []RuleBehavior{ 1261 { 1262 Locked: false, 1263 Name: "contentType", 1264 Options: RuleOptionsMap{ 1265 "matchOperator": "IS_ONE_OF", 1266 "matchWildcard": true, 1267 "matchCaseSensitive": false, 1268 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1269 }, 1270 }, 1271 }, 1272 Name: "Compress Text Content", 1273 }, 1274 }, 1275 Criteria: []RuleBehavior{}, 1276 Name: "default", 1277 Options: RuleOptions{IsSecure: false}, 1278 CustomOverride: &RuleCustomOverride{ 1279 OverrideID: "cbo_12345", 1280 Name: "mdc", 1281 }, 1282 Variables: []RuleVariable{ 1283 { 1284 Description: "This is a sample Property Manager variable.", 1285 Hidden: false, 1286 Name: "VAR_NAME", 1287 Sensitive: false, 1288 Value: "default value", 1289 }, 1290 }, 1291 }, 1292 }, 1293 }, 1294 withError: ErrStructValidation, 1295 }, 1296 } 1297 1298 for name, test := range tests { 1299 t.Run(name, func(t *testing.T) { 1300 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1301 assert.Equal(t, test.expectedPath, r.URL.String()) 1302 assert.Equal(t, http.MethodPut, r.Method) 1303 1304 if len(test.responseHeaders) > 0 { 1305 for header, value := range test.responseHeaders { 1306 w.Header().Set(header, value) 1307 } 1308 } 1309 w.WriteHeader(test.responseStatus) 1310 _, err := w.Write([]byte(test.responseBody)) 1311 assert.NoError(t, err) 1312 })) 1313 client := mockAPIClient(t, mockServer) 1314 result, err := client.UpdateIncludeRuleTree(context.Background(), test.params) 1315 if test.withError != nil { 1316 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 1317 return 1318 } 1319 require.NoError(t, err) 1320 assert.Equal(t, test.expectedResponse, result) 1321 }) 1322 } 1323 }