diff --git a/pkg/yaml/validation/error.go b/pkg/yaml/validation/error.go index b8dc15c..c3e8272 100644 --- a/pkg/yaml/validation/error.go +++ b/pkg/yaml/validation/error.go @@ -15,6 +15,7 @@ package validation import ( + "errors" "fmt" "strings" ) @@ -31,6 +32,46 @@ const ( ErrUnknown ) +var validationErrors = []ErrorKind{ + ErrKindChangesValidationFailed, + ErrKindValidationFailed, + ErrKindInvalidYAML, + ErrDocumentValidationFailed, + ErrSchemaNotFound, + ErrRead, + ErrUnknown, +} + +// ExtractValidationErrors +// extract all validation errors from error +// if no any error extracted returns slice with ErrUnknown +func ExtractValidationErrors(err error) []ErrorKind { + result := make([]ErrorKind, 0, 2) + for _, e := range validationErrors { + if errors.Is(err, e) { + result = append(result, e) + } + } + + if len(result) == 0 { + result = append(result, ErrUnknown) + } + + return result +} + +// ExtractValidationError +// extract first validation error from error +// if no any error extracted returns ErrUnknown +func ExtractValidationError(err error) ErrorKind { + errs := ExtractValidationErrors(err) + if len(errs) > 0 { + return errs[0] + } + + return ErrUnknown +} + func (k ErrorKind) Error() string { return k.String() } diff --git a/pkg/yaml/validation/error_test.go b/pkg/yaml/validation/error_test.go new file mode 100644 index 0000000..0b78e60 --- /dev/null +++ b/pkg/yaml/validation/error_test.go @@ -0,0 +1,68 @@ +// Copyright 2026 Flant JSC +// +// 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 validation + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestExtractErrors(t *testing.T) { + tests := []struct { + name string + input error + expectedErrors []ErrorKind + }{ + { + name: "one error", + input: fmt.Errorf("some %w error", ErrSchemaNotFound), + expectedErrors: []ErrorKind{ErrSchemaNotFound}, + }, + + { + name: "multiple errors in order", + input: fmt.Errorf("some %w error: %w", ErrKindInvalidYAML, ErrKindValidationFailed), + expectedErrors: []ErrorKind{ErrKindValidationFailed, ErrKindInvalidYAML}, + }, + + { + name: "no validation error must return ErrUnknown", + input: fmt.Errorf("some error"), + expectedErrors: []ErrorKind{ErrUnknown}, + }, + } + + t.Run("extract all errors", func(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + errs := ExtractValidationErrors(test.input) + require.Len(t, errs, len(test.expectedErrors), "unexpected error count") + require.Equal(t, test.expectedErrors, errs, "should extract all errors") + }) + } + }) + + t.Run("extract one error", func(t *testing.T) { + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := ExtractValidationError(test.input) + require.Error(t, err, "should extract validation error") + require.Equal(t, test.expectedErrors[0], err, "should extract valid error") + }) + } + }) +}