pulumi/pkg/resource/analyzer/config_test.go
CyrusNajmabadi 66bd3f4aa8
Breaking changes due to Feature 2.0 work
* Make `async:true` the default for `invoke` calls (#3750)

* Switch away from native grpc impl. (#3728)

* Remove usage of the 'deasync' library from @pulumi/pulumi. (#3752)

* Only retry as long as we get unavailable back.  Anything else continues. (#3769)

* Handle all errors for now. (#3781)


* Do not assume --yes was present when using pulumi in non-interactive mode (#3793)

* Upgrade all paths for sdk and pkg to v2

* Backport C# invoke classes and other recent gen changes (#4288)

Adjust C# generation

* Replace IDeployment with a sealed class (#4318)

Replace IDeployment with a sealed class

* .NET: default to args subtype rather than Args.Empty (#4320)

* Adding system namespace for Dotnet code gen

This is required for using Obsolute attributes for deprecations

```
Iam/InstanceProfile.cs(142,10): error CS0246: The type or namespace name 'ObsoleteAttribute' could not be found (are you missing a using directive or an assembly reference?) [/Users/stack72/code/go/src/github.com/pulumi/pulumi-aws/sdk/dotnet/Pulumi.Aws.csproj]
Iam/InstanceProfile.cs(142,10): error CS0246: The type or namespace name 'Obsolete' could not be found (are you missing a using directive or an assembly reference?) [/Users/stack72/code/go/src/github.com/pulumi/pulumi-aws/sdk/dotnet/Pulumi.Aws.csproj]
```

* Fix the nullability of config type properties in C# codegen (#4379)
2020-04-14 09:30:25 +01:00

1193 lines
28 KiB
Go

// Copyright 2016-2020, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package analyzer
import (
"encoding/json"
"fmt"
"testing"
"github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
"github.com/pulumi/pulumi/sdk/v2/go/common/resource/plugin"
"github.com/stretchr/testify/assert"
)
type JSONTestCaseSuccess struct {
JSON string
Expected map[string]plugin.AnalyzerPolicyConfig
}
var success = []JSONTestCaseSuccess{
{
JSON: `{}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{},
},
{
JSON: `{"foo":{"enforcementLevel":"advisory"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
EnforcementLevel: apitype.Advisory,
},
},
},
{
JSON: `{"foo":{"enforcementLevel":"mandatory"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
EnforcementLevel: apitype.Mandatory,
},
},
},
{
JSON: `{"foo":{"enforcementLevel":"advisory","bar":"blah"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
EnforcementLevel: apitype.Advisory,
Properties: map[string]interface{}{
"bar": "blah",
},
},
},
},
{
JSON: `{"foo":{}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{},
},
{
JSON: `{"foo":{"bar":"blah"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
Properties: map[string]interface{}{
"bar": "blah",
},
},
},
},
{
JSON: `{"policy1":{"foo":"one"},"policy2":{"foo":"two"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy1": {
Properties: map[string]interface{}{
"foo": "one",
},
},
"policy2": {
Properties: map[string]interface{}{
"foo": "two",
},
},
},
},
}
func TestParsePolicyPackConfigFromAPISuccess(t *testing.T) {
for _, test := range success {
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
config := make(map[string]*json.RawMessage)
unmarshalErr := json.Unmarshal([]byte(test.JSON), &config)
assert.NoError(t, unmarshalErr)
result, err := ParsePolicyPackConfigFromAPI(config)
assert.NoError(t, err)
assert.Equal(t, test.Expected, result)
})
}
}
func TestParsePolicyPackConfigSuccess(t *testing.T) {
tests := []JSONTestCaseSuccess{
{
JSON: "",
Expected: nil,
},
{
JSON: " ",
Expected: nil,
},
{
JSON: "\t",
Expected: nil,
},
{
JSON: "\n",
Expected: nil,
},
{
JSON: `{"foo":"advisory"}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
EnforcementLevel: apitype.Advisory,
},
},
},
{
JSON: `{"foo":"mandatory"}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"foo": {
EnforcementLevel: apitype.Mandatory,
},
},
},
{
JSON: `{"all":"mandatory","policy1":{"foo":"one"},"policy2":{"foo":"two"}}`,
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: apitype.Mandatory,
},
"policy1": {
Properties: map[string]interface{}{
"foo": "one",
},
},
"policy2": {
Properties: map[string]interface{}{
"foo": "two",
},
},
},
},
}
tests = append(tests, success...)
for _, test := range tests {
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
result, err := parsePolicyPackConfig([]byte(test.JSON))
assert.NoError(t, err)
assert.Equal(t, test.Expected, result)
})
}
}
func TestParsePolicyPackConfigFail(t *testing.T) {
tests := []string{
`{"foo":[]}`,
`{"foo":null}`,
`{"foo":undefined}`,
`{"foo":0}`,
`{"foo":true}`,
`{"foo":false}`,
`{"foo":""}`,
`{"foo":"bar"}`,
`{"foo":{"enforcementLevel":[]}}`,
`{"foo":{"enforcementLevel":null}}`,
`{"foo":{"enforcementLevel":undefined}}`,
`{"foo":{"enforcementLevel":0}}`,
`{"foo":{"enforcementLevel":true}}`,
`{"foo":{"enforcementLevel":false}}`,
`{"foo":{"enforcementLevel":{}}}`,
`{"foo":{"enforcementLevel":""}}`,
`{"foo":{"enforcementLevel":"bar"}}`,
}
for _, test := range tests {
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
result, err := parsePolicyPackConfig([]byte(test))
assert.Nil(t, result)
assert.Error(t, err)
})
}
}
func TestExtractEnforcementLevelSuccess(t *testing.T) {
tests := []struct {
Properties map[string]interface{}
ExpectedEnforcementLevel apitype.EnforcementLevel
ExpectedProperties map[string]interface{}
}{
{
Properties: map[string]interface{}{},
ExpectedEnforcementLevel: "",
ExpectedProperties: map[string]interface{}{},
},
{
Properties: map[string]interface{}{
"enforcementLevel": "advisory",
},
ExpectedEnforcementLevel: "advisory",
ExpectedProperties: map[string]interface{}{},
},
{
Properties: map[string]interface{}{
"enforcementLevel": "mandatory",
},
ExpectedEnforcementLevel: "mandatory",
ExpectedProperties: map[string]interface{}{},
},
{
Properties: map[string]interface{}{
"enforcementLevel": "disabled",
},
ExpectedEnforcementLevel: "disabled",
ExpectedProperties: map[string]interface{}{},
},
{
Properties: map[string]interface{}{
"enforcementLevel": "advisory",
"foo": "bar",
"blah": 1,
},
ExpectedEnforcementLevel: "advisory",
ExpectedProperties: map[string]interface{}{
"foo": "bar",
"blah": 1,
},
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
result, err := extractEnforcementLevel(test.Properties)
assert.NoError(t, err)
assert.Equal(t, test.ExpectedEnforcementLevel, result)
assert.Equal(t, test.ExpectedProperties, test.Properties)
})
}
}
func TestExtractEnforcementLevelFail(t *testing.T) {
tests := []struct {
Properties map[string]interface{}
ExpectedError string
}{
{
Properties: map[string]interface{}{
"enforcementLevel": "",
},
ExpectedError: `"" is not a valid enforcement level`,
},
{
Properties: map[string]interface{}{
"enforcementLevel": "foo",
},
ExpectedError: `"foo" is not a valid enforcement level`,
},
{
Properties: map[string]interface{}{
"enforcementLevel": nil,
},
ExpectedError: `<nil> is not a valid enforcement level; must be a string`,
},
{
Properties: map[string]interface{}{
"enforcementLevel": 1,
},
ExpectedError: `1 is not a valid enforcement level; must be a string`,
},
{
Properties: map[string]interface{}{
"enforcementLevel": []string{},
},
ExpectedError: `[] is not a valid enforcement level; must be a string`,
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%v", test), func(t *testing.T) {
result, err := extractEnforcementLevel(test.Properties)
assert.Equal(t, apitype.EnforcementLevel(""), result)
assert.Error(t, err)
if test.ExpectedError != "" {
assert.Equal(t, test.ExpectedError, err.Error())
}
})
}
}
func TestReconcilePolicyPackConfigSuccess(t *testing.T) {
tests := []struct {
Test string
Policies []plugin.AnalyzerPolicyInfo
Config map[string]plugin.AnalyzerPolicyConfig
Expected map[string]plugin.AnalyzerPolicyConfig
}{
{
Test: "Default enforcement level used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "mandatory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "mandatory",
},
},
},
{
Test: "Specified enforcement level used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "mandatory",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
},
{
Test: "Enforcement level from 'all' used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "disabled",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
"policy": {
EnforcementLevel: "mandatory",
},
},
},
{
Test: "Enforcement level from 'all' used with multiple policies",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy-one",
EnforcementLevel: "advisory",
},
{
Name: "policy-two",
EnforcementLevel: "mandatory",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "disabled",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "disabled",
},
"policy-one": {
EnforcementLevel: "disabled",
},
"policy-two": {
EnforcementLevel: "disabled",
},
},
},
{
Test: "Specified config enforcement level used even if 'all' is present",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "disabled",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
"policy": {
EnforcementLevel: "advisory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
"policy": {
EnforcementLevel: "advisory",
},
},
},
{
Test: "Default string value specified in schema used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"default": "bar",
},
},
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "bar",
},
},
},
},
{
Test: "Default number value specified in schema used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "number",
"default": float64(42),
},
},
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(42),
},
},
},
},
{
Test: "Specified config value overrides default value",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"default": "bar",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "overridden",
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "overridden",
},
},
},
},
{
Test: "Default value specified in schema for required field used",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"default": "bar",
},
},
Required: []string{"foo"},
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "bar",
},
},
},
},
{
Test: "type: string",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "bar",
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "bar",
},
},
},
},
{
Test: "type: number (int)",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "number",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(42),
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(42),
},
},
},
},
{
Test: "type: number (float)",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "number",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(3.14),
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(3.14),
},
},
},
},
{
Test: "type: integer",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "integer",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(42),
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": float64(42),
},
},
},
},
{
Test: "type: boolean true",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "boolean",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": true,
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": true,
},
},
},
},
{
Test: "type: boolean false",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "boolean",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": false,
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": false,
},
},
},
},
{
Test: "type: object",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "object",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": map[string]interface{}{"bar": "baz"},
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": map[string]interface{}{"bar": "baz"},
},
},
},
},
{
Test: "type: array",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "array",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": []string{"a", "b", "c"},
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": []string{"a", "b", "c"},
},
},
},
},
{
Test: "type: null",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "null",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": nil,
},
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": nil,
},
},
},
},
}
for _, test := range tests {
t.Run(test.Test, func(t *testing.T) {
result, validationErrors, err := ReconcilePolicyPackConfig(test.Policies, nil, test.Config)
assert.NoError(t, err)
assert.Empty(t, validationErrors)
assert.Equal(t, test.Expected, result)
})
}
}
func TestReconcilePolicyPackConfigWithInitialConfig(t *testing.T) {
tests := []struct {
Test string
Policies []plugin.AnalyzerPolicyInfo
Config map[string]plugin.AnalyzerPolicyConfig
InitialConfig map[string]plugin.AnalyzerPolicyConfig
Expected map[string]plugin.AnalyzerPolicyConfig
}{
{
Test: "Initial config applied",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
},
},
InitialConfig: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
},
{
Test: "Initial config replaced by config",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy",
},
},
InitialConfig: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "mandatory",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"policy": {
EnforcementLevel: "advisory",
},
},
},
{
Test: "Initial config 'all' used, then replaced for one policy by config",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy-one",
},
{
Name: "policy-two",
},
{
Name: "policy-three",
},
},
InitialConfig: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"policy-three": {
EnforcementLevel: "advisory",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "mandatory",
},
"policy-one": {
EnforcementLevel: "mandatory",
},
"policy-two": {
EnforcementLevel: "mandatory",
},
"policy-three": {
EnforcementLevel: "advisory",
},
},
},
{
Test: "Initial config 'all' used with multiple policies",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "policy-one",
},
{
Name: "policy-two",
},
},
InitialConfig: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "disabled",
},
},
Expected: map[string]plugin.AnalyzerPolicyConfig{
"all": {
EnforcementLevel: "disabled",
},
"policy-one": {
EnforcementLevel: "disabled",
},
"policy-two": {
EnforcementLevel: "disabled",
},
},
},
}
for _, test := range tests {
t.Run(test.Test, func(t *testing.T) {
result, validationErrors, err := ReconcilePolicyPackConfig(test.Policies, test.InitialConfig, test.Config)
assert.NoError(t, err)
assert.Empty(t, validationErrors)
assert.Equal(t, test.Expected, result)
})
}
}
func TestReconcilePolicyPackConfigValidationErrors(t *testing.T) {
tests := []struct {
Test string
Policies []plugin.AnalyzerPolicyInfo
Config map[string]plugin.AnalyzerPolicyConfig
ExpectedValidationErrors []string
}{
{
Test: "Required config property not set",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
},
},
Required: []string{"foo"},
},
},
},
ExpectedValidationErrors: []string{"foo-policy: foo is required"},
},
{
Test: "Default value set to incorrect type",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"default": 1,
},
},
},
},
},
ExpectedValidationErrors: []string{"foo-policy: foo: Invalid type. Expected: string, given: integer"},
},
{
Test: "Default value too long",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"maxLength": 3,
"default": "this value is too long",
},
},
},
},
},
ExpectedValidationErrors: []string{"foo-policy: foo: String length must be less than or equal to 3"},
},
{
Test: "Default value too short",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"minLength": 50,
"default": "this value is too short",
},
},
},
},
},
ExpectedValidationErrors: []string{"foo-policy: foo: String length must be greater than or equal to 50"},
},
{
Test: "Default value set to invalid enum value",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"enum": []string{"bar", "baz"},
"default": "blah",
},
},
},
},
},
ExpectedValidationErrors: []string{`foo-policy: foo: foo must be one of the following: "bar", "baz"`},
},
{
Test: "Default value set to invalid constant value",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"const": "bar",
"default": "blah",
},
},
},
},
},
ExpectedValidationErrors: []string{`foo-policy: foo: foo does not match: "bar"`},
},
{
Test: "Incorrect type",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"foo-policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": 1,
},
},
},
ExpectedValidationErrors: []string{"foo-policy: foo: Invalid type. Expected: string, given: integer"},
},
{
Test: "Invalid enum value",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"enum": []string{"bar", "baz"},
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"foo-policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "blah",
},
},
},
ExpectedValidationErrors: []string{`foo-policy: foo: foo must be one of the following: "bar", "baz"`},
},
{
Test: "Invalid constant value",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"const": "bar",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"foo-policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "blah",
},
},
},
ExpectedValidationErrors: []string{`foo-policy: foo: foo does not match: "bar"`},
},
{
Test: "Multiple validation errors",
Policies: []plugin.AnalyzerPolicyInfo{
{
Name: "foo-policy",
EnforcementLevel: "advisory",
ConfigSchema: &plugin.AnalyzerPolicyConfigSchema{
Properties: map[string]plugin.JSONSchema{
"foo": {
"type": "string",
"maxLength": 3,
},
"bar": {
"type": "integer",
},
},
},
},
},
Config: map[string]plugin.AnalyzerPolicyConfig{
"foo-policy": {
EnforcementLevel: "advisory",
Properties: map[string]interface{}{
"foo": "this is too long",
"bar": float64(3.14),
},
},
},
ExpectedValidationErrors: []string{
"foo-policy: bar: Invalid type. Expected: integer, given: number",
"foo-policy: foo: String length must be less than or equal to 3",
},
},
}
for _, test := range tests {
t.Run(test.Test, func(t *testing.T) {
result, validationErrors, err := ReconcilePolicyPackConfig(test.Policies, nil, test.Config)
assert.NoError(t, err)
assert.Nil(t, result)
assert.ElementsMatch(t, test.ExpectedValidationErrors, validationErrors)
})
}
}