Unverified Commit c799072a authored by Mustaque Ahmed's avatar Mustaque Ahmed Committed by GitHub
Browse files

feat: add `--permissive-schema` flag (#827)


* initial commit

* feat: add `permissiveSchema` paramter to the `kubeconform` function

* feat: add `permissiveSchema` flag in the test command and fix test case

* feat: add `permissiveSchema` flag in `kustomize test` command

* adjust flag usage text
Co-authored-by: default avatarRoy Hadad <roy@datree.io>
Showing with 18 additions and 13 deletions
+18 -13
......@@ -29,10 +29,10 @@ func New() *K8sValidator {
return &K8sValidator{}
}
func (val *K8sValidator) InitClient(k8sVersion string, ignoreMissingSchemas bool, userProvidedSchemaLocations []string) {
func (val *K8sValidator) InitClient(k8sVersion string, ignoreMissingSchemas bool, userProvidedSchemaLocations []string, permissiveSchema bool) {
val.isOffline = checkIsOffline()
val.areThereCustomSchemaLocations = len(userProvidedSchemaLocations) > 0
val.validationClient = newKubeconformValidator(k8sVersion, ignoreMissingSchemas, getAllSchemaLocations(userProvidedSchemaLocations, val.isOffline))
val.validationClient = newKubeconformValidator(k8sVersion, ignoreMissingSchemas, getAllSchemaLocations(userProvidedSchemaLocations, val.isOffline), permissiveSchema)
}
func checkIsOffline() bool {
......@@ -212,8 +212,8 @@ func (val *K8sValidator) validateResource(filepath string) (bool, []error, *vali
return isValid, validationErrors, warning, nil
}
func newKubeconformValidator(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string) ValidationClient {
v, _ := kubeconformValidator.New(schemaLocations, kubeconformValidator.Opts{Strict: true, KubernetesVersion: k8sVersion, IgnoreMissingSchemas: ignoreMissingSchemas})
func newKubeconformValidator(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string, permissiveSchema bool) ValidationClient {
v, _ := kubeconformValidator.New(schemaLocations, kubeconformValidator.Opts{Strict: !permissiveSchema, KubernetesVersion: k8sVersion, IgnoreMissingSchemas: ignoreMissingSchemas})
return v
}
......
......@@ -226,7 +226,7 @@ func test_validateResource_offline_with_local_schema(t *testing.T) {
k8sValidator := &K8sValidator{
validationClient: newKubeconformValidator("1.21.0", false, getAllSchemaLocations([]string{
"some-path-to-non-existing-file-to-get-404.yaml",
}, true)),
}, true), false),
isOffline: true,
areThereCustomSchemaLocations: true,
}
......@@ -241,7 +241,7 @@ func test_validateResource_offline_with_local_schema(t *testing.T) {
func test_validateResource_offline_without_custom_schema_location(t *testing.T) {
k8sValidator := &K8sValidator{
validationClient: newKubeconformValidator("1.21.0", false, getAllSchemaLocations([]string{}, true)),
validationClient: newKubeconformValidator("1.21.0", false, getAllSchemaLocations([]string{}, true), true),
isOffline: true,
areThereCustomSchemaLocations: false,
}
......
......@@ -137,7 +137,7 @@ func (kv *k8sValidatorMock) GetK8sFiles(filesConfigurationsChan chan *extractor.
return args.Get(0).(chan *extractor.FileConfigurations), args.Get(1).(chan *extractor.FileConfigurations)
}
func (kv *k8sValidatorMock) InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string) {
func (kv *k8sValidatorMock) InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string, permissiveSchema bool) {
}
type PrinterMock struct {
......
......@@ -45,7 +45,7 @@ type Messager interface {
type K8sValidator interface {
ValidateResources(filesConfigurations chan *extractor.FileConfigurations, concurrency int, skipSchemaValidation bool) (chan *extractor.FileConfigurations, chan *extractor.InvalidFile, chan *validation.FileWithWarning)
InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string)
InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string, permissiveSchema bool)
GetK8sFiles(filesConfigurationsChan chan *extractor.FileConfigurations, concurrency int) (chan *extractor.FileConfigurations, chan *extractor.FileConfigurations)
}
......@@ -61,6 +61,7 @@ type TestCommandFlags struct {
NoRecord bool
SkipValidation string
SaveRendered bool
PermissiveSchema bool
}
// TestCommandFlags constructor
......@@ -75,6 +76,7 @@ func NewTestCommandFlags() *TestCommandFlags {
SchemaLocations: make([]string, 0),
SkipValidation: "",
SaveRendered: false,
PermissiveSchema: false,
}
}
......@@ -151,6 +153,7 @@ type TestCommandData struct {
ClientId string
SkipSchemaValidation bool
SaveRendered bool
PermissiveSchema bool
}
type TestCommandContext struct {
......@@ -265,7 +268,8 @@ func (flags *TestCommandFlags) AddFlags(cmd *cobra.Command) {
// kubeconform flag
cmd.Flags().StringArrayVarP(&flags.SchemaLocations, "schema-location", "", []string{}, "Override schemas location search path (can be specified multiple times)")
cmd.Flags().BoolVarP(&flags.IgnoreMissingSchemas, "ignore-missing-schemas", "", false, "Ignore missing schemas when executing schema validation step")
cmd.Flags().BoolVarP(&flags.SaveRendered, "save-rendered", "", false, "Don't delete rendered files after the policy check (e.g helm, kustomize)")
cmd.Flags().BoolVarP(&flags.SaveRendered, "save-rendered", "", false, "Don't delete rendered files after the policy check (e.g. helm, kustomize)")
cmd.Flags().BoolVarP(&flags.PermissiveSchema, "permissive-schema", "", false, "Perform non-strict schema validation (i.e. allow additional properties)")
}
func GenerateTestCommandData(testCommandFlags *TestCommandFlags, localConfigContent *localConfig.LocalConfig, evaluationPrerunDataResp *cliClient.EvaluationPrerunDataResponse) (*TestCommandData, error) {
......@@ -321,6 +325,7 @@ func GenerateTestCommandData(testCommandFlags *TestCommandFlags, localConfigCont
PromptRegistrationURL: evaluationPrerunDataResp.PromptRegistrationURL,
SkipSchemaValidation: testCommandFlags.SkipValidation == "schema",
SaveRendered: testCommandFlags.SaveRendered,
PermissiveSchema: testCommandFlags.PermissiveSchema,
}
return testCommandOptions, nil
......@@ -490,7 +495,7 @@ func evaluate(ctx *TestCommandContext, filesPaths []string, testCommandData *Tes
validationManager := NewValidationManager()
ctx.K8sValidator.InitClient(testCommandData.K8sVersion, testCommandData.IgnoreMissingSchemas, testCommandData.SchemaLocations)
ctx.K8sValidator.InitClient(testCommandData.K8sVersion, testCommandData.IgnoreMissingSchemas, testCommandData.SchemaLocations, testCommandData.PermissiveSchema)
concurrency := 100
var wg sync.WaitGroup
......
......@@ -137,7 +137,7 @@ func (kv *K8sValidatorMock) GetK8sFiles(filesConfigurationsChan chan *extractor.
return args.Get(0).(chan *extractor.FileConfigurations), args.Get(1).(chan *extractor.FileConfigurations)
}
func (kv *K8sValidatorMock) InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string) {
func (kv *K8sValidatorMock) InitClient(k8sVersion string, ignoreMissingSchemas bool, schemaLocations []string, permissiveSchema bool) {
}
type PrinterMock struct {
......@@ -242,7 +242,7 @@ func TestTestFlow(t *testing.T) {
readerMock.On("FilterFiles", mock.Anything).Return(tt.args.path, nil)
filesExtractorMock.On("ExtractFilesConfigurations", mock.Anything, 100).Return(tt.mock.ExtractFilesConfigurations.filesConfigurationsChan, tt.mock.ExtractFilesConfigurations.invalidFilesChan)
k8sValidatorMock.On("ValidateResources", mock.Anything, 100).Return(tt.mock.ValidateResources.k8sFilesConfigurationsChan, tt.mock.ValidateResources.k8sInvalidFilesChan, tt.mock.ValidateResources.filesWithWarningsChan)
k8sValidatorMock.On("InitClient", mock.Anything, mock.Anything, mock.Anything).Return()
k8sValidatorMock.On("InitClient", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return()
evaluatorMock.On("Evaluate", mock.Anything, mock.Anything, mock.Anything).Return(tt.mock.Evaluate.policyCheckResultData, tt.mock.Evaluate.err)
evaluatorMock.On("SendEvaluationResult", mock.Anything).Return(tt.mock.SendEvaluationResult.sendEvaluationResultsResponse, tt.mock.SendEvaluationResult.err)
......@@ -690,7 +690,7 @@ func setup() {
k8sValidatorMock.On("ValidateResources", mock.Anything, mock.Anything, mock.Anything).Return(filesConfigurationsChan, invalidK8sFilesChan, k8sValidationWarningsChan, newErrorsChan())
k8sValidatorMock.On("GetK8sFiles", mock.Anything, mock.Anything).Return(filesConfigurationsChan, ignoredFilesChan, newErrorsChan())
k8sValidatorMock.On("InitClient", mock.Anything, mock.Anything, mock.Anything).Return()
k8sValidatorMock.On("InitClient", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return()
filesExtractorMock := &FilesExtractorMock{}
filesExtractorMock.On("ExtractFilesConfigurations", mock.Anything, 100).Return(filesConfigurationsChan, invalidFilesChan)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment