diff --git a/.github/workflows/sanity.yml b/.github/workflows/sanity.yml index d8882201..efc392c5 100644 --- a/.github/workflows/sanity.yml +++ b/.github/workflows/sanity.yml @@ -2,7 +2,7 @@ on: [push, pull_request] name: Sanity env: - GO_VERSION: '1.19.x' + GO_VERSION: '1.20.x' jobs: build: diff --git a/cmd/cdi/go.mod b/cmd/cdi/go.mod index f270f316..9d7bba5f 100644 --- a/cmd/cdi/go.mod +++ b/cmd/cdi/go.mod @@ -1,6 +1,6 @@ module tags.cncf.io/container-device-interface/cmd/cdi -go 1.19 +go 1.20 require ( github.com/fsnotify/fsnotify v1.5.1 diff --git a/cmd/validate/go.mod b/cmd/validate/go.mod index 29341d6c..1d5c8701 100644 --- a/cmd/validate/go.mod +++ b/cmd/validate/go.mod @@ -1,6 +1,6 @@ module tags.cncf.io/container-device-interface/cmd/validate -go 1.19 +go 1.20 require tags.cncf.io/container-device-interface v0.0.0 diff --git a/go.mod b/go.mod index 3ba5b193..9ab275e1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module tags.cncf.io/container-device-interface -go 1.19 +go 1.20 require ( github.com/fsnotify/fsnotify v1.5.1 diff --git a/internal/multierror/multierror.go b/internal/multierror/multierror.go deleted file mode 100644 index 07aca4a1..00000000 --- a/internal/multierror/multierror.go +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright © 2022 The CDI Authors - - 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 multierror - -import ( - "strings" -) - -// New combines several errors into a single error. Parameters that are nil are -// ignored. If no errors are passed in or all parameters are nil, then the -// result is also nil. -func New(errors ...error) error { - // Filter out nil entries. - numErrors := 0 - for _, err := range errors { - if err != nil { - errors[numErrors] = err - numErrors++ - } - } - if numErrors == 0 { - return nil - } - return multiError(errors[0:numErrors]) -} - -// multiError is the underlying implementation used by New. -// -// Beware that a null multiError is not the same as a nil error. -type multiError []error - -// multiError returns all individual error strings concatenated with "\n" -func (e multiError) Error() string { - var builder strings.Builder - for i, err := range e { - if i > 0 { - _, _ = builder.WriteString("\n") - } - _, _ = builder.WriteString(err.Error()) - } - return builder.String() -} - -// Append returns a new multi error all errors concatenated. Errors that are -// multi errors get flattened, nil is ignored. -func Append(err error, errors ...error) error { - var result multiError - if m, ok := err.(multiError); ok { - result = m - } else if err != nil { - result = append(result, err) - } - - for _, e := range errors { - if e == nil { - continue - } - if m, ok := e.(multiError); ok { - result = append(result, m...) - } else { - result = append(result, e) - } - } - if len(result) == 0 { - return nil - } - return result -} diff --git a/internal/multierror/multierror_test.go b/internal/multierror/multierror_test.go deleted file mode 100644 index 173c58c0..00000000 --- a/internal/multierror/multierror_test.go +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright © 2022 The CDI Authors - - 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 multierror - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNew(t *testing.T) { - assert.Equal(t, nil, New()) - assert.Equal(t, nil, New(nil)) - assert.Equal(t, nil, New(nil, nil)) - assert.Equal(t, "hello\nworld", New(errors.New("hello"), errors.New("world")).Error()) -} - -func TestAppend(t *testing.T) { - assert.Equal(t, nil, Append(nil)) - assert.Equal(t, nil, Append(nil, nil)) - assert.Equal(t, multiError{errors.New("hello"), errors.New("world"), errors.New("x"), errors.New("y")}, - Append(New(errors.New("hello"), errors.New("world")), New(errors.New("x"), nil, errors.New("y"))), nil) -} diff --git a/internal/validation/k8s/objectmeta.go b/internal/validation/k8s/objectmeta.go index 5cf63dab..fb86c67a 100644 --- a/internal/validation/k8s/objectmeta.go +++ b/internal/validation/k8s/objectmeta.go @@ -20,10 +20,9 @@ limitations under the License. package k8s import ( + "errors" "fmt" "strings" - - "tags.cncf.io/container-device-interface/internal/multierror" ) // TotalAnnotationSizeLimitB defines the maximum size of all annotations in characters. @@ -31,17 +30,17 @@ const TotalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB // ValidateAnnotations validates that a set of annotations are correctly defined. func ValidateAnnotations(annotations map[string]string, path string) error { - errors := multierror.New() + errs := []error{} for k := range annotations { // The rule is QualifiedName except that case doesn't matter, so convert to lowercase before checking. for _, msg := range IsQualifiedName(strings.ToLower(k)) { - errors = multierror.Append(errors, fmt.Errorf("%v.%v is invalid: %v", path, k, msg)) + errs = append(errs, fmt.Errorf("%v.%v is invalid: %v", path, k, msg)) } } if err := ValidateAnnotationsSize(annotations); err != nil { - errors = multierror.Append(errors, fmt.Errorf("%v is too long: %v", path, err)) + errs = append(errs, fmt.Errorf("%v is too long: %v", path, err)) } - return errors + return errors.Join(errs...) } // ValidateAnnotationsSize validates that a set of annotations is not too large. diff --git a/pkg/cdi/cache.go b/pkg/cdi/cache.go index a3f95fa5..c2f7fe34 100644 --- a/pkg/cdi/cache.go +++ b/pkg/cdi/cache.go @@ -28,7 +28,6 @@ import ( "github.com/fsnotify/fsnotify" oci "github.com/opencontainers/runtime-spec/specs-go" - "tags.cncf.io/container-device-interface/internal/multierror" cdi "tags.cncf.io/container-device-interface/specs-go" ) @@ -133,11 +132,11 @@ func (c *Cache) Refresh() error { } // collect and return cached errors, much like refresh() does it - var result error - for _, errors := range c.errors { - result = multierror.Append(result, errors...) + errs := []error{} + for _, specErrs := range c.errors { + errs = append(errs, errors.Join(specErrs...)) } - return result + return errors.Join(errs...) } // Refresh the Cache by rescanning CDI Spec directories and files. @@ -147,12 +146,10 @@ func (c *Cache) refresh() error { devices = map[string]*Device{} conflicts = map[string]struct{}{} specErrors = map[string][]error{} - result []error ) // collect errors per spec file path and once globally collectError := func(err error, paths ...string) { - result = append(result, err) for _, path := range paths { specErrors[path] = append(specErrors[path], err) } @@ -205,7 +202,11 @@ func (c *Cache) refresh() error { c.devices = devices c.errors = specErrors - return multierror.New(result...) + errs := []error{} + for _, specErrs := range specErrors { + errs = append(errs, errors.Join(specErrs...)) + } + return errors.Join(errs...) } // RefreshIfRequired triggers a refresh if necessary. diff --git a/schema/schema.go b/schema/schema.go index e6e4063e..6a582ca1 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -20,6 +20,7 @@ import ( "bytes" "embed" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -30,7 +31,6 @@ import ( "sigs.k8s.io/yaml" schema "github.com/xeipuuv/gojsonschema" - "tags.cncf.io/container-device-interface/internal/multierror" "tags.cncf.io/container-device-interface/internal/validation" ) @@ -333,11 +333,16 @@ func (e *Error) Error() string { return "" } - var multi error + errs := []error{} for _, err := range e.Result.Errors() { - multi = multierror.Append(multi, fmt.Errorf("%v", err)) + errs = append(errs, fmt.Errorf("%v", err)) } - return multi.Error() + + if err := errors.Join(errs...); err != nil { + return fmt.Sprintf("%v", err) + } + + return "" } var (