github.com/dhaiducek/policy-generator-plugin@v1.99.99/internal/plugin_config_test.go (about) 1 // Copyright Contributors to the Open Cluster Management project 2 package internal 3 4 import ( 5 "fmt" 6 "os" 7 "path" 8 "path/filepath" 9 "testing" 10 11 "github.com/dhaiducek/policy-generator-plugin/internal/types" 12 ) 13 14 func createConfigMap(t *testing.T, tmpDir, filename string) { 15 t.Helper() 16 17 manifestsPath := path.Join(tmpDir, filename) 18 yamlContent := ` 19 apiVersion: v1 20 kind: ConfigMap 21 metadata: 22 name: my-configmap 23 data: 24 game.properties: enemies=potato 25 ` 26 27 err := os.WriteFile(manifestsPath, []byte(yamlContent), 0o666) 28 if err != nil { 29 t.Fatalf("Failed to write %s", manifestsPath) 30 } 31 } 32 33 func createIamPolicyManifest(t *testing.T, tmpDir, filename string) { 34 t.Helper() 35 36 manifestsPath := path.Join(tmpDir, filename) 37 yamlContent := ` 38 apiVersion: policy.open-cluster-management.io/v1 39 kind: IamPolicy 40 metadata: 41 name: policy-limitclusteradmin-example 42 spec: 43 severity: medium 44 namespaceSelector: 45 include: ["*"] 46 exclude: ["kube-*", "openshift-*"] 47 remediationAction: enforce 48 maxClusterRoleBindingUsers: 5 49 ` 50 51 err := os.WriteFile(manifestsPath, []byte(yamlContent), 0o666) 52 if err != nil { 53 t.Fatalf("Failed to write %s", manifestsPath) 54 } 55 } 56 57 func TestConfig(t *testing.T) { 58 t.Parallel() 59 tmpDir := t.TempDir() 60 createConfigMap(t, tmpDir, "configmap.yaml") 61 configMapPath := path.Join(tmpDir, "configmap.yaml") 62 createConfigMap(t, tmpDir, "configmap2.yaml") 63 configMapPath2 := path.Join(tmpDir, "configmap.yaml") 64 createConfigMap(t, tmpDir, "configmap3.yaml") 65 configMapPath3 := path.Join(tmpDir, "configmap.yaml") 66 exampleConfig := fmt.Sprintf( 67 ` 68 apiVersion: policy.open-cluster-management.io/v1 69 kind: PolicyGenerator 70 metadata: 71 name: policy-generator-name 72 placementBindingDefaults: 73 name: my-placement-binding 74 policyDefaults: 75 controls: 76 - PR.DS-1 Data-at-rest 77 metadataComplianceType: musthave 78 namespace: my-policies 79 namespaceSelector: 80 include: 81 - default 82 exclude: 83 - my-protected-ns 84 placement: 85 clusterSelectors: 86 cloud: red hat 87 remediationAction: enforce 88 severity: medium 89 policies: 90 - name: policy-app-config 91 disabled: false 92 manifests: 93 - path: %s 94 namespaceSelector: 95 include: 96 - app-ns 97 remediationAction: inform 98 - name: policy-app-config2 99 metadataComplianceType: mustonlyhave 100 disabled: true 101 manifests: 102 - path: %s 103 metadataComplianceType: musthave 104 - path: %s 105 placement: 106 clusterSelectors: 107 cloud: weather 108 `, 109 configMapPath, 110 configMapPath2, 111 configMapPath3, 112 ) 113 114 p := Plugin{} 115 116 err := p.Config([]byte(exampleConfig), tmpDir) 117 if err != nil { 118 t.Fatal(err.Error()) 119 } 120 121 assertEqual(t, p.Metadata.Name, "policy-generator-name") 122 assertEqual(t, p.PlacementBindingDefaults.Name, "my-placement-binding") 123 assertReflectEqual(t, p.PolicyDefaults.Categories, []string{"CM Configuration Management"}) 124 assertEqual(t, p.PolicyDefaults.ComplianceType, "musthave") 125 assertReflectEqual(t, p.PolicyDefaults.Controls, []string{"PR.DS-1 Data-at-rest"}) 126 assertEqual(t, p.PolicyDefaults.Namespace, "my-policies") 127 128 expectedNsSelector := types.NamespaceSelector{ 129 Exclude: []string{"my-protected-ns"}, Include: []string{"default"}, 130 } 131 132 assertReflectEqual(t, p.PolicyDefaults.NamespaceSelector, expectedNsSelector) 133 assertEqual(t, p.PolicyDefaults.Placement.PlacementRulePath, "") 134 assertEqual(t, p.PolicyDefaults.Placement.PlacementPath, "") 135 assertReflectEqual( 136 t, 137 p.PolicyDefaults.Placement.ClusterSelectors, 138 map[string]interface{}{"cloud": "red hat"}, 139 ) 140 assertEqual(t, len(p.PolicyDefaults.Placement.LabelSelector), 0) 141 assertEqual(t, p.PolicyDefaults.RemediationAction, "enforce") 142 assertEqual(t, p.PolicyDefaults.Severity, "medium") 143 assertReflectEqual(t, p.PolicyDefaults.Standards, []string{"NIST SP 800-53"}) 144 assertEqual(t, len(p.Policies), 2) 145 146 policy1 := p.Policies[0] 147 assertReflectEqual(t, policy1.Categories, []string{"CM Configuration Management"}) 148 assertEqual(t, policy1.ComplianceType, "musthave") 149 assertEqual(t, policy1.MetadataComplianceType, "musthave") 150 assertReflectEqual(t, policy1.Controls, []string{"PR.DS-1 Data-at-rest"}) 151 assertEqual(t, policy1.Disabled, false) 152 assertEqual(t, len(policy1.Manifests), 1) 153 assertEqual(t, policy1.Manifests[0].Path, configMapPath) 154 assertEqual(t, policy1.Manifests[0].MetadataComplianceType, "musthave") 155 assertEqual(t, policy1.Name, "policy-app-config") 156 157 p1ExpectedNsSelector := types.NamespaceSelector{ 158 Exclude: nil, Include: []string{"app-ns"}, 159 } 160 161 assertReflectEqual(t, policy1.NamespaceSelector, p1ExpectedNsSelector) 162 assertReflectEqual( 163 t, 164 policy1.Placement.ClusterSelectors, 165 map[string]interface{}{"cloud": "red hat"}, 166 ) 167 assertEqual(t, policy1.RemediationAction, "inform") 168 assertEqual(t, policy1.Severity, "medium") 169 assertReflectEqual(t, policy1.Standards, []string{"NIST SP 800-53"}) 170 171 policy2 := p.Policies[1] 172 assertReflectEqual(t, policy2.Categories, []string{"CM Configuration Management"}) 173 assertEqual(t, policy2.ComplianceType, "musthave") 174 assertEqual(t, policy2.MetadataComplianceType, "mustonlyhave") 175 assertReflectEqual(t, policy2.Controls, []string{"PR.DS-1 Data-at-rest"}) 176 assertEqual(t, policy2.Disabled, true) 177 assertEqual(t, len(policy2.Manifests), 2) 178 assertEqual(t, policy2.Manifests[0].Path, configMapPath2) 179 assertEqual(t, policy2.Manifests[0].MetadataComplianceType, "musthave") 180 assertEqual(t, policy2.Manifests[1].Path, configMapPath3) 181 assertEqual(t, policy2.Manifests[1].MetadataComplianceType, "mustonlyhave") 182 assertEqual(t, policy2.Name, "policy-app-config2") 183 assertReflectEqual(t, policy2.NamespaceSelector, expectedNsSelector) 184 assertReflectEqual( 185 t, 186 policy2.Placement.ClusterSelectors, 187 map[string]interface{}{"cloud": "weather"}, 188 ) 189 assertEqual(t, policy2.RemediationAction, "enforce") 190 assertEqual(t, policy2.Severity, "medium") 191 assertReflectEqual(t, policy2.Standards, []string{"NIST SP 800-53"}) 192 } 193 194 func TestConfigAllDefaults(t *testing.T) { 195 t.Parallel() 196 tmpDir := t.TempDir() 197 createConfigMap(t, tmpDir, "configmap.yaml") 198 configMapPath := path.Join(tmpDir, "configmap.yaml") 199 defaultsConfig := fmt.Sprintf( 200 ` 201 apiVersion: policy.open-cluster-management.io/v1 202 kind: PolicyGenerator 203 metadata: 204 name: policy-generator-name 205 policyDefaults: 206 namespace: my-policies 207 policies: 208 - name: policy-app-config 209 manifests: 210 - path: %s 211 `, 212 configMapPath, 213 ) 214 p := Plugin{} 215 216 err := p.Config([]byte(defaultsConfig), tmpDir) 217 if err != nil { 218 t.Fatal(err.Error()) 219 } 220 221 assertEqual(t, p.Metadata.Name, "policy-generator-name") 222 assertEqual(t, p.PlacementBindingDefaults.Name, "") 223 assertReflectEqual(t, p.PolicyDefaults.Categories, []string{"CM Configuration Management"}) 224 assertEqual(t, p.PolicyDefaults.Disabled, false) 225 assertEqual(t, p.PolicyDefaults.ComplianceType, "musthave") 226 assertEqual(t, p.PolicyDefaults.MetadataComplianceType, "") 227 assertReflectEqual(t, p.PolicyDefaults.Controls, []string{"CM-2 Baseline Configuration"}) 228 assertEqual(t, p.PolicyDefaults.Namespace, "my-policies") 229 230 expectedNsSelector := types.NamespaceSelector{Exclude: nil, Include: nil} 231 232 assertEqual(t, p.PolicyDefaults.InformGatekeeperPolicies, true) 233 assertEqual(t, p.PolicyDefaults.InformKyvernoPolicies, true) 234 assertReflectEqual(t, p.PolicyDefaults.NamespaceSelector, expectedNsSelector) 235 assertEqual(t, p.PolicyDefaults.Placement.PlacementRulePath, "") 236 assertEqual(t, len(p.PolicyDefaults.Placement.ClusterSelectors), 0) 237 assertEqual(t, p.PolicyDefaults.Placement.PlacementPath, "") 238 assertEqual(t, len(p.PolicyDefaults.Placement.LabelSelector), 0) 239 assertEqual(t, p.PolicyDefaults.RemediationAction, "inform") 240 assertEqual(t, p.PolicyDefaults.Severity, "low") 241 assertReflectEqual(t, p.PolicyDefaults.Standards, []string{"NIST SP 800-53"}) 242 assertEqual(t, len(p.Policies), 1) 243 244 policy := p.Policies[0] 245 assertReflectEqual(t, policy.Categories, []string{"CM Configuration Management"}) 246 assertEqual(t, policy.Disabled, false) 247 assertEqual(t, policy.ComplianceType, "musthave") 248 assertEqual(t, policy.MetadataComplianceType, "") 249 assertReflectEqual(t, policy.Controls, []string{"CM-2 Baseline Configuration"}) 250 assertEqual(t, policy.Disabled, false) 251 assertEqual(t, len(policy.Manifests), 1) 252 assertEqual(t, policy.Manifests[0].Path, configMapPath) 253 assertEqual(t, policy.Name, "policy-app-config") 254 assertReflectEqual(t, policy.NamespaceSelector, expectedNsSelector) 255 assertEqual(t, len(policy.Placement.ClusterSelectors), 0) 256 assertEqual(t, policy.Placement.PlacementRulePath, "") 257 assertEqual(t, len(policy.Placement.LabelSelector), 0) 258 assertEqual(t, policy.Placement.PlacementPath, "") 259 assertEqual(t, policy.RemediationAction, "inform") 260 assertEqual(t, policy.Severity, "low") 261 assertReflectEqual(t, policy.Standards, []string{"NIST SP 800-53"}) 262 assertEqual(t, policy.InformGatekeeperPolicies, true) 263 assertEqual(t, policy.InformKyvernoPolicies, true) 264 } 265 266 func TestConfigNoNamespace(t *testing.T) { 267 t.Parallel() 268 const config = ` 269 apiVersion: policy.open-cluster-management.io/v1 270 kind: PolicyGenerator 271 metadata: 272 name: policy-generator-name 273 policies: 274 - name: policy-app-config 275 manifests: 276 - path: input/configmap.yaml 277 ` 278 279 p := Plugin{} 280 281 err := p.Config([]byte(config), "") 282 if err == nil { 283 t.Fatal("Expected an error but did not get one") 284 } 285 286 expected := "policyDefaults.namespace is empty but it must be set" 287 assertEqual(t, err.Error(), expected) 288 } 289 290 func TestConfigInvalidPolicyName(t *testing.T) { 291 t.Parallel() 292 tmpDir := t.TempDir() 293 createConfigMap(t, tmpDir, "configmap.yaml") 294 configMapPath := path.Join(tmpDir, "configmap.yaml") 295 policyNS := "my-policies-my-policies-my-policies" 296 policyName := "policy-app-config-policy-app-config-policy-app-config" 297 defaultsConfig := fmt.Sprintf( 298 ` 299 apiVersion: policy.open-cluster-management.io/v1 300 kind: PolicyGenerator 301 metadata: 302 name: policy-generator-name 303 policyDefaults: 304 namespace: %s 305 policies: 306 - name: %s 307 manifests: 308 - path: %s 309 `, 310 policyNS, policyName, configMapPath, 311 ) 312 313 p := Plugin{} 314 315 err := p.Config([]byte(defaultsConfig), tmpDir) 316 if err == nil { 317 t.Fatal("Expected an error but did not get one") 318 } 319 320 expected := fmt.Sprintf( 321 "the policy namespace and name cannot be more than 63 characters: %s.%s", policyNS, policyName, 322 ) 323 assertEqual(t, err.Error(), expected) 324 } 325 326 func TestConfigNoPolicies(t *testing.T) { 327 t.Parallel() 328 const config = ` 329 apiVersion: policy.open-cluster-management.io/v1 330 kind: PolicyGenerator 331 metadata: 332 name: policy-generator-name 333 policyDefaults: 334 namespace: my-policies 335 ` 336 337 p := Plugin{} 338 339 err := p.Config([]byte(config), "") 340 if err == nil { 341 t.Fatal("Expected an error but did not get one") 342 } 343 344 expected := "policies is empty but it must be set" 345 assertEqual(t, err.Error(), expected) 346 } 347 348 func TestConfigInvalidPath(t *testing.T) { 349 t.Parallel() 350 tmpDir := t.TempDir() 351 createConfigMap(t, tmpDir, "configmap.yaml") 352 configMapPath := path.Join(tmpDir, "configmap.yaml") 353 policyNS := "my-policies" 354 policyName := "policy-app-config" 355 defaultsConfig := fmt.Sprintf( 356 ` 357 apiVersion: policy.open-cluster-management.io/v1 358 kind: PolicyGenerator 359 metadata: 360 name: policy-generator-name 361 policyDefaults: 362 namespace: %s 363 policies: 364 - name: %s 365 manifests: 366 - path: %s 367 `, 368 policyNS, policyName, configMapPath, 369 ) 370 371 p := Plugin{} 372 // Provide a base directory that isn't in the same directory tree as tmpDir. 373 baseDir := t.TempDir() 374 375 err := p.Config([]byte(defaultsConfig), baseDir) 376 if err == nil { 377 t.Fatal("Expected an error but did not get one") 378 } 379 380 expected := fmt.Sprintf( 381 "the manifest path %s is not in the same directory tree as the kustomization.yaml file", configMapPath, 382 ) 383 assertEqual(t, err.Error(), expected) 384 } 385 386 func TestConfigMultiplePlacementsClusterSelectorAndPlRPath(t *testing.T) { 387 t.Parallel() 388 tmpDir := t.TempDir() 389 createConfigMap(t, tmpDir, "configmap.yaml") 390 config := fmt.Sprintf(` 391 apiVersion: policy.open-cluster-management.io/v1 392 kind: PolicyGenerator 393 metadata: 394 name: policy-generator-name 395 policyDefaults: 396 namespace: my-policies 397 policies: 398 - name: policy-app-config 399 placement: 400 clusterSelectors: 401 cloud: red hat 402 placementRulePath: path/to/plr.yaml 403 manifests: 404 - path: %s 405 `, 406 path.Join(tmpDir, "configmap.yaml"), 407 ) 408 p := Plugin{} 409 410 err := p.Config([]byte(config), tmpDir) 411 if err == nil { 412 t.Fatal("Expected an error but did not get one") 413 } 414 415 expected := "policy policy-app-config must specify only one of " + 416 "placement selector, placement path, or placement name" 417 assertEqual(t, err.Error(), expected) 418 } 419 420 func TestConfigMultiplePlacementsClusterSelectorAndPlRName(t *testing.T) { 421 t.Parallel() 422 tmpDir := t.TempDir() 423 createConfigMap(t, tmpDir, "configmap.yaml") 424 config := fmt.Sprintf(` 425 apiVersion: policy.open-cluster-management.io/v1 426 kind: PolicyGenerator 427 metadata: 428 name: policy-generator-name 429 policyDefaults: 430 namespace: my-policies 431 policies: 432 - name: policy-app-config 433 placement: 434 clusterSelectors: 435 cloud: red hat 436 placementRuleName: plrexistingname 437 manifests: 438 - path: %s 439 `, 440 path.Join(tmpDir, "configmap.yaml"), 441 ) 442 p := Plugin{} 443 444 err := p.Config([]byte(config), tmpDir) 445 if err == nil { 446 t.Fatal("Expected an error but did not get one") 447 } 448 449 expected := "policy policy-app-config must specify only one of " + 450 "placement selector, placement path, or placement name" 451 assertEqual(t, err.Error(), expected) 452 } 453 454 func TestConfigMultiplePlacementsLabelSelectorAndPlRPath(t *testing.T) { 455 t.Parallel() 456 tmpDir := t.TempDir() 457 createConfigMap(t, tmpDir, "configmap.yaml") 458 config := fmt.Sprintf(` 459 apiVersion: policy.open-cluster-management.io/v1 460 kind: PolicyGenerator 461 metadata: 462 name: policy-generator-name 463 policyDefaults: 464 namespace: my-policies 465 policies: 466 - name: policy-app-config 467 placement: 468 labelSelector: 469 cloud: red hat 470 placementRulePath: path/to/plr.yaml 471 manifests: 472 - path: %s 473 `, 474 path.Join(tmpDir, "configmap.yaml"), 475 ) 476 p := Plugin{} 477 478 err := p.Config([]byte(config), tmpDir) 479 if err == nil { 480 t.Fatal("Expected an error but did not get one") 481 } 482 483 expected := "policy policy-app-config must specify only one of " + 484 "placement selector, placement path, or placement name" 485 assertEqual(t, err.Error(), expected) 486 } 487 488 func TestConfigMultiplePlacementsLabelSelectorAndPlRName(t *testing.T) { 489 t.Parallel() 490 tmpDir := t.TempDir() 491 createConfigMap(t, tmpDir, "configmap.yaml") 492 config := fmt.Sprintf(` 493 apiVersion: policy.open-cluster-management.io/v1 494 kind: PolicyGenerator 495 metadata: 496 name: policy-generator-name 497 policyDefaults: 498 namespace: my-policies 499 policies: 500 - name: policy-app-config 501 placement: 502 labelSelector: 503 cloud: red hat 504 placementRuleName: plrexistingname 505 manifests: 506 - path: %s 507 `, 508 path.Join(tmpDir, "configmap.yaml"), 509 ) 510 p := Plugin{} 511 512 err := p.Config([]byte(config), tmpDir) 513 if err == nil { 514 t.Fatal("Expected an error but did not get one") 515 } 516 517 expected := "policy policy-app-config must specify only one of " + 518 "placement selector, placement path, or placement name" 519 assertEqual(t, err.Error(), expected) 520 } 521 522 func TestConfigMultiplePlacementsLabelSelectorAndPlPath(t *testing.T) { 523 t.Parallel() 524 tmpDir := t.TempDir() 525 createConfigMap(t, tmpDir, "configmap.yaml") 526 config := fmt.Sprintf(` 527 apiVersion: policy.open-cluster-management.io/v1 528 kind: PolicyGenerator 529 metadata: 530 name: policy-generator-name 531 policyDefaults: 532 namespace: my-policies 533 policies: 534 - name: policy-app-config 535 placement: 536 labelSelector: 537 cloud: red hat 538 placementPath: path/to/pl.yaml 539 manifests: 540 - path: %s 541 `, 542 path.Join(tmpDir, "configmap.yaml"), 543 ) 544 p := Plugin{} 545 546 err := p.Config([]byte(config), tmpDir) 547 if err == nil { 548 t.Fatal("Expected an error but did not get one") 549 } 550 551 expected := "policy policy-app-config must specify only one of " + 552 "placement selector, placement path, or placement name" 553 assertEqual(t, err.Error(), expected) 554 } 555 556 func TestConfigMultiplePlacementsLabelSelectorAndPlName(t *testing.T) { 557 t.Parallel() 558 tmpDir := t.TempDir() 559 createConfigMap(t, tmpDir, "configmap.yaml") 560 config := fmt.Sprintf(` 561 apiVersion: policy.open-cluster-management.io/v1 562 kind: PolicyGenerator 563 metadata: 564 name: policy-generator-name 565 policyDefaults: 566 namespace: my-policies 567 policies: 568 - name: policy-app-config 569 placement: 570 labelSelector: 571 cloud: red hat 572 placementName: plexistingname 573 manifests: 574 - path: %s 575 `, 576 path.Join(tmpDir, "configmap.yaml"), 577 ) 578 p := Plugin{} 579 580 err := p.Config([]byte(config), tmpDir) 581 if err == nil { 582 t.Fatal("Expected an error but did not get one") 583 } 584 585 expected := "policy policy-app-config must specify only one of " + 586 "placement selector, placement path, or placement name" 587 assertEqual(t, err.Error(), expected) 588 } 589 590 func TestConfigMultipleDefaultPlacementLabels(t *testing.T) { 591 t.Parallel() 592 const config = ` 593 apiVersion: policy.open-cluster-management.io/v1 594 kind: PolicyGenerator 595 metadata: 596 name: policy-generator-name 597 policyDefaults: 598 namespace: my-policies 599 placement: 600 clusterSelectors: 601 cloud: red hat 602 labelSelector: 603 cloud: red hat 604 policies: 605 - name: policy-app-config 606 manifests: 607 - path: input/configmap.yaml 608 ` 609 610 p := Plugin{} 611 612 err := p.Config([]byte(config), "") 613 if err == nil { 614 t.Fatal("Expected an error but did not get one") 615 } 616 617 expected := "policyDefaults must provide only one of " + 618 "placement.labelSelector or placement.clusterSelectors" 619 assertEqual(t, err.Error(), expected) 620 } 621 622 func TestConfigMultiplePolicyPlacementLabels(t *testing.T) { 623 t.Parallel() 624 tmpDir := t.TempDir() 625 createConfigMap(t, tmpDir, "configmap.yaml") 626 config := fmt.Sprintf(` 627 apiVersion: policy.open-cluster-management.io/v1 628 kind: PolicyGenerator 629 metadata: 630 name: policy-generator-name 631 policyDefaults: 632 namespace: my-policies 633 policies: 634 - name: policy-app-config 635 placement: 636 clusterSelectors: 637 cloud: red hat 638 labelSelector: 639 cloud: red hat 640 manifests: 641 - path: %s 642 `, 643 path.Join(tmpDir, "configmap.yaml"), 644 ) 645 646 p := Plugin{} 647 648 err := p.Config([]byte(config), tmpDir) 649 if err == nil { 650 t.Fatal("Expected an error but did not get one") 651 } 652 653 expected := "policy policy-app-config must provide only one of " + 654 "placement.labelSelector or placement.clusterSelectors" 655 assertEqual(t, err.Error(), expected) 656 } 657 658 func TestConfigMultipleDefaultPlacementPaths(t *testing.T) { 659 t.Parallel() 660 const config = ` 661 apiVersion: policy.open-cluster-management.io/v1 662 kind: PolicyGenerator 663 metadata: 664 name: policy-generator-name 665 policyDefaults: 666 namespace: my-policies 667 placement: 668 placementPath: path/to/pl.yaml 669 placementRulePath: path/to/plr.yaml 670 policies: 671 - name: policy-app-config 672 placement: 673 clusterSelectors: 674 cloud: red hat 675 placementRulePath: path/to/plr.yaml 676 manifests: 677 - path: input/configmap.yaml 678 ` 679 680 p := Plugin{} 681 682 err := p.Config([]byte(config), "") 683 if err == nil { 684 t.Fatal("Expected an error but did not get one") 685 } 686 687 expected := "policyDefaults must provide only one of " + 688 "placement.placementPath or placement.placementRulePath" 689 assertEqual(t, err.Error(), expected) 690 } 691 692 func TestConfigMultipleDefaultPlacementName(t *testing.T) { 693 t.Parallel() 694 const config = ` 695 apiVersion: policy.open-cluster-management.io/v1 696 kind: PolicyGenerator 697 metadata: 698 name: policy-generator-name 699 policyDefaults: 700 namespace: my-policies 701 placement: 702 placementName: plExistingName 703 placementRuleName: plrExistingName 704 policies: 705 - name: policy-app-config 706 placement: 707 clusterSelectors: 708 cloud: red hat 709 placementRuleName: plrExistingName 710 manifests: 711 - path: input/configmap.yaml 712 ` 713 714 p := Plugin{} 715 716 err := p.Config([]byte(config), "") 717 if err == nil { 718 t.Fatal("Expected an error but did not get one") 719 } 720 721 expected := "policyDefaults must provide only one of " + 722 "placement.placementName or placement.placementRuleName" 723 assertEqual(t, err.Error(), expected) 724 } 725 726 func TestConfigMultipleDefaultAndPolicyPlacements(t *testing.T) { 727 t.Parallel() 728 tmpDir := t.TempDir() 729 plFileName := "plr.yaml" 730 cmFileName := "configmap.yaml" 731 732 createConfigMap(t, tmpDir, cmFileName) 733 734 err := os.WriteFile(path.Join(tmpDir, plFileName), []byte{}, 0o666) 735 if err != nil { 736 t.Fatalf("Failed to write %s", plFileName) 737 } 738 739 config := fmt.Sprintf(` 740 apiVersion: policy.open-cluster-management.io/v1 741 kind: PolicyGenerator 742 metadata: 743 name: policy-generator-name 744 policyDefaults: 745 namespace: my-policies 746 placement: 747 placementPath: %s 748 policies: 749 - name: policy-app-config 750 placement: 751 clusterSelectors: 752 cloud: red hat 753 manifests: 754 - path: %s 755 `, 756 path.Join(tmpDir, plFileName), 757 path.Join(tmpDir, cmFileName), 758 ) 759 p := Plugin{} 760 761 err = p.Config([]byte(config), tmpDir) 762 if err == nil { 763 t.Fatal("Expected an error but did not get one") 764 } 765 766 expected := "policy policy-app-config must specify only one of " + 767 "placement selector, placement path, or placement name" 768 assertEqual(t, err.Error(), expected) 769 } 770 771 func TestConfigMultipleDefaultAndPolicyPlacementNames(t *testing.T) { 772 t.Parallel() 773 tmpDir := t.TempDir() 774 createConfigMap(t, tmpDir, "configmap.yaml") 775 config := fmt.Sprintf(` 776 apiVersion: policy.open-cluster-management.io/v1 777 kind: PolicyGenerator 778 metadata: 779 name: policy-generator-name 780 policyDefaults: 781 namespace: my-policies 782 placement: 783 placementName: plexistingname 784 policies: 785 - name: policy-app-config 786 placement: 787 clusterSelectors: 788 cloud: red hat 789 manifests: 790 - path: %s 791 `, 792 path.Join(tmpDir, "configmap.yaml"), 793 ) 794 795 p := Plugin{} 796 797 err := p.Config([]byte(config), tmpDir) 798 if err == nil { 799 t.Fatal("Expected an error but did not get one") 800 } 801 802 expected := "policy policy-app-config must specify only one of " + 803 "placement selector, placement path, or placement name" 804 assertEqual(t, err.Error(), expected) 805 } 806 807 func TestConfigPlacementInvalidMixture(t *testing.T) { 808 t.Parallel() 809 tmpDir := t.TempDir() 810 createConfigMap(t, tmpDir, "configmap.yaml") 811 config := fmt.Sprintf(` 812 apiVersion: policy.open-cluster-management.io/v1 813 kind: PolicyGenerator 814 metadata: 815 name: policy-generator-name 816 policyDefaults: 817 namespace: my-policies 818 policies: 819 - name: policy-app-config-1 820 placement: 821 clusterSelectors: 822 cloud: red hat 823 manifests: 824 - path: %s 825 - name: policy-app-config-2 826 placement: 827 labelSelector: 828 cloud: red hat 829 manifests: 830 - path: %s 831 `, 832 path.Join(tmpDir, "configmap.yaml"), path.Join(tmpDir, "configmap.yaml"), 833 ) 834 p := Plugin{} 835 836 err := p.Config([]byte(config), tmpDir) 837 if err == nil { 838 t.Fatal("Expected an error but did not get one") 839 } 840 841 expected := "may not use a mix of Placement and PlacementRule for " + 842 "policies and policysets; found 1 Placement and 1 PlacementRule" 843 assertEqual(t, err.Error(), expected) 844 } 845 846 func TestConfigPlacementPathNotFound(t *testing.T) { 847 t.Parallel() 848 tmpDir := t.TempDir() 849 createConfigMap(t, tmpDir, "configmap.yaml") 850 config := fmt.Sprintf(` 851 apiVersion: policy.open-cluster-management.io/v1 852 kind: PolicyGenerator 853 metadata: 854 name: policy-generator-name 855 policyDefaults: 856 namespace: my-policies 857 policies: 858 - name: policy-app-config 859 placement: 860 placementPath: path/to/pl.yaml 861 manifests: 862 - path: %s 863 `, 864 path.Join(tmpDir, "configmap.yaml"), 865 ) 866 p := Plugin{} 867 868 err := p.Config([]byte(config), tmpDir) 869 if err == nil { 870 t.Fatal("Expected an error but did not get one") 871 } 872 873 expected := "policy policy-app-config placement.placementPath could not read the path path/to/pl.yaml" 874 assertEqual(t, err.Error(), expected) 875 } 876 877 func TestConfigDuplicateNames(t *testing.T) { 878 t.Parallel() 879 tmpDir := t.TempDir() 880 createConfigMap(t, tmpDir, "configmap.yaml") 881 createConfigMap(t, tmpDir, "configmap2.yaml") 882 config := fmt.Sprintf(` 883 apiVersion: policy.open-cluster-management.io/v1 884 kind: PolicyGenerator 885 metadata: 886 name: policy-generator-name 887 placementBindingDefaults: 888 name: my-pb 889 policyDefaults: 890 namespace: my-policies 891 policies: 892 - name: policy-app-config 893 manifests: 894 - path: %s 895 - name: policy-app-config 896 manifests: 897 - path: %s 898 `, 899 path.Join(tmpDir, "configmap.yaml"), 900 path.Join(tmpDir, "configmap2.yaml"), 901 ) 902 p := Plugin{} 903 904 err := p.Config([]byte(config), tmpDir) 905 if err == nil { 906 t.Fatal("Expected an error but did not get one") 907 } 908 909 expected := "each policy must have a unique name set, " + 910 "but found a duplicate name: policy-app-config" 911 assertEqual(t, err.Error(), expected) 912 } 913 914 func TestConfigInvalidEvalInterval(t *testing.T) { 915 t.Parallel() 916 tmpDir := t.TempDir() 917 createConfigMap(t, tmpDir, "configmap.yaml") 918 919 tests := []struct { 920 // Individual values can't be used for compliant/noncompliant since an empty string means 921 // to not inherit from the policy defaults. 922 defaultEvalInterval string 923 policyEvalInterval string 924 manifestEvalInterval string 925 expectedMsg string 926 }{ 927 { 928 `{"compliant": "not a duration"}`, 929 "", 930 "", 931 `the policy policy-app has an invalid policy.evaluationInterval.compliant value: time: invalid duration ` + 932 `"not a duration"`, 933 }, 934 { 935 `{"noncompliant": "not a duration"}`, 936 "", 937 "", 938 `the policy policy-app has an invalid policy.evaluationInterval.noncompliant value: time: invalid ` + 939 `duration "not a duration"`, 940 }, 941 { 942 "", 943 `{"compliant": "not a duration"}`, 944 "", 945 `the policy policy-app has an invalid policy.evaluationInterval.compliant value: time: invalid duration ` + 946 `"not a duration"`, 947 }, 948 { 949 "", 950 `{"noncompliant": "not a duration"}`, 951 "", 952 `the policy policy-app has an invalid policy.evaluationInterval.noncompliant value: time: invalid ` + 953 `duration "not a duration"`, 954 }, 955 { 956 "", 957 "", 958 `{"compliant": "not a duration"}`, 959 `the policy policy-app has the evaluationInterval value set on manifest[0] but consolidateManifests is ` + 960 `true`, 961 }, 962 { 963 "", 964 "", 965 `{"noncompliant": "not a duration"}`, 966 `the policy policy-app has the evaluationInterval value set on manifest[0] but consolidateManifests is ` + 967 `true`, 968 }, 969 { 970 "", 971 `{"compliant": "10d5h1m"}`, 972 "", 973 `the policy policy-app has an invalid policy.evaluationInterval.compliant value: time: unknown unit "d" ` + 974 `in duration "10d5h1m"`, 975 }, 976 { 977 "", 978 `{"noncompliant": "1w2d"}`, 979 "", 980 `the policy policy-app has an invalid policy.evaluationInterval.noncompliant value: time: unknown unit ` + 981 `"w" in duration "1w2d"`, 982 }, 983 } 984 985 for _, test := range tests { 986 test := test 987 988 t.Run( 989 fmt.Sprintf("expected=%s", test.expectedMsg), 990 func(t *testing.T) { 991 t.Parallel() 992 config := fmt.Sprintf(` 993 apiVersion: policy.open-cluster-management.io/v1 994 kind: PolicyGenerator 995 metadata: 996 name: policy-generator-name 997 policyDefaults: 998 namespace: my-policies 999 evaluationInterval: %s 1000 policies: 1001 - name: policy-app 1002 evaluationInterval: %s 1003 manifests: 1004 - path: %s 1005 evaluationInterval: %s 1006 `, 1007 test.defaultEvalInterval, 1008 test.policyEvalInterval, 1009 path.Join(tmpDir, "configmap.yaml"), 1010 test.manifestEvalInterval, 1011 ) 1012 1013 p := Plugin{} 1014 err := p.Config([]byte(config), tmpDir) 1015 if err == nil { 1016 t.Fatal("Expected an error but did not get one") 1017 } 1018 1019 assertEqual(t, err.Error(), test.expectedMsg) 1020 }, 1021 ) 1022 } 1023 } 1024 1025 func TestConfigInvalidManifestKey(t *testing.T) { 1026 t.Parallel() 1027 tmpDir := t.TempDir() 1028 createConfigMap(t, tmpDir, "configmap.yaml") 1029 1030 tests := map[string]struct { 1031 // Individual values can't be used for compliant/noncompliant since an empty string means 1032 // to not inherit from the policy defaults. 1033 keyName string 1034 defaultKey string 1035 policyKey string 1036 manifestKey string 1037 expectedMsg string 1038 }{ 1039 "pruneObjectBehavior specified in manifest": { 1040 "pruneObjectBehavior", 1041 "", 1042 "", 1043 "None", 1044 `the policy policy-app has the pruneObjectBehavior value set` + 1045 ` on manifest[0] but consolidateManifests is true`, 1046 }, 1047 "namespaceSelector specified in manifest": { 1048 "namespaceSelector", 1049 "", 1050 "", 1051 `{"include": ["test"]}`, 1052 `the policy policy-app has the namespaceSelector value set` + 1053 ` on manifest[0] but consolidateManifests is true`, 1054 }, 1055 "remediationAction specified in manifest": { 1056 "remediationAction", 1057 "", 1058 "", 1059 "enforce", 1060 `the policy policy-app has the remediationAction value set` + 1061 ` on manifest[0] but consolidateManifests is true`, 1062 }, 1063 "severity specified in manifest": { 1064 "severity", 1065 "", 1066 "", 1067 "critical", 1068 `the policy policy-app has the severity value set` + 1069 ` on manifest[0] but consolidateManifests is true`, 1070 }, 1071 } 1072 1073 for testName, test := range tests { 1074 test := test 1075 1076 t.Run( 1077 testName, 1078 func(t *testing.T) { 1079 t.Parallel() 1080 config := fmt.Sprintf(` 1081 apiVersion: policy.open-cluster-management.io/v1 1082 kind: PolicyGenerator 1083 metadata: 1084 name: policy-generator-name 1085 policyDefaults: 1086 namespace: my-policies 1087 %s: %s 1088 policies: 1089 - name: policy-app 1090 %s: %s 1091 manifests: 1092 - path: %s 1093 %s: %s 1094 `, 1095 test.keyName, test.defaultKey, 1096 test.keyName, test.policyKey, 1097 path.Join(tmpDir, "configmap.yaml"), 1098 test.keyName, test.manifestKey, 1099 ) 1100 1101 p := Plugin{} 1102 err := p.Config([]byte(config), tmpDir) 1103 if err == nil { 1104 t.Fatal("Expected an error but did not get one") 1105 } 1106 1107 assertEqual(t, err.Error(), test.expectedMsg) 1108 }, 1109 ) 1110 } 1111 } 1112 1113 func TestConfigNoManifests(t *testing.T) { 1114 t.Parallel() 1115 const config = ` 1116 apiVersion: policy.open-cluster-management.io/v1 1117 kind: PolicyGenerator 1118 metadata: 1119 name: policy-generator-name 1120 policyDefaults: 1121 namespace: my-policies 1122 policies: 1123 - name: policy-app-config 1124 ` 1125 1126 p := Plugin{} 1127 1128 err := p.Config([]byte(config), "") 1129 if err == nil { 1130 t.Fatal("Expected an error but did not get one") 1131 } 1132 1133 expected := "each policy must have at least one manifest, " + 1134 "but found none in policy policy-app-config" 1135 assertEqual(t, err.Error(), expected) 1136 } 1137 1138 func TestConfigManifestNotFound(t *testing.T) { 1139 t.Parallel() 1140 tmpDir := t.TempDir() 1141 manifestPath := path.Join(tmpDir, "configmap.yaml") 1142 config := fmt.Sprintf( 1143 ` 1144 apiVersion: policy.open-cluster-management.io/v1 1145 kind: PolicyGenerator 1146 metadata: 1147 name: policy-generator-name 1148 policyDefaults: 1149 namespace: my-policies 1150 policies: 1151 - name: policy-app-config 1152 manifests: 1153 - path: %s 1154 `, 1155 manifestPath, 1156 ) 1157 p := Plugin{} 1158 1159 err := p.Config([]byte(config), tmpDir) 1160 if err == nil { 1161 t.Fatal("Expected an error but did not get one") 1162 } 1163 1164 expected := fmt.Sprintf( 1165 "could not read the manifest path %s in policy policy-app-config", manifestPath, 1166 ) 1167 assertEqual(t, err.Error(), expected) 1168 } 1169 1170 func TestConfigNoPolicyName(t *testing.T) { 1171 t.Parallel() 1172 tmpDir := t.TempDir() 1173 createConfigMap(t, tmpDir, "configmap.yaml") 1174 config := fmt.Sprintf( 1175 ` 1176 apiVersion: policy.open-cluster-management.io/v1 1177 kind: PolicyGenerator 1178 metadata: 1179 name: policy-generator-name 1180 policyDefaults: 1181 namespace: my-policies 1182 policies: 1183 - manifests: 1184 - path: %s 1185 `, 1186 path.Join(tmpDir, "configmap.yaml"), 1187 ) 1188 p := Plugin{} 1189 1190 err := p.Config([]byte(config), tmpDir) 1191 if err == nil { 1192 t.Fatal("Expected an error but did not get one") 1193 } 1194 1195 expected := "each policy must have a name set, but did not find a name at policy array index 0" 1196 assertEqual(t, err.Error(), expected) 1197 } 1198 1199 func TestConfigPlrNotFound(t *testing.T) { 1200 t.Parallel() 1201 tmpDir := t.TempDir() 1202 createConfigMap(t, tmpDir, "configmap.yaml") 1203 plrPath := path.Join(tmpDir, "plr.yaml") 1204 config := fmt.Sprintf( 1205 ` 1206 apiVersion: policy.open-cluster-management.io/v1 1207 kind: PolicyGenerator 1208 metadata: 1209 name: policy-generator-name 1210 policyDefaults: 1211 namespace: my-policies 1212 placement: 1213 placementRulePath: %s 1214 policies: 1215 - name: policy-app-config 1216 manifests: 1217 - path: %s 1218 `, 1219 plrPath, 1220 path.Join(tmpDir, "configmap.yaml"), 1221 ) 1222 p := Plugin{} 1223 1224 err := p.Config([]byte(config), tmpDir) 1225 if err == nil { 1226 t.Fatal("Expected an error but did not get one") 1227 } 1228 1229 expected := fmt.Sprintf("policyDefaults placement.placementRulePath could not read the path %s", plrPath) 1230 assertEqual(t, err.Error(), expected) 1231 } 1232 1233 func TestPolicySetConfig(t *testing.T) { 1234 t.Parallel() 1235 tmpDir := t.TempDir() 1236 createConfigMap(t, tmpDir, "configmap.yaml") 1237 1238 testCases := []testCase{ 1239 { 1240 name: "policySet must have a name set", 1241 setupFunc: func(p *Plugin) { 1242 p.PolicySets = []types.PolicySetConfig{ 1243 { 1244 PolicySetOptions: types.PolicySetOptions{ 1245 Placement: types.PlacementConfig{ 1246 Name: "policyset-placement", 1247 ClusterSelectors: map[string]interface{}{"my": "app"}, 1248 }, 1249 }, 1250 }, 1251 } 1252 }, 1253 expectedErrMsg: "each policySet must have a name set, but did not find a name at policySet array index 0", 1254 }, 1255 { 1256 name: "policySet must be unique", 1257 setupFunc: func(p *Plugin) { 1258 p.PolicySets = []types.PolicySetConfig{ 1259 { 1260 Name: "my-policyset", 1261 }, 1262 { 1263 Name: "my-policyset", 1264 }, 1265 } 1266 }, 1267 expectedErrMsg: "each policySet must have a unique name set, but found a duplicate name: my-policyset", 1268 }, 1269 { 1270 name: "policySet must provide only one of placementRulePath or placementPath", 1271 setupFunc: func(p *Plugin) { 1272 p.PolicySets = []types.PolicySetConfig{ 1273 { 1274 Name: "my-policyset", 1275 PolicySetOptions: types.PolicySetOptions{ 1276 Placement: types.PlacementConfig{ 1277 PlacementPath: "../config/plc.yaml", 1278 PlacementRulePath: "../config/plr.yaml", 1279 }, 1280 }, 1281 }, 1282 } 1283 }, 1284 expectedErrMsg: "policySet my-policyset must provide only one of " + 1285 "placement.placementPath or placement.placementRulePath", 1286 }, 1287 { 1288 name: "policySet must provide only one of placementRuleName or placementName", 1289 setupFunc: func(p *Plugin) { 1290 p.PolicySets = []types.PolicySetConfig{ 1291 { 1292 Name: "my-policyset", 1293 PolicySetOptions: types.PolicySetOptions{ 1294 Placement: types.PlacementConfig{ 1295 PlacementName: "plExistingName", 1296 PlacementRuleName: "plrExistingName", 1297 }, 1298 }, 1299 }, 1300 } 1301 }, 1302 expectedErrMsg: "policySet my-policyset must provide only one of " + 1303 "placement.placementName or placement.placementRuleName", 1304 }, 1305 { 1306 name: "policySet must provide only one of labelSelector or clusterSelectors", 1307 setupFunc: func(p *Plugin) { 1308 p.PolicySets = []types.PolicySetConfig{ 1309 { 1310 Name: "my-policyset", 1311 PolicySetOptions: types.PolicySetOptions{ 1312 Placement: types.PlacementConfig{ 1313 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1314 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1315 }, 1316 }, 1317 }, 1318 } 1319 }, 1320 expectedErrMsg: "policySet my-policyset must provide only one of placement.labelSelector or " + 1321 "placement.clusterSelectors", 1322 }, 1323 { 1324 name: "policySet may not specify a cluster selector and placement path together", 1325 setupFunc: func(p *Plugin) { 1326 p.PolicySets = []types.PolicySetConfig{ 1327 { 1328 Name: "my-policyset", 1329 PolicySetOptions: types.PolicySetOptions{ 1330 Placement: types.PlacementConfig{ 1331 PlacementPath: "../config/plc.yaml", 1332 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1333 }, 1334 }, 1335 }, 1336 } 1337 }, 1338 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1339 "placement name", 1340 }, 1341 { 1342 name: "policySet may not specify a cluster selector and placement name together", 1343 setupFunc: func(p *Plugin) { 1344 p.PolicySets = []types.PolicySetConfig{ 1345 { 1346 Name: "my-policyset", 1347 PolicySetOptions: types.PolicySetOptions{ 1348 Placement: types.PlacementConfig{ 1349 PlacementName: "plexistingname", 1350 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1351 }, 1352 }, 1353 }, 1354 } 1355 }, 1356 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1357 "placement name", 1358 }, 1359 { 1360 name: "policySet may not specify a label selector and placement path together", 1361 setupFunc: func(p *Plugin) { 1362 p.PolicySets = []types.PolicySetConfig{ 1363 { 1364 Name: "my-policyset", 1365 PolicySetOptions: types.PolicySetOptions{ 1366 Placement: types.PlacementConfig{ 1367 PlacementPath: "../config/plc.yaml", 1368 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1369 }, 1370 }, 1371 }, 1372 } 1373 }, 1374 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1375 "placement name", 1376 }, 1377 { 1378 name: "policySet may not specify a label selector and placement name together", 1379 setupFunc: func(p *Plugin) { 1380 p.PolicySets = []types.PolicySetConfig{ 1381 { 1382 Name: "my-policyset", 1383 PolicySetOptions: types.PolicySetOptions{ 1384 Placement: types.PlacementConfig{ 1385 PlacementName: "plexistingname", 1386 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1387 }, 1388 }, 1389 }, 1390 } 1391 }, 1392 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1393 "placement name", 1394 }, 1395 { 1396 name: "policySet may not specify a cluster selector and placementrule path together", 1397 setupFunc: func(p *Plugin) { 1398 p.PolicySets = []types.PolicySetConfig{ 1399 { 1400 Name: "my-policyset", 1401 PolicySetOptions: types.PolicySetOptions{ 1402 Placement: types.PlacementConfig{ 1403 PlacementRulePath: "../config/plc.yaml", 1404 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1405 }, 1406 }, 1407 }, 1408 } 1409 }, 1410 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1411 "placement name", 1412 }, 1413 { 1414 name: "policySet may not specify a cluster selector and placementrule name together", 1415 setupFunc: func(p *Plugin) { 1416 p.PolicySets = []types.PolicySetConfig{ 1417 { 1418 Name: "my-policyset", 1419 PolicySetOptions: types.PolicySetOptions{ 1420 Placement: types.PlacementConfig{ 1421 PlacementRuleName: "plrexistingname", 1422 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1423 }, 1424 }, 1425 }, 1426 } 1427 }, 1428 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1429 "placement name", 1430 }, 1431 { 1432 name: "policySet may not specify a label selector and placementrule path together", 1433 setupFunc: func(p *Plugin) { 1434 p.PolicySets = []types.PolicySetConfig{ 1435 { 1436 Name: "my-policyset", 1437 PolicySetOptions: types.PolicySetOptions{ 1438 Placement: types.PlacementConfig{ 1439 PlacementRulePath: "../config/plc.yaml", 1440 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1441 }, 1442 }, 1443 }, 1444 } 1445 }, 1446 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1447 "placement name", 1448 }, 1449 { 1450 name: "policySet may not specify a label selector and placementrule name together", 1451 setupFunc: func(p *Plugin) { 1452 p.PolicySets = []types.PolicySetConfig{ 1453 { 1454 Name: "my-policyset", 1455 PolicySetOptions: types.PolicySetOptions{ 1456 Placement: types.PlacementConfig{ 1457 PlacementRuleName: "plrexistingname", 1458 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1459 }, 1460 }, 1461 }, 1462 } 1463 }, 1464 expectedErrMsg: "policySet my-policyset must specify only one of placement selector, placement path, or " + 1465 "placement name", 1466 }, 1467 { 1468 name: "policySet placementrule path not resolvable", 1469 setupFunc: func(p *Plugin) { 1470 p.PolicySets = []types.PolicySetConfig{ 1471 { 1472 Name: "my-policyset", 1473 PolicySetOptions: types.PolicySetOptions{ 1474 Placement: types.PlacementConfig{ 1475 PlacementRulePath: "../config/plc.yaml", 1476 }, 1477 }, 1478 }, 1479 } 1480 }, 1481 expectedErrMsg: "policySet my-policyset placement.placementRulePath " + 1482 "could not read the path ../config/plc.yaml", 1483 }, 1484 { 1485 name: "policySet placement path not resolvable", 1486 setupFunc: func(p *Plugin) { 1487 p.PolicySets = []types.PolicySetConfig{ 1488 { 1489 Name: "my-policyset", 1490 PolicySetOptions: types.PolicySetOptions{ 1491 Placement: types.PlacementConfig{ 1492 PlacementPath: "../config/plc.yaml", 1493 }, 1494 }, 1495 }, 1496 } 1497 }, 1498 expectedErrMsg: "policySet my-policyset placement.placementPath could not read the path ../config/plc.yaml", 1499 }, 1500 { 1501 name: "Placement and PlacementRule can't be mixed", 1502 setupFunc: func(p *Plugin) { 1503 p.Policies[0].Placement = types.PlacementConfig{ 1504 LabelSelector: map[string]interface{}{"cloud": "red hat"}, 1505 } 1506 p.PolicySets = []types.PolicySetConfig{ 1507 { 1508 Name: "my-policyset", 1509 PolicySetOptions: types.PolicySetOptions{ 1510 Placement: types.PlacementConfig{ 1511 ClusterSelectors: map[string]interface{}{"cloud": "red hat"}, 1512 }, 1513 }, 1514 }, 1515 } 1516 }, 1517 expectedErrMsg: "may not use a mix of Placement and PlacementRule for policies and policysets; found 1 " + 1518 "Placement and 1 PlacementRule", 1519 }, 1520 } 1521 1522 for _, tc := range testCases { 1523 tc := tc // capture range variable 1524 t.Run(tc.name, func(t *testing.T) { 1525 t.Parallel() 1526 p := Plugin{} 1527 var err error 1528 p.baseDirectory, err = filepath.EvalSymlinks(tmpDir) 1529 if err != nil { 1530 t.Fatal(err.Error()) 1531 } 1532 p.PlacementBindingDefaults.Name = "my-placement-binding" 1533 p.PolicyDefaults.Placement.Name = "my-placement-rule" 1534 p.PolicyDefaults.Namespace = "my-policies" 1535 policyConf1 := types.PolicyConfig{ 1536 Name: "policy-app-config", 1537 Manifests: []types.Manifest{ 1538 { 1539 Path: path.Join(tmpDir, "configmap.yaml"), 1540 }, 1541 }, 1542 } 1543 policyConf2 := types.PolicyConfig{ 1544 Name: "policy-app-config2", 1545 Manifests: []types.Manifest{ 1546 { 1547 Path: path.Join(tmpDir, "configmap.yaml"), 1548 }, 1549 }, 1550 } 1551 p.Policies = append(p.Policies, policyConf1, policyConf2) 1552 tc.setupFunc(&p) 1553 p.applyDefaults(map[string]interface{}{}) 1554 err = p.assertValidConfig() 1555 if err == nil { 1556 t.Fatal("Expected an error but did not get one") 1557 } 1558 assertEqual(t, err.Error(), tc.expectedErrMsg) 1559 }) 1560 } 1561 } 1562 1563 func TestDisabled(t *testing.T) { 1564 t.Parallel() 1565 tmpDir := t.TempDir() 1566 createConfigMap(t, tmpDir, "configmap.yaml") 1567 configMapPath := path.Join(tmpDir, "configmap.yaml") 1568 defaultsConfig := fmt.Sprintf( 1569 ` 1570 apiVersion: policy.open-cluster-management.io/v1 1571 kind: PolicyGenerator 1572 metadata: 1573 name: policy-generator-name 1574 policyDefaults: 1575 namespace: my-policies 1576 disabled: true 1577 policies: 1578 - name: policy-app-config 1579 disabled: false 1580 manifests: 1581 - path: %s 1582 namespaceSelector: 1583 include: 1584 - app-ns 1585 remediationAction: inform 1586 - name: policy-app-config2 1587 manifests: 1588 - path: %s 1589 `, 1590 configMapPath, 1591 configMapPath, 1592 ) 1593 p := Plugin{} 1594 1595 err := p.Config([]byte(defaultsConfig), tmpDir) 1596 if err != nil { 1597 t.Fatal(err.Error()) 1598 } 1599 1600 assertEqual(t, p.PolicyDefaults.Disabled, true) 1601 1602 enabledPolicy := p.Policies[0] 1603 assertEqual(t, enabledPolicy.Disabled, false) 1604 1605 disabledPolicy := p.Policies[1] 1606 assertEqual(t, disabledPolicy.Disabled, true) 1607 } 1608 1609 func TestConflictingPlacementSelectors(t *testing.T) { 1610 t.Parallel() 1611 tmpDir := t.TempDir() 1612 createConfigMap(t, tmpDir, "configmap.yaml") 1613 configMapPath := path.Join(tmpDir, "configmap.yaml") 1614 policyNS := "my-policies" 1615 policyName := "policy-app" 1616 defaultsConfig := fmt.Sprintf( 1617 ` 1618 apiVersion: policy.open-cluster-management.io/v1 1619 kind: PolicyGenerator 1620 metadata: 1621 name: policy-generator-name 1622 policyDefaults: 1623 namespace: %s 1624 placement: 1625 labelSelector: 1626 matchExpressions: 1627 - key: cloud 1628 operator: In 1629 values: 1630 - red hat 1631 - hello 1632 cloud: red hat 1633 clusterID: 1234-5678 1634 policies: 1635 - name: %s 1636 manifests: 1637 - path: %s 1638 `, 1639 policyNS, policyName, configMapPath, 1640 ) 1641 1642 p := Plugin{} 1643 1644 err := p.Config([]byte(defaultsConfig), tmpDir) 1645 if err == nil { 1646 t.Fatal("Expected an error but did not get one") 1647 } 1648 1649 expected := "policyDefaults placement has invalid selectors: " + 1650 "the input is not a valid label selector or key-value label matching map" 1651 assertEqual(t, err.Error(), expected) 1652 }