From fc3acd6421d07a41c2de1076070be8eabbbfb227 Mon Sep 17 00:00:00 2001 From: Yasmin Valim Date: Fri, 8 Nov 2024 12:09:28 -0300 Subject: [PATCH 1/3] go.mod: update to Ignition 2.20.0 --- go.mod | 6 +- go.sum | 45 +--- .../v2/config/shared/errors/errors.go | 2 + .../testify/assert/assertion_compare.go | 28 ++- .../assert/assertion_compare_can_convert.go | 16 -- .../assert/assertion_compare_legacy.go | 16 -- .../testify/assert/assertion_format.go | 32 ++- .../testify/assert/assertion_forward.go | 59 +++-- .../stretchr/testify/assert/assertions.go | 207 +++++++++++------- .../testify/assert/http_assertions.go | 27 ++- vendor/modules.txt | 12 +- 11 files changed, 248 insertions(+), 202 deletions(-) delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go diff --git a/go.mod b/go.mod index 82bc34d..ec3c9ab 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.18 require ( github.com/clarketm/json v1.17.1 github.com/coreos/ignition v0.35.0 - github.com/coreos/ignition/v2 v2.16.2 - github.com/stretchr/testify v1.8.4 + github.com/coreos/ignition/v2 v2.20.0 + github.com/stretchr/testify v1.9.0 ) require ( github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 // indirect - github.com/aws/aws-sdk-go v1.44.298 // indirect + github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 // indirect diff --git a/go.sum b/go.sum index 602ea2b..333fbae 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= -github.com/aws/aws-sdk-go v1.44.298 h1:5qTxdubgV7PptZJmp/2qDwD2JL187ePL7VOxsSh1i3g= -github.com/aws/aws-sdk-go v1.44.298/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/clarketm/json v1.17.1 h1:U1IxjqJkJ7bRK4L6dyphmoO840P6bdhPdbbLySourqI= github.com/clarketm/json v1.17.1/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo= github.com/coreos/go-json v0.0.0-20230131223807-18775e0fb4fb h1:rmqyI19j3Z/74bIRhuC59RB442rXUazKNueVpfJPxg4= @@ -14,55 +14,22 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/ignition v0.35.0 h1:UFodoYq1mOPrbEjtxIsZbThcDyQwAI1owczRDqWmKkQ= github.com/coreos/ignition v0.35.0/go.mod h1:WJQapxzEn9DE0ryxsGvm8QnBajm/XsS/PkrDqSpz+bA= -github.com/coreos/ignition/v2 v2.16.2 h1:wPpxTovdzCLJISYmNiM5Cpw4qCPc3/P2ibruPyS46eA= -github.com/coreos/ignition/v2 v2.16.2/go.mod h1:Y1BKC60VSNgA5oWNoLIHXigpFX1FFn4CVeimmsI+Bhg= +github.com/coreos/ignition/v2 v2.20.0 h1:xQjrxhCbcSKpqrN2hOQavAc1rx0GOf6qh2QCauScwPU= +github.com/coreos/ignition/v2 v2.20.0/go.mod h1:l7EpXNWA7jBXmjUMvnVBlrrj+LX2wA/PAyD9kstwFDQ= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 h1:uSmlDgJGbUB0bwQBcZomBTottKwEDF5fF8UjSwKSzWM= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687/go.mod h1:Salmysdw7DAVuobBW/LwsKKgpyCPHUhjyJoMJD+ZJiI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go4.org v0.0.0-20200104003542-c7e774b10ea0 h1:M6XsnQeLwG+rHQ+/rrGh3puBI3WZEy9TBWmf2H+enQA= go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go b/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go index 8e2d24d..13742ab 100644 --- a/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go +++ b/vendor/github.com/coreos/ignition/v2/config/shared/errors/errors.go @@ -85,6 +85,8 @@ var ( ErrInvalidProxy = errors.New("proxies must be http(s)") ErrInsecureProxy = errors.New("insecure plaintext HTTP proxy specified for HTTPS resources") ErrPathConflictsSystemd = errors.New("path conflicts with systemd unit or dropin") + ErrCexWithClevis = errors.New("cannot use cex with clevis") + ErrCexWithKeyFile = errors.New("cannot use key file with cex") // Systemd section errors ErrInvalidSystemdExt = errors.New("invalid systemd unit extension") diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index b774da8..4d4b4aa 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -28,6 +28,8 @@ var ( uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) + uintptrType = reflect.TypeOf(uintptr(1)) + float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) @@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Struct: { // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { + if !obj1Value.CanConvert(timeType) { break } - // time.Time can compared! + // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) @@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Slice: { // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { + if !obj1Value.CanConvert(bytesType) { break } @@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true } + case reflect.Uintptr: + { + uintptrObj1, ok := obj1.(uintptr) + if !ok { + uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) + } + uintptrObj2, ok := obj2.(uintptr) + if !ok { + uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) + } + if uintptrObj1 > uintptrObj2 { + return compareGreater, true + } + if uintptrObj1 == uintptrObj2 { + return compareEqual, true + } + if uintptrObj1 < uintptrObj2 { + return compareLess, true + } + } } return compareEqual, false diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go deleted file mode 100644 index da86790..0000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2..0000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 84dbd6c..3ddab10 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index b1d94ae..a84e09b 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface return EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn return EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in return NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index a55d1bb..0b7570f 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -19,7 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" + "gopkg.in/yaml.v3" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" @@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} { return result.Interface() case reflect.Array, reflect.Slice: - result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + var result reflect.Value + if expectedKind == reflect.Array { + result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() + } else { + result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + } for i := 0; i < expectedValue.Len(); i++ { index := expectedValue.Index(i) if isNil(index) { @@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} { // structures. // // This function does no assertion of any kind. +// +// Deprecated: Use [EqualExportedValues] instead. func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { expectedCleaned := copyExportedFields(expected) actualCleaned := copyExportedFields(actual) @@ -153,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { return true } - actualType := reflect.TypeOf(actual) - if actualType == nil { + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + if !expectedValue.IsValid() || !actualValue.IsValid() { return false } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + + expectedType := expectedValue.Type() + actualType := actualValue.Type() + if !expectedType.ConvertibleTo(actualType) { + return false + } + + if !isNumericType(expectedType) || !isNumericType(actualType) { // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + return reflect.DeepEqual( + expectedValue.Convert(actualType).Interface(), actual, + ) } - return false + // If BOTH values are numeric, there are chances of false positives due + // to overflow or underflow. So, we need to make sure to always convert + // the smaller type to a larger type before comparing. + if expectedType.Size() >= actualType.Size() { + return actualValue.Convert(expectedType).Interface() == expected + } + + return expectedValue.Convert(actualType).Interface() == actual +} + +// isNumericType returns true if the type is one of: +// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, +// float32, float64, complex64, complex128 +func isNumericType(t reflect.Type) bool { + return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object @@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) @@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg return true } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) + } + if reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) + } + + return true +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool { // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar +// with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { @@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string { return value } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs .. return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } + if aType.Kind() == reflect.Ptr { + aType = aType.Elem() + } + if bType.Kind() == reflect.Ptr { + bType = bType.Elem() + } + if aType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) } if bType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) } expected = copyExportedFields(expected) @@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -638,16 +683,13 @@ func isNil(object interface{}) bool { } value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, - kind) - - if isNilableKind && value.IsNil() { - return true + switch value.Kind() { + case + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice, reflect.UnsafePointer: + + return value.IsNil() } return false @@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { +// getLen tries to get the length of an object. +// It returns (0, false) if impossible. +func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { - if e := recover(); e != nil { - ok = false - } + ok = recover() == nil }() - return true, v.Len() + return v.Len(), true } // Len asserts that the specified object has specific length. @@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) if h, ok := t.(tHelper); ok { h.Helper() } - ok, l := getLen(object) + l, ok := getLen(object) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } @@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd h.Helper() } if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") + return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { @@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if h, ok := t.(tHelper); ok { h.Helper() } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { + + if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } - actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) + actualSlice := reflect.ValueOf(actual) - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result + if expectedSlice.Type().Kind() != reflect.Slice { + return Fail(t, "Expected value must be slice", msgAndArgs...) + } + + expectedLen := expectedSlice.Len() + if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { + return false + } + + for i := 0; i < expectedLen; i++ { + if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { + return false } } @@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) { } // FailNow panics. -func (c *CollectT) FailNow() { +func (*CollectT) FailNow() { panic("Assertion failed") } -// Reset clears the collected errors. -func (c *CollectT) Reset() { - c.errors = nil +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Reset() { + panic("Reset() is deprecated") } -// Copy copies the collected errors to the supplied t. -func (c *CollectT) Copy(t TestingT) { - if tt, ok := t.(tHelper); ok { - tt.Helper() - } - for _, err := range c.errors { - t.Errorf("%v", err) - } +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Copy(TestingT) { + panic("Copy() is deprecated") } // EventuallyWithT asserts that given condition will be met in waitFor time, @@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time h.Helper() } - collect := new(CollectT) - ch := make(chan bool, 1) + var lastFinishedTickErrs []error + ch := make(chan []error, 1) timer := time.NewTimer(waitFor) defer timer.Stop() @@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time for tick := ticker.C; ; { select { case <-timer.C: - collect.Copy(t) + for _, err := range lastFinishedTickErrs { + t.Errorf("%v", err) + } return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil - collect.Reset() go func() { + collect := new(CollectT) + defer func() { + ch <- collect.errors + }() condition(collect) - ch <- len(collect.errors) == 0 }() - case v := <-ch: - if v { + case errs := <-ch: + if len(errs) == 0 { return true } + // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. + lastFinishedTickErrs = errs tick = ticker.C } } diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index d8038c2..861ed4b 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,7 +12,7 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } @@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode @@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode @@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode @@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful @@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if len(values) > 0 { + url += "?" + values.Encode() + } + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } @@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/modules.txt b/vendor/modules.txt index 99304b7..078a64a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,8 +1,8 @@ # github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 ## explicit github.com/ajeddeloh/go-json -# github.com/aws/aws-sdk-go v1.44.298 -## explicit; go 1.11 +# github.com/aws/aws-sdk-go v1.55.5 +## explicit; go 1.19 github.com/aws/aws-sdk-go/aws/arn # github.com/clarketm/json v1.17.1 ## explicit @@ -41,8 +41,8 @@ github.com/coreos/ignition/config/validate github.com/coreos/ignition/config/validate/astjson github.com/coreos/ignition/config/validate/astnode github.com/coreos/ignition/config/validate/report -# github.com/coreos/ignition/v2 v2.16.2 -## explicit; go 1.18 +# github.com/coreos/ignition/v2 v2.20.0 +## explicit; go 1.20 github.com/coreos/ignition/v2/config/merge github.com/coreos/ignition/v2/config/shared/errors github.com/coreos/ignition/v2/config/shared/parse @@ -71,8 +71,8 @@ github.com/davecgh/go-spew/spew # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/stretchr/testify v1.8.4 -## explicit; go 1.20 +# github.com/stretchr/testify v1.9.0 +## explicit; go 1.17 github.com/stretchr/testify/assert # github.com/vincent-petithory/dataurl v1.0.0 ## explicit From b4708fa88e2782cf6ad45e622eca3684494cc54c Mon Sep 17 00:00:00 2001 From: Yasmin Valim Date: Sat, 9 Nov 2024 22:11:52 -0300 Subject: [PATCH 2/3] Add translation v35 to v34 --- go.mod | 2 + translate/v35tov34/v35tov34.go | 97 +++++ translate_test.go | 368 ++++++++++++++++++ .../ignition/v2/config/v3_5/types/cex.go | 33 ++ .../ignition/v2/config/v3_5/types/clevis.go | 49 +++ .../ignition/v2/config/v3_5/types/config.go | 64 +++ .../ignition/v2/config/v3_5/types/device.go | 25 ++ .../v2/config/v3_5/types/directory.go | 26 ++ .../ignition/v2/config/v3_5/types/disk.go | 135 +++++++ .../ignition/v2/config/v3_5/types/file.go | 43 ++ .../v2/config/v3_5/types/filesystem.go | 106 +++++ .../ignition/v2/config/v3_5/types/headers.go | 65 ++++ .../ignition/v2/config/v3_5/types/ignition.go | 49 +++ .../ignition/v2/config/v3_5/types/kargs.go | 22 ++ .../ignition/v2/config/v3_5/types/luks.go | 82 ++++ .../ignition/v2/config/v3_5/types/mode.go | 26 ++ .../ignition/v2/config/v3_5/types/node.go | 59 +++ .../v2/config/v3_5/types/partition.go | 91 +++++ .../ignition/v2/config/v3_5/types/passwd.go | 23 ++ .../ignition/v2/config/v3_5/types/path.go | 42 ++ .../ignition/v2/config/v3_5/types/proxy.go | 49 +++ .../ignition/v2/config/v3_5/types/raid.go | 62 +++ .../ignition/v2/config/v3_5/types/resource.go | 91 +++++ .../ignition/v2/config/v3_5/types/schema.go | 264 +++++++++++++ .../ignition/v2/config/v3_5/types/storage.go | 115 ++++++ .../ignition/v2/config/v3_5/types/systemd.go | 61 +++ .../ignition/v2/config/v3_5/types/tang.go | 65 ++++ .../ignition/v2/config/v3_5/types/tls.go | 27 ++ .../ignition/v2/config/v3_5/types/unit.go | 68 ++++ .../ignition/v2/config/v3_5/types/url.go | 83 ++++ .../v2/config/v3_5/types/verification.go | 71 ++++ vendor/modules.txt | 2 + 32 files changed, 2365 insertions(+) create mode 100644 translate/v35tov34/v35tov34.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go create mode 100644 vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go diff --git a/go.mod b/go.mod index ec3c9ab..1f0391f 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/coreos/ign-converter go 1.18 +replace github.com/coreos/ign-converter/translate/v34tov35 => ./translate/v35tov34 + require ( github.com/clarketm/json v1.17.1 github.com/coreos/ignition v0.35.0 diff --git a/translate/v35tov34/v35tov34.go b/translate/v35tov34/v35tov34.go new file mode 100644 index 0000000..12572ea --- /dev/null +++ b/translate/v35tov34/v35tov34.go @@ -0,0 +1,97 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 v35tov34 + +import ( + "fmt" + "reflect" + + "github.com/coreos/ignition/v2/config/translate" + "github.com/coreos/ignition/v2/config/v3_4/types" + + old_types "github.com/coreos/ignition/v2/config/v3_5/types" + "github.com/coreos/ignition/v2/config/validate" +) + +// Copy of github.com/coreos/ignition/v2/config/v3_4/translate/translate.go +// with the types & old_types imports reversed (the referenced file translates +// from 3.4 -> 3.5 but as a result only touches fields that are understood by +// the 3.4 spec). +func translateIgnition(old old_types.Ignition) (ret types.Ignition) { + // use a new translator so we don't recurse infinitely + translate.NewTranslator().Translate(&old, &ret) + ret.Version = types.MaxVersion.String() + return +} +func translateLuks(old old_types.Luks) (ret types.Luks) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateTang) + tr.Translate(&old.Clevis, &ret.Clevis) + tr.Translate(&old.Device, &ret.Device) + tr.Translate(&old.KeyFile, &ret.KeyFile) + tr.Translate(&old.Label, &ret.Label) + tr.Translate(&old.Name, &ret.Name) + tr.Translate(&old.OpenOptions, &ret.OpenOptions) + tr.Translate(&old.Options, &ret.Options) + tr.Translate(&old.Discard, &ret.Discard) + tr.Translate(&old.UUID, &ret.UUID) + tr.Translate(&old.WipeVolume, &ret.WipeVolume) + return +} +func translateTang(old old_types.Tang) (ret types.Tang) { + tr := translate.NewTranslator() + tr.Translate(&old.Thumbprint, &ret.Thumbprint) + tr.Translate(&old.URL, &ret.URL) + return +} +func translateConfig(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateLuks) + tr.Translate(&old, &ret) + return +} + +// end copied Ignition v3_5/translate block + +// Translate translates Ignition spec config v3.5 to spec v3.4 +func Translate(cfg old_types.Config) (types.Config, error) { + rpt := validate.ValidateWithContext(cfg, nil) + if rpt.IsFatal() { + return types.Config{}, fmt.Errorf("invalid input config:\n%s", rpt.String()) + } + + err := checkValue(reflect.ValueOf(cfg)) + if err != nil { + return types.Config{}, err + } + + res := translateConfig(cfg) + + // Sanity check the returned config + oldrpt := validate.ValidateWithContext(res, nil) + if oldrpt.IsFatal() { + return types.Config{}, fmt.Errorf("converted spec has unexpected fatal error:\n%s", oldrpt.String()) + } + return res, nil +} + +func checkValue(v reflect.Value) error { + // v3.5 introduced Cex type + if v.Type() == reflect.TypeOf(old_types.Cex{}) { + return fmt.Errorf("invalid input config: 'Cex' type is not supported in spec v3.4") + } + + return nil +} diff --git a/translate_test.go b/translate_test.go index a8ae52f..c03eb17 100644 --- a/translate_test.go +++ b/translate_test.go @@ -25,6 +25,7 @@ import ( types3_2 "github.com/coreos/ignition/v2/config/v3_2/types" types3_3 "github.com/coreos/ignition/v2/config/v3_3/types" types3_4 "github.com/coreos/ignition/v2/config/v3_4/types" + types3_5 "github.com/coreos/ignition/v2/config/v3_5/types" "github.com/stretchr/testify/assert" @@ -38,6 +39,7 @@ import ( "github.com/coreos/ign-converter/translate/v32tov31" "github.com/coreos/ign-converter/translate/v33tov32" "github.com/coreos/ign-converter/translate/v34tov33" + "github.com/coreos/ign-converter/translate/v35tov34" "github.com/coreos/ign-converter/util" ) @@ -1855,6 +1857,344 @@ var ( }, } + downtranslateConfig3_4 = types3_5.Config{ + Ignition: types3_5.Ignition{ + Version: "3.5.0", + Config: types3_5.IgnitionConfig{ + Merge: []types3_5.Resource{ + { + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + Replace: types3_5.Resource{ + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + Timeouts: types3_5.Timeouts{ + HTTPResponseHeaders: util.IntP(5), + HTTPTotal: util.IntP(10), + }, + Security: types3_5.Security{ + TLS: types3_5.TLS{ + CertificateAuthorities: []types3_5.Resource{ + { + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + }, + }, + Proxy: types3_5.Proxy{ + HTTPProxy: util.StrP("https://proxy.example.net/"), + HTTPSProxy: util.StrP("https://secure.proxy.example.net/"), + NoProxy: []types3_5.NoProxyItem{ + "www.example.net", + "www.example2.net", + }, + }, + }, + Storage: types3_5.Storage{ + Disks: []types3_5.Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolP(true), + Partitions: []types3_5.Partition{ + { + Label: util.StrP("var"), + Number: 1, + SizeMiB: util.IntP(5000), + StartMiB: util.IntP(2048), + TypeGUID: &aUUID, + GUID: &aUUID, + WipePartitionEntry: util.BoolP(true), + ShouldExist: util.BoolP(true), + }, + }, + }, + }, + Raid: []types3_5.Raid{ + { + Name: "array", + Level: util.StrP("raid10"), + Devices: []types3_5.Device{"/dev/sdb", "/dev/sdc"}, + Spares: util.IntP(1), + Options: []types3_5.RaidOption{"foobar"}, + }, + }, + Filesystems: []types3_5.Filesystem{ + { + Path: util.StrP("/var"), + Device: "/dev/disk/by-partlabel/var", + Format: util.StrP("xfs"), + WipeFilesystem: util.BoolP(true), + Label: util.StrP("var"), + UUID: &aUUID, + Options: []types3_5.FilesystemOption{"rw"}, + }, + }, + Files: []types3_5.File{ + { + Node: types3_5.Node{ + Path: "/var/varfile", + Overwrite: util.BoolPStrict(false), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + FileEmbedded1: types3_5.FileEmbedded1{ + Mode: util.IntP(420), + Append: []types3_5.Resource{ + { + Compression: util.StrP("gzip"), + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + HTTPHeaders: types3_5.HTTPHeaders{ + types3_5.HTTPHeader{ + Name: "Authorization", + Value: util.StrP("Basic YWxhZGRpbjpvcGVuc2VzYW1l"), + }, + types3_5.HTTPHeader{ + Name: "User-Agent", + Value: util.StrP("Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)"), + }, + }, + }, + }, + }, + }, + { + Node: types3_5.Node{ + Path: "/empty", + Overwrite: util.BoolPStrict(false), + }, + FileEmbedded1: types3_5.FileEmbedded1{ + Mode: util.IntP(420), + Contents: types3_5.Resource{ + Source: util.StrPStrict(""), + }, + }, + }, + }, + Directories: []types3_5.Directory{ + { + Node: types3_5.Node{ + Path: "/rootdir", + Overwrite: util.BoolP(true), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + DirectoryEmbedded1: types3_5.DirectoryEmbedded1{ + Mode: util.IntP(420), + }, + }, + }, + Links: []types3_5.Link{ + { + Node: types3_5.Node{ + Path: "/rootlink", + Overwrite: util.BoolP(true), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + LinkEmbedded1: types3_5.LinkEmbedded1{ + Hard: util.BoolP(false), + Target: util.StrP("/foobar"), + }, + }, + }, + }, + } + + nonexhaustiveConfig3_5 = types3_5.Config{ + Ignition: types3_5.Ignition{ + Version: "3.5.0", + Config: types3_5.IgnitionConfig{ + Merge: []types3_5.Resource{ + { + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + Replace: types3_5.Resource{ + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + Timeouts: types3_5.Timeouts{ + HTTPResponseHeaders: util.IntP(5), + HTTPTotal: util.IntP(10), + }, + Security: types3_5.Security{ + TLS: types3_5.TLS{ + CertificateAuthorities: []types3_5.Resource{ + { + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + }, + }, + }, + }, + Proxy: types3_5.Proxy{ + HTTPProxy: util.StrP("https://proxy.example.net/"), + HTTPSProxy: util.StrP("https://secure.proxy.example.net/"), + NoProxy: []types3_5.NoProxyItem{ + "www.example.net", + "www.example2.net", + }, + }, + }, + Storage: types3_5.Storage{ + Disks: []types3_5.Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolP(true), + Partitions: []types3_5.Partition{ + { + Label: util.StrP("var"), + Number: 1, + SizeMiB: util.IntP(5000), + StartMiB: util.IntP(2048), + TypeGUID: &aUUID, + GUID: &aUUID, + WipePartitionEntry: util.BoolP(true), + ShouldExist: util.BoolP(true), + }, + }, + }, + }, + Raid: []types3_5.Raid{ + { + Name: "array", + Level: util.StrP("raid10"), + Devices: []types3_5.Device{"/dev/sdb", "/dev/sdc"}, + Spares: util.IntP(1), + Options: []types3_5.RaidOption{"foobar"}, + }, + }, + Filesystems: []types3_5.Filesystem{ + { + Path: util.StrP("/var"), + Device: "/dev/disk/by-partlabel/var", + Format: util.StrP("xfs"), + WipeFilesystem: util.BoolP(true), + Label: util.StrP("var"), + UUID: &aUUID, + Options: []types3_5.FilesystemOption{"rw"}, + }, + }, + Files: []types3_5.File{ + { + Node: types3_5.Node{ + Path: "/var/varfile", + Overwrite: util.BoolPStrict(false), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + FileEmbedded1: types3_5.FileEmbedded1{ + Mode: util.IntP(420), + Append: []types3_5.Resource{ + { + Compression: util.StrP("gzip"), + Source: util.StrP("https://example.com"), + Verification: types3_5.Verification{ + Hash: &aSha512Hash, + }, + HTTPHeaders: types3_5.HTTPHeaders{ + types3_5.HTTPHeader{ + Name: "Authorization", + Value: util.StrP("Basic YWxhZGRpbjpvcGVuc2VzYW1l"), + }, + types3_5.HTTPHeader{ + Name: "User-Agent", + Value: util.StrP("Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)"), + }, + }, + }, + }, + }, + }, + { + Node: types3_5.Node{ + Path: "/empty", + Overwrite: util.BoolPStrict(false), + }, + FileEmbedded1: types3_5.FileEmbedded1{ + Mode: util.IntP(420), + Contents: types3_5.Resource{ + Source: util.StrPStrict(""), + }, + }, + }, + }, + Directories: []types3_5.Directory{ + { + Node: types3_5.Node{ + Path: "/rootdir", + Overwrite: util.BoolP(true), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + DirectoryEmbedded1: types3_5.DirectoryEmbedded1{ + Mode: util.IntP(420), + }, + }, + }, + Links: []types3_5.Link{ + { + Node: types3_5.Node{ + Path: "/rootlink", + Overwrite: util.BoolP(true), + User: types3_5.NodeUser{ + ID: util.IntP(1000), + }, + Group: types3_5.NodeGroup{ + Name: util.StrP("groupname"), + }, + }, + LinkEmbedded1: types3_5.LinkEmbedded1{ + Hard: util.BoolP(false), + Target: util.StrP("/foobar"), + }, + }, + }, + }, + } + downtranslateConfig3_3 = types3_3.Config{ Ignition: types3_3.Ignition{ Version: "3.3.0", @@ -2554,6 +2894,34 @@ func TestTranslate3_4to3_3(t *testing.T) { }) assert.Error(t, err) } +func TestTranslate3_5to3_4(t *testing.T) { + emptyConfig := types3_5.Config{ + Ignition: types3_5.Ignition{ + Version: "3.5.0", + }, + } + + _, err := v35tov34.Translate(emptyConfig) + if err != nil { + t.Fatalf("Failed translation: %v", err) + } + + res, err := v35tov34.Translate(nonexhaustiveConfig3_4) + if err != nil { + t.Fatalf("Failed translation: %v", err) + } + assert.Equal(t, downtranslateConfig3_3, res) + + // Translation with unsupported `Cex` type + _, err = v35tov34.Translate(types3_5.Config{ + Ignition: types3_5.Ignition{ + Version: "3.5.0", + }, + }) + assert.Error(t, err) + assert.ErrorContains(t, err, "'Cex' type is not supported in spec v3.4") + +} func TestRemoveDuplicateFilesUnitsUsers2_3(t *testing.T) { mode := 420 diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go new file mode 100644 index 0000000..b34f5f5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/cex.go @@ -0,0 +1,33 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (cm Cex) IsPresent() bool { + return util.IsTrue(cm.Enabled) +} + +func (cx Cex) Validate(c path.ContextPath) (r report.Report) { + if !util.IsTrue(cx.Enabled) { + return + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go new file mode 100644 index 0000000..68887d4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/clevis.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (c Clevis) IsPresent() bool { + return util.NotEmpty(c.Custom.Pin) || + len(c.Tang) > 0 || + util.IsTrue(c.Tpm2) || + c.Threshold != nil && *c.Threshold != 0 +} + +func (cu ClevisCustom) Validate(c path.ContextPath) (r report.Report) { + if util.NilOrEmpty(cu.Pin) && util.NilOrEmpty(cu.Config) && !util.IsTrue(cu.NeedsNetwork) { + return + } + if util.NotEmpty(cu.Pin) { + switch *cu.Pin { + case "tpm2", "tang", "sss": + default: + r.AddOnError(c.Append("pin"), errors.ErrUnknownClevisPin) + } + } else { + r.AddOnError(c.Append("pin"), errors.ErrClevisPinRequired) + } + if util.NilOrEmpty(cu.Config) { + r.AddOnError(c.Append("config"), errors.ErrClevisConfigRequired) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go new file mode 100644 index 0000000..659657b --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/config.go @@ -0,0 +1,64 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +var ( + MaxVersion = semver.Version{ + Major: 3, + Minor: 5, + } +) + +func (cfg Config) Validate(c path.ContextPath) (r report.Report) { + systemdPath := "/etc/systemd/system/" + unitPaths := map[string]struct{}{} + for _, unit := range cfg.Systemd.Units { + if !util.NilOrEmpty(unit.Contents) { + pathString := systemdPath + unit.Name + unitPaths[pathString] = struct{}{} + } + for _, dropin := range unit.Dropins { + if !util.NilOrEmpty(dropin.Contents) { + pathString := systemdPath + unit.Name + ".d/" + dropin.Name + unitPaths[pathString] = struct{}{} + } + } + } + for i, f := range cfg.Storage.Files { + if _, exists := unitPaths[f.Path]; exists { + r.AddOnError(c.Append("storage", "files", i, "path"), errors.ErrPathConflictsSystemd) + } + } + for i, d := range cfg.Storage.Directories { + if _, exists := unitPaths[d.Path]; exists { + r.AddOnError(c.Append("storage", "directories", i, "path"), errors.ErrPathConflictsSystemd) + } + } + for i, l := range cfg.Storage.Links { + if _, exists := unitPaths[l.Path]; exists { + r.AddOnError(c.Append("storage", "links", i, "path"), errors.ErrPathConflictsSystemd) + } + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go new file mode 100644 index 0000000..a10ce97 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/device.go @@ -0,0 +1,25 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Device) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c, validatePath(string(d))) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go new file mode 100644 index 0000000..f6f0684 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/directory.go @@ -0,0 +1,26 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Directory) Validate(c path.ContextPath) (r report.Report) { + r.Merge(d.Node.Validate(c)) + r.AddOnError(c.Append("mode"), validateMode(d.Mode)) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go new file mode 100644 index 0000000..8caf849 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/disk.go @@ -0,0 +1,135 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (d Disk) Key() string { + return d.Device +} + +func (n Disk) Validate(c path.ContextPath) (r report.Report) { + if len(n.Device) == 0 { + r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) + return + } + r.AddOnError(c.Append("device"), validatePath(n.Device)) + + if collides, p := n.partitionNumbersCollide(); collides { + r.AddOnError(c.Append("partitions", p), errors.ErrPartitionNumbersCollide) + } + if overlaps, p := n.partitionsOverlap(); overlaps { + r.AddOnError(c.Append("partitions", p), errors.ErrPartitionsOverlap) + } + if n.partitionsMixZeroesAndNonexistence() { + r.AddOnError(c.Append("partitions"), errors.ErrZeroesWithShouldNotExist) + } + if collides, p := n.partitionLabelsCollide(); collides { + r.AddOnError(c.Append("partitions", p), errors.ErrDuplicateLabels) + } + return +} + +// partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. It also returns the +// index of the colliding partition +func (n Disk) partitionNumbersCollide() (bool, int) { + m := map[int][]int{} // from partition number to index into array + for i, p := range n.Partitions { + if p.Number != 0 { + // a number of 0 means next available number, multiple devices can specify this + m[p.Number] = append(m[p.Number], i) + } + } + for _, n := range m { + if len(n) > 1 { + // TODO(vc): return information describing the collision for logging + return true, n[1] + } + } + return false, 0 +} + +func (d Disk) partitionLabelsCollide() (bool, int) { + m := map[string]struct{}{} + for i, p := range d.Partitions { + if p.Label != nil { + // a number of 0 means next available number, multiple devices can specify this + if _, exists := m[*p.Label]; exists { + return true, i + } + m[*p.Label] = struct{}{} + } + } + return false, 0 +} + +// end returns the last sector of a partition. Only used by partitionsOverlap. Requires non-nil Start and Size. +func (p Partition) end() int { + if *p.SizeMiB == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return *p.StartMiB + } + return *p.StartMiB + *p.SizeMiB - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap. It also returns the index of +// the overlapping partition +func (n Disk) partitionsOverlap() (bool, int) { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.StartMiB == nil || p.SizeMiB == nil || *p.StartMiB == 0 { + continue + } + + for i, o := range n.Partitions { + if o.StartMiB == nil || o.SizeMiB == nil || p == o || *o.StartMiB == 0 { + continue + } + + // is p.StartMiB within o? + if *p.StartMiB >= *o.StartMiB && *p.StartMiB <= o.end() { + return true, i + } + + // is p.end() within o? + if p.end() >= *o.StartMiB && p.end() <= o.end() { + return true, i + } + + // do p.StartMiB and p.end() straddle o? + if *p.StartMiB < *o.StartMiB && p.end() > o.end() { + return true, i + } + } + } + return false, 0 +} + +func (n Disk) partitionsMixZeroesAndNonexistence() bool { + hasZero := false + hasShouldNotExist := false + for _, p := range n.Partitions { + hasShouldNotExist = hasShouldNotExist || util.IsFalse(p.ShouldExist) + hasZero = hasZero || (p.Number == 0) + } + return hasZero && hasShouldNotExist +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go new file mode 100644 index 0000000..9b71bb2 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/file.go @@ -0,0 +1,43 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (f File) Validate(c path.ContextPath) (r report.Report) { + r.Merge(f.Node.Validate(c)) + r.AddOnError(c.Append("mode"), validateMode(f.Mode)) + r.AddOnError(c.Append("overwrite"), f.validateOverwrite()) + return +} + +func (f File) validateOverwrite() error { + if util.IsTrue(f.Overwrite) && f.Contents.Source == nil { + return errors.ErrOverwriteAndNilSource + } + return nil +} + +func (f FileEmbedded1) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Append": {}, + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go new file mode 100644 index 0000000..c722b36 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/filesystem.go @@ -0,0 +1,106 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (f Filesystem) Key() string { + return f.Device +} + +func (f Filesystem) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + "MountOptions": {}, + } +} + +func (f Filesystem) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("path"), f.validatePath()) + r.AddOnError(c.Append("device"), validatePath(f.Device)) + r.AddOnError(c.Append("format"), f.validateFormat()) + r.AddOnError(c.Append("label"), f.validateLabel()) + return +} + +func (f Filesystem) validatePath() error { + return validatePathNilOK(f.Path) +} + +func (f Filesystem) validateFormat() error { + if util.NilOrEmpty(f.Format) { + if util.NotEmpty(f.Path) || + util.NotEmpty(f.Label) || + util.NotEmpty(f.UUID) || + util.IsTrue(f.WipeFilesystem) || + len(f.MountOptions) != 0 || + len(f.Options) != 0 { + return errors.ErrFormatNilWithOthers + } + } else { + switch *f.Format { + case "ext4", "btrfs", "xfs", "swap", "vfat", "none": + default: + return errors.ErrFilesystemInvalidFormat + } + } + return nil +} + +func (f Filesystem) validateLabel() error { + if util.NilOrEmpty(f.Label) { + return nil + } + if util.NilOrEmpty(f.Format) { + return errors.ErrLabelNeedsFormat + } + + switch *f.Format { + case "ext4": + if len(*f.Label) > 16 { + // source: man mkfs.ext4 + return errors.ErrExt4LabelTooLong + } + case "btrfs": + if len(*f.Label) > 256 { + // source: man mkfs.btrfs + return errors.ErrBtrfsLabelTooLong + } + case "xfs": + if len(*f.Label) > 12 { + // source: man mkfs.xfs + return errors.ErrXfsLabelTooLong + } + case "swap": + // mkswap's man page does not state a limit on label size, but through + // experimentation it appears that mkswap will truncate long labels to + // 15 characters, so let's enforce that. + if len(*f.Label) > 15 { + return errors.ErrSwapLabelTooLong + } + case "vfat": + if len(*f.Label) > 11 { + // source: man mkfs.fat + return errors.ErrVfatLabelTooLong + } + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go new file mode 100644 index 0000000..be1aada --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/headers.go @@ -0,0 +1,65 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/http" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +// Parse generates standard net/http headers from the data in HTTPHeaders +func (hs HTTPHeaders) Parse() (http.Header, error) { + headers := http.Header{} + for _, header := range hs { + if header.Name == "" { + return nil, errors.ErrEmptyHTTPHeaderName + } + if header.Value == nil || string(*header.Value) == "" { + return nil, errors.ErrInvalidHTTPHeader + } + headers.Add(header.Name, string(*header.Value)) + } + return headers, nil +} + +func (h HTTPHeader) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("name"), h.validateName()) + r.AddOnError(c.Append("value"), h.validateValue()) + return +} + +func (h HTTPHeader) validateName() error { + if h.Name == "" { + return errors.ErrEmptyHTTPHeaderName + } + return nil +} + +func (h HTTPHeader) validateValue() error { + if h.Value == nil { + return nil + } + if string(*h.Value) == "" { + return errors.ErrInvalidHTTPHeader + } + return nil +} + +func (h HTTPHeader) Key() string { + return h.Name +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go new file mode 100644 index 0000000..190445b --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/ignition.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/go-semver/semver" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (v Ignition) Semver() (*semver.Version, error) { + return semver.NewVersion(v.Version) +} + +func (ic IgnitionConfig) Validate(c path.ContextPath) (r report.Report) { + for i, res := range ic.Merge { + r.AddOnError(c.Append("merge", i), res.validateRequiredSource()) + } + return +} + +func (v Ignition) Validate(c path.ContextPath) (r report.Report) { + c = c.Append("version") + tv, err := v.Semver() + if err != nil { + r.AddOnError(c, errors.ErrInvalidVersion) + return + } + + if MaxVersion != *tv { + r.AddOnError(c, errors.ErrUnknownVersion) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go new file mode 100644 index 0000000..42c2940 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/kargs.go @@ -0,0 +1,22 @@ +// Copyright 2021 Red Hat, Inc. +// +// 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 types + +func (k KernelArguments) MergedKeys() map[string]string { + return map[string]string{ + "ShouldExist": "KernelArgument", + "ShouldNotExist": "KernelArgument", + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go new file mode 100644 index 0000000..e4c1d68 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/luks.go @@ -0,0 +1,82 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (l Luks) Key() string { + return l.Name +} + +func (l Luks) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + } +} + +func (l Luks) Validate(c path.ContextPath) (r report.Report) { + if strings.Contains(l.Name, "/") { + r.AddOnError(c.Append("name"), errors.ErrLuksNameContainsSlash) + } + r.AddOnError(c.Append("label"), l.validateLabel()) + if util.NilOrEmpty(l.Device) { + r.AddOnError(c.Append("device"), errors.ErrDiskDeviceRequired) + } else { + r.AddOnError(c.Append("device"), validatePath(*l.Device)) + } + + if util.NotEmpty(l.Clevis.Custom.Pin) && (len(l.Clevis.Tang) > 0 || util.IsTrue(l.Clevis.Tpm2) || (l.Clevis.Threshold != nil && *l.Clevis.Threshold != 0)) { + r.AddOnError(c.Append("clevis"), errors.ErrClevisCustomWithOthers) + } + + // fail if a key file is provided and is not valid + if err := validateURLNilOK(l.KeyFile.Source); err != nil { + r.AddOnError(c.Append("keys"), errors.ErrInvalidLuksKeyFile) + } + + // fail if Cex use with Clevis + if l.Clevis.IsPresent() && l.Cex.IsPresent() { + r.AddOnError(c.Append("cex"), errors.ErrCexWithClevis) + } + + // fail if key file is provided along with Cex + if l.Cex.IsPresent() && util.NotEmpty(l.KeyFile.Source) { + r.AddOnError(c.Append("cex"), errors.ErrCexWithKeyFile) + } + + return +} + +func (l Luks) validateLabel() error { + if util.NilOrEmpty(l.Label) { + return nil + } + + if len(*l.Label) > 47 { + // LUKS2_LABEL_L has a maximum length of 48 (including the null terminator) + // https://gitlab.com/cryptsetup/cryptsetup/-/blob/1633f030e89ad2f11ae649ba9600997a41abd3fc/lib/luks2/luks2.h#L86 + return errors.ErrLuksLabelTooLong + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go new file mode 100644 index 0000000..9eb7573 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/mode.go @@ -0,0 +1,26 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" +) + +func validateMode(m *int) error { + if m != nil && (*m < 0 || *m > 07777) { + return errors.ErrFileIllegalMode + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go new file mode 100644 index 0000000..248276e --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/node.go @@ -0,0 +1,59 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (n Node) Key() string { + return n.Path +} + +func (n Node) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c.Append("path"), validatePath(n.Path)) + return +} + +func (n Node) Depth() int { + count := 0 + for p := path.Clean(string(n.Path)); p != "/"; count++ { + p = path.Dir(p) + } + return count +} + +func validateIDorName(id *int, name *string) error { + if id != nil && util.NotEmpty(name) { + return errors.ErrBothIDAndNameSet + } + return nil +} + +func (nu NodeUser) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c, validateIDorName(nu.ID, nu.Name)) + return +} + +func (ng NodeGroup) Validate(c vpath.ContextPath) (r report.Report) { + r.AddOnError(c, validateIDorName(ng.ID, ng.Name)) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go new file mode 100644 index 0000000..1b2d97e --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/partition.go @@ -0,0 +1,91 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "fmt" + "regexp" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) + +var ( + guidRegex = regexp.MustCompile(guidRegexStr) +) + +func (p Partition) Key() string { + if p.Number != 0 { + return fmt.Sprintf("number:%d", p.Number) + } else if p.Label != nil { + return fmt.Sprintf("label:%s", *p.Label) + } else { + return "" + } +} + +func (p Partition) Validate(c path.ContextPath) (r report.Report) { + if util.IsFalse(p.ShouldExist) && + (p.Label != nil || util.NotEmpty(p.TypeGUID) || util.NotEmpty(p.GUID) || p.StartMiB != nil || p.SizeMiB != nil) { + r.AddOnError(c, errors.ErrShouldNotExistWithOthers) + } + if p.Number == 0 && p.Label == nil { + r.AddOnError(c, errors.ErrNeedLabelOrNumber) + } + + r.AddOnError(c.Append("label"), p.validateLabel()) + r.AddOnError(c.Append("guid"), validateGUID(p.GUID)) + r.AddOnError(c.Append("typeGuid"), validateGUID(p.TypeGUID)) + return +} + +func (p Partition) validateLabel() error { + if p.Label == nil { + return nil + } + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(*p.Label) > 36 { + return errors.ErrLabelTooLong + } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(*p.Label, ":") { + return errors.ErrLabelContainsColon + } + return nil +} + +func validateGUID(guidPointer *string) error { + if guidPointer == nil { + return nil + } + guid := *guidPointer + if ok := guidRegex.MatchString(guid); !ok { + return errors.ErrDoesntMatchGUIDRegex + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go new file mode 100644 index 0000000..4060a2a --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/passwd.go @@ -0,0 +1,23 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +func (p PasswdUser) Key() string { + return p.Name +} + +func (g PasswdGroup) Key() string { + return g.Name +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go new file mode 100644 index 0000000..131e300 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/path.go @@ -0,0 +1,42 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" +) + +func validatePath(p string) error { + if p == "" { + return errors.ErrNoPath + } + if !path.IsAbs(p) { + return errors.ErrPathRelative + } + if path.Clean(p) != p { + return errors.ErrDirtyPath + } + return nil +} + +func validatePathNilOK(p *string) error { + if util.NilOrEmpty(p) { + return nil + } + return validatePath(*p) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go new file mode 100644 index 0000000..d48d210 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/proxy.go @@ -0,0 +1,49 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (p Proxy) Validate(c path.ContextPath) (r report.Report) { + validateProxyURL(p.HTTPProxy, c.Append("httpProxy"), &r, true) + validateProxyURL(p.HTTPSProxy, c.Append("httpsProxy"), &r, false) + return +} + +func validateProxyURL(s *string, p path.ContextPath, r *report.Report, httpOk bool) { + if s == nil { + return + } + u, err := url.Parse(*s) + if err != nil { + r.AddOnError(p, errors.ErrInvalidUrl) + return + } + + if u.Scheme != "https" && u.Scheme != "http" { + r.AddOnError(p, errors.ErrInvalidProxy) + return + } + if u.Scheme == "http" && !httpOk { + r.AddOnWarn(p, errors.ErrInsecureProxy) + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go new file mode 100644 index 0000000..9d69aa3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/raid.go @@ -0,0 +1,62 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (r Raid) Key() string { + return r.Name +} + +func (r Raid) IgnoreDuplicates() map[string]struct{} { + return map[string]struct{}{ + "Options": {}, + } +} + +func (ra Raid) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("level"), ra.validateLevel()) + if len(ra.Devices) == 0 { + r.AddOnError(c.Append("devices"), errors.ErrRaidDevicesRequired) + } + return +} + +func (r Raid) validateLevel() error { + if util.NilOrEmpty(r.Level) { + return errors.ErrRaidLevelRequired + } + switch *r.Level { + case "linear", "raid0", "0", "stripe": + if r.Spares != nil && *r.Spares != 0 { + return errors.ErrSparesUnsupportedForLevel + } + case "raid1", "1", "mirror": + case "raid4", "4": + case "raid5", "5": + case "raid6", "6": + case "raid10", "10": + default: + return errors.ErrUnrecognizedRaidLevel + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go new file mode 100644 index 0000000..68da6c7 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/resource.go @@ -0,0 +1,91 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (res Resource) Key() string { + if res.Source == nil { + return "" + } + return *res.Source +} + +func (res Resource) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("compression"), res.validateCompression()) + r.AddOnError(c.Append("verification", "hash"), res.validateVerification()) + r.AddOnError(c.Append("source"), validateURLNilOK(res.Source)) + r.AddOnError(c.Append("httpHeaders"), res.validateSchemeForHTTPHeaders()) + return +} + +func (res Resource) validateCompression() error { + if res.Compression != nil { + switch *res.Compression { + case "", "gzip": + default: + return errors.ErrCompressionInvalid + } + } + return nil +} + +func (res Resource) validateVerification() error { + if res.Verification.Hash != nil && res.Source == nil { + return errors.ErrVerificationAndNilSource + } + return nil +} + +func (res Resource) validateSchemeForHTTPHeaders() error { + if len(res.HTTPHeaders) < 1 { + return nil + } + + if util.NilOrEmpty(res.Source) { + return errors.ErrInvalidUrl + } + + u, err := url.Parse(*res.Source) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https": + return nil + default: + return errors.ErrUnsupportedSchemeForHTTPHeaders + } +} + +// Ensure that the Source is specified and valid. This is not called by +// Resource.Validate() because some structs that embed Resource don't +// require Source to be specified. Containing structs that require Source +// should call this function from their Validate(). +func (res Resource) validateRequiredSource() error { + if util.NilOrEmpty(res.Source) { + return errors.ErrSourceRequired + } + return validateURL(*res.Source) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go new file mode 100644 index 0000000..6c8c42f --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/schema.go @@ -0,0 +1,264 @@ +package types + +// generated by "schematyper --package=types config/v3_5/schema/ignition.json -o config/v3_5/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Cex struct { + Enabled *bool `json:"enabled,omitempty"` +} + +type Clevis struct { + Custom ClevisCustom `json:"custom,omitempty"` + Tang []Tang `json:"tang,omitempty"` + Threshold *int `json:"threshold,omitempty"` + Tpm2 *bool `json:"tpm2,omitempty"` +} + +type ClevisCustom struct { + Config *string `json:"config,omitempty"` + NeedsNetwork *bool `json:"needsNetwork,omitempty"` + Pin *string `json:"pin,omitempty"` +} + +type Config struct { + Ignition Ignition `json:"ignition"` + KernelArguments KernelArguments `json:"kernelArguments,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode *int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable *bool `json:"wipeTable,omitempty"` +} + +type Dropin struct { + Contents *string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileEmbedded1 struct { + Append []Resource `json:"append,omitempty"` + Contents Resource `json:"contents,omitempty"` + Mode *int `json:"mode,omitempty"` +} + +type Filesystem struct { + Device string `json:"device"` + Format *string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + MountOptions []MountOption `json:"mountOptions,omitempty"` + Options []FilesystemOption `json:"options,omitempty"` + Path *string `json:"path,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem *bool `json:"wipeFilesystem,omitempty"` +} + +type FilesystemOption string + +type Group string + +type HTTPHeader struct { + Name string `json:"name"` + Value *string `json:"value,omitempty"` +} + +type HTTPHeaders []HTTPHeader + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Proxy Proxy `json:"proxy,omitempty"` + Security Security `json:"security,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version"` +} + +type IgnitionConfig struct { + Merge []Resource `json:"merge,omitempty"` + Replace Resource `json:"replace,omitempty"` +} + +type KernelArgument string + +type KernelArguments struct { + ShouldExist []KernelArgument `json:"shouldExist,omitempty"` + ShouldNotExist []KernelArgument `json:"shouldNotExist,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard *bool `json:"hard,omitempty"` + Target *string `json:"target,omitempty"` +} + +type Luks struct { + Cex Cex `json:"cex,omitempty"` + Clevis Clevis `json:"clevis,omitempty"` + Device *string `json:"device,omitempty"` + Discard *bool `json:"discard,omitempty"` + KeyFile Resource `json:"keyFile,omitempty"` + Label *string `json:"label,omitempty"` + Name string `json:"name"` + OpenOptions []OpenOption `json:"openOptions,omitempty"` + Options []LuksOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeVolume *bool `json:"wipeVolume,omitempty"` +} + +type LuksOption string + +type MountOption string + +type NoProxyItem string + +type Node struct { + Group NodeGroup `json:"group,omitempty"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path"` + User NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name *string `json:"name,omitempty"` +} + +type OpenOption string + +type Partition struct { + GUID *string `json:"guid,omitempty"` + Label *string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Resize *bool `json:"resize,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + SizeMiB *int `json:"sizeMiB,omitempty"` + StartMiB *int `json:"startMiB,omitempty"` + TypeGUID *string `json:"typeGuid,omitempty"` + WipePartitionEntry *bool `json:"wipePartitionEntry,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name"` + PasswordHash *string `json:"passwordHash,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + System *bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Gecos *string `json:"gecos,omitempty"` + Groups []Group `json:"groups,omitempty"` + HomeDir *string `json:"homeDir,omitempty"` + Name string `json:"name"` + NoCreateHome *bool `json:"noCreateHome,omitempty"` + NoLogInit *bool `json:"noLogInit,omitempty"` + NoUserGroup *bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup *string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell *string `json:"shell,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + System *bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type Proxy struct { + HTTPProxy *string `json:"httpProxy,omitempty"` + HTTPSProxy *string `json:"httpsProxy,omitempty"` + NoProxy []NoProxyItem `json:"noProxy,omitempty"` +} + +type Raid struct { + Devices []Device `json:"devices,omitempty"` + Level *string `json:"level,omitempty"` + Name string `json:"name"` + Options []RaidOption `json:"options,omitempty"` + Spares *int `json:"spares,omitempty"` +} + +type RaidOption string + +type Resource struct { + Compression *string `json:"compression,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source *string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type SSHAuthorizedKey string + +type Security struct { + TLS TLS `json:"tls,omitempty"` +} + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Luks []Luks `json:"luks,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type TLS struct { + CertificateAuthorities []Resource `json:"certificateAuthorities,omitempty"` +} + +type Tang struct { + Advertisement *string `json:"advertisement,omitempty"` + Thumbprint *string `json:"thumbprint,omitempty"` + URL string `json:"url,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents *string `json:"contents,omitempty"` + Dropins []Dropin `json:"dropins,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask *bool `json:"mask,omitempty"` + Name string `json:"name"` +} + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go new file mode 100644 index 0000000..20cb730 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/storage.go @@ -0,0 +1,115 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (s Storage) MergedKeys() map[string]string { + return map[string]string{ + "Directories": "Node", + "Files": "Node", + "Links": "Node", + } +} + +func (s Storage) Validate(c vpath.ContextPath) (r report.Report) { + s.validateDirectories(c, &r) + s.validateFiles(c, &r) + s.validateLinks(c, &r) + s.validateFilesystems(c, &r) + return +} + +func (s Storage) validateDirectories(c vpath.ContextPath, r *report.Report) { + for i, d := range s.Directories { + for _, l := range s.Links { + if strings.HasPrefix(d.Path, l.Path+"/") { + r.AddOnError(c.Append("directories", i), errors.ErrDirectoryUsedSymlink) + } + } + } +} + +func (s Storage) validateFiles(c vpath.ContextPath, r *report.Report) { + for i, f := range s.Files { + for _, l := range s.Links { + if strings.HasPrefix(f.Path, l.Path+"/") { + r.AddOnError(c.Append("files", i), errors.ErrFileUsedSymlink) + } + } + } +} + +func (s Storage) validateLinks(c vpath.ContextPath, r *report.Report) { + for i, l1 := range s.Links { + for _, l2 := range s.Links { + if strings.HasPrefix(l1.Path, l2.Path+"/") { + r.AddOnError(c.Append("links", i), errors.ErrLinkUsedSymlink) + } + } + if util.NilOrEmpty(l1.Target) { + r.AddOnError(c.Append("links", i, "target"), errors.ErrLinkTargetRequired) + continue + } + if !util.IsTrue(l1.Hard) { + continue + } + target := path.Clean(*l1.Target) + if !path.IsAbs(target) { + target = path.Join(l1.Path, *l1.Target) + } + for _, d := range s.Directories { + if target == d.Path { + r.AddOnError(c.Append("links", i), errors.ErrHardLinkToDirectory) + } + } + ownerCheck := func(ok bool, path vpath.ContextPath) { + if !ok { + r.AddOnWarn(path, errors.ErrHardLinkSpecifiesOwner) + } + } + ownerCheck(l1.User.ID == nil, c.Append("links", i, "user", "id")) + ownerCheck(l1.User.Name == nil, c.Append("links", i, "user", "name")) + ownerCheck(l1.Group.ID == nil, c.Append("links", i, "group", "id")) + ownerCheck(l1.Group.Name == nil, c.Append("links", i, "group", "name")) + } +} + +func (s Storage) validateFilesystems(c vpath.ContextPath, r *report.Report) { + disks := make(map[string]Disk) + for _, d := range s.Disks { + disks[d.Device] = d + } + + for i, f := range s.Filesystems { + disk, exist := disks[f.Device] + if exist { + if len(disk.Partitions) > 0 { + r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrPartitionsOverwritten) + } else if !util.IsTrue(f.WipeFilesystem) && util.IsTrue(disk.WipeTable) { + r.AddOnWarn(c.Append("filesystems", i, "device"), errors.ErrFilesystemImplicitWipe) + } + } + } +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go new file mode 100644 index 0000000..ac521ba --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/systemd.go @@ -0,0 +1,61 @@ +// Copyright 2022 Red Hat, Inc. +// +// 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 types + +import ( + "regexp" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/shared/parse" + "github.com/coreos/ignition/v2/config/util" + + vpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (s Systemd) Validate(c vpath.ContextPath) (r report.Report) { + units := make(map[string]Unit) + checkInstanceUnit := regexp.MustCompile(`^(.+?)@(.+?)\.service$`) + for _, d := range s.Units { + units[d.Name] = d + } + for index, unit := range s.Units { + if checkInstanceUnit.MatchString(unit.Name) && util.IsTrue(unit.Enabled) { + instUnitSlice := checkInstanceUnit.FindSubmatch([]byte(unit.Name)) + instantiableUnit := string(instUnitSlice[1]) + "@.service" + if _, ok := units[instantiableUnit]; ok && util.NotEmpty(units[instantiableUnit].Contents) { + foundInstallSection := false + // we're doing a separate validation pass on each unit to identify + // if an instantiable unit has the install section. So logging an + // `AddOnError` will produce duplicate errors on bad unit contents + // because we're already doing that while validating a unit separately. + opts, err := parse.ParseUnitContents(units[instantiableUnit].Contents) + if err != nil { + continue + } + for _, section := range opts { + if section.Section == "Install" { + foundInstallSection = true + break + } + } + if !foundInstallSection { + r.AddOnWarn(c.Append("units", index, "contents"), errors.NewNoInstallSectionForInstantiableUnitError(instantiableUnit, unit.Name)) + } + } + } + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go new file mode 100644 index 0000000..1839d6c --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tang.go @@ -0,0 +1,65 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "encoding/json" + "net/url" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (t Tang) Key() string { + return t.URL +} + +func (t Tang) Validate(c path.ContextPath) (r report.Report) { + r.AddOnError(c.Append("url"), validateTangURL(t.URL)) + if util.NilOrEmpty(t.Thumbprint) { + r.AddOnError(c.Append("thumbprint"), errors.ErrTangThumbprintRequired) + } + r.AddOnError(c.Append("advertisement"), validateTangAdvertisement(t.Advertisement)) + return +} + +func validateTangURL(s string) error { + u, err := url.Parse(s) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https": + return nil + default: + return errors.ErrInvalidScheme + } +} + +func validateTangAdvertisement(s *string) error { + if util.NotEmpty(s) { + var adv any + err := json.Unmarshal([]byte(*s), &adv) + if err != nil { + return errors.ErrInvalidTangAdvertisement + } + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go new file mode 100644 index 0000000..8890e39 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/tls.go @@ -0,0 +1,27 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (tls TLS) Validate(c path.ContextPath) (r report.Report) { + for i, ca := range tls.CertificateAuthorities { + r.AddOnError(c.Append("certificateAuthorities", i), ca.validateRequiredSource()) + } + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go new file mode 100644 index 0000000..c5ee1e8 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/unit.go @@ -0,0 +1,68 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "path" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/shared/parse" + "github.com/coreos/ignition/v2/config/shared/validations" + "github.com/coreos/ignition/v2/config/util" + + cpath "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +func (u Unit) Key() string { + return u.Name +} + +func (d Dropin) Key() string { + return d.Name +} + +func (u Unit) Validate(c cpath.ContextPath) (r report.Report) { + r.AddOnError(c.Append("name"), validateName(u.Name)) + c = c.Append("contents") + opts, err := parse.ParseUnitContents(u.Contents) + r.AddOnError(c, err) + + r.AddOnWarn(c, validations.ValidateInstallSection(u.Name, util.IsTrue(u.Enabled), util.NilOrEmpty(u.Contents), opts)) + + return +} + +func validateName(name string) error { + switch path.Ext(name) { + case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": + default: + return errors.ErrInvalidSystemdExt + } + return nil +} + +func (d Dropin) Validate(c cpath.ContextPath) (r report.Report) { + _, err := parse.ParseUnitContents(d.Contents) + r.AddOnError(c.Append("contents"), err) + + switch path.Ext(d.Name) { + case ".conf": + default: + r.AddOnError(c.Append("name"), errors.ErrInvalidSystemdDropinExt) + } + + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go new file mode 100644 index 0000000..3ca189d --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/url.go @@ -0,0 +1,83 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "net/url" + "strings" + + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/vincent-petithory/dataurl" + + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" +) + +func validateURL(s string) error { + u, err := url.Parse(s) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https", "tftp", "gs": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "arn": + fullURL := u.Scheme + ":" + u.Opaque + if !arn.IsARN(fullURL) { + return errors.ErrInvalidS3ARN + } + s3arn, err := arn.Parse(fullURL) + if err != nil { + return err + } + if s3arn.Service != "s3" { + return errors.ErrInvalidS3ARN + } + urlSplit := strings.Split(fullURL, "/") + if strings.HasPrefix(s3arn.Resource, "accesspoint/") && len(urlSplit) < 3 { + return errors.ErrInvalidS3ARN + } else if len(urlSplit) < 2 { + return errors.ErrInvalidS3ARN + } + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "data": + if _, err := dataurl.DecodeString(s); err != nil { + return err + } + return nil + default: + return errors.ErrInvalidScheme + } +} + +func validateURLNilOK(s *string) error { + if util.NilOrEmpty(s) { + return nil + } + return validateURL(*s) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go new file mode 100644 index 0000000..5def6f0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5/types/verification.go @@ -0,0 +1,71 @@ +// Copyright 2020 Red Hat, Inc. +// +// 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 types + +import ( + "crypto" + "encoding/hex" + "strings" + + "github.com/coreos/ignition/v2/config/shared/errors" + + "github.com/coreos/vcontext/path" + "github.com/coreos/vcontext/report" +) + +// HashParts will return the sum and function (in that order) of the hash stored +// in this Verification, or an error if there is an issue during parsing. +func (v Verification) HashParts() (string, string, error) { + if v.Hash == nil { + // The hash can be nil + return "", "", nil + } + parts := strings.SplitN(*v.Hash, "-", 2) + if len(parts) != 2 { + return "", "", errors.ErrHashMalformed + } + + return parts[0], parts[1], nil +} + +func (v Verification) Validate(c path.ContextPath) (r report.Report) { + c = c.Append("hash") + if v.Hash == nil { + // The hash can be nil + return + } + + function, sum, err := v.HashParts() + if err != nil { + r.AddOnError(c, err) + return + } + var hash crypto.Hash + switch function { + case "sha512": + hash = crypto.SHA512 + case "sha256": + hash = crypto.SHA256 + default: + r.AddOnError(c, errors.ErrHashUnrecognized) + return + } + + if len(sum) != hex.EncodedLen(hash.Size()) { + r.AddOnError(c, errors.ErrHashWrongSize) + } + + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 078a64a..104cd7c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -57,6 +57,7 @@ github.com/coreos/ignition/v2/config/v3_1/types github.com/coreos/ignition/v2/config/v3_2/types github.com/coreos/ignition/v2/config/v3_3/types github.com/coreos/ignition/v2/config/v3_4/types +github.com/coreos/ignition/v2/config/v3_5/types github.com/coreos/ignition/v2/config/validate # github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 ## explicit; go 1.18 @@ -83,3 +84,4 @@ go4.org/errorutil # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 +# github.com/coreos/ign-converter/translate/v34tov35 => ./translate/v35tov34 From b4cb29a30868f5d4ccfe3482415181b429b2b054 Mon Sep 17 00:00:00 2001 From: Yasmin Valim Date: Thu, 21 Nov 2024 11:00:42 -0300 Subject: [PATCH 3/3] Add unit tests --- translate/v35tov34/v35tov34.go | 4 +- translate_test.go | 108 ++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 52 deletions(-) diff --git a/translate/v35tov34/v35tov34.go b/translate/v35tov34/v35tov34.go index 12572ea..edbc1db 100644 --- a/translate/v35tov34/v35tov34.go +++ b/translate/v35tov34/v35tov34.go @@ -24,9 +24,9 @@ import ( "github.com/coreos/ignition/v2/config/validate" ) -// Copy of github.com/coreos/ignition/v2/config/v3_4/translate/translate.go +// Copy of github.com/coreos/ignition/v2/config/v3_5/translate/translate.go // with the types & old_types imports reversed (the referenced file translates -// from 3.4 -> 3.5 but as a result only touches fields that are understood by +// from 3.5 -> 3.4 but as a result only touches fields that are understood by // the 3.4 spec). func translateIgnition(old old_types.Ignition) (ret types.Ignition) { // use a new translator so we don't recurse infinitely diff --git a/translate_test.go b/translate_test.go index c03eb17..7825fab 100644 --- a/translate_test.go +++ b/translate_test.go @@ -1857,56 +1857,56 @@ var ( }, } - downtranslateConfig3_4 = types3_5.Config{ - Ignition: types3_5.Ignition{ - Version: "3.5.0", - Config: types3_5.IgnitionConfig{ - Merge: []types3_5.Resource{ + downtranslateConfig3_4 = types3_4.Config{ + Ignition: types3_4.Ignition{ + Version: "3.4.0", + Config: types3_4.IgnitionConfig{ + Merge: []types3_4.Resource{ { Source: util.StrP("https://example.com"), - Verification: types3_5.Verification{ + Verification: types3_4.Verification{ Hash: &aSha512Hash, }, }, }, - Replace: types3_5.Resource{ + Replace: types3_4.Resource{ Source: util.StrP("https://example.com"), - Verification: types3_5.Verification{ + Verification: types3_4.Verification{ Hash: &aSha512Hash, }, }, }, - Timeouts: types3_5.Timeouts{ + Timeouts: types3_4.Timeouts{ HTTPResponseHeaders: util.IntP(5), HTTPTotal: util.IntP(10), }, - Security: types3_5.Security{ - TLS: types3_5.TLS{ - CertificateAuthorities: []types3_5.Resource{ + Security: types3_4.Security{ + TLS: types3_4.TLS{ + CertificateAuthorities: []types3_4.Resource{ { Source: util.StrP("https://example.com"), - Verification: types3_5.Verification{ + Verification: types3_4.Verification{ Hash: &aSha512Hash, }, }, }, }, }, - Proxy: types3_5.Proxy{ + Proxy: types3_4.Proxy{ HTTPProxy: util.StrP("https://proxy.example.net/"), HTTPSProxy: util.StrP("https://secure.proxy.example.net/"), - NoProxy: []types3_5.NoProxyItem{ + NoProxy: []types3_4.NoProxyItem{ "www.example.net", "www.example2.net", }, }, }, - Storage: types3_5.Storage{ - Disks: []types3_5.Disk{ + Storage: types3_4.Storage{ + Disks: []types3_4.Disk{ { Device: "/dev/sda", WipeTable: util.BoolP(true), - Partitions: []types3_5.Partition{ + Partitions: []types3_4.Partition{ { Label: util.StrP("var"), Number: 1, @@ -1920,16 +1920,16 @@ var ( }, }, }, - Raid: []types3_5.Raid{ + Raid: []types3_4.Raid{ { Name: "array", Level: util.StrP("raid10"), - Devices: []types3_5.Device{"/dev/sdb", "/dev/sdc"}, + Devices: []types3_4.Device{"/dev/sdb", "/dev/sdc"}, Spares: util.IntP(1), - Options: []types3_5.RaidOption{"foobar"}, + Options: []types3_4.RaidOption{"foobar"}, }, }, - Filesystems: []types3_5.Filesystem{ + Filesystems: []types3_4.Filesystem{ { Path: util.StrP("/var"), Device: "/dev/disk/by-partlabel/var", @@ -1937,36 +1937,36 @@ var ( WipeFilesystem: util.BoolP(true), Label: util.StrP("var"), UUID: &aUUID, - Options: []types3_5.FilesystemOption{"rw"}, + Options: []types3_4.FilesystemOption{"rw"}, }, }, - Files: []types3_5.File{ + Files: []types3_4.File{ { - Node: types3_5.Node{ + Node: types3_4.Node{ Path: "/var/varfile", Overwrite: util.BoolPStrict(false), - User: types3_5.NodeUser{ + User: types3_4.NodeUser{ ID: util.IntP(1000), }, - Group: types3_5.NodeGroup{ + Group: types3_4.NodeGroup{ Name: util.StrP("groupname"), }, }, - FileEmbedded1: types3_5.FileEmbedded1{ + FileEmbedded1: types3_4.FileEmbedded1{ Mode: util.IntP(420), - Append: []types3_5.Resource{ + Append: []types3_4.Resource{ { Compression: util.StrP("gzip"), Source: util.StrP("https://example.com"), - Verification: types3_5.Verification{ + Verification: types3_4.Verification{ Hash: &aSha512Hash, }, - HTTPHeaders: types3_5.HTTPHeaders{ - types3_5.HTTPHeader{ + HTTPHeaders: types3_4.HTTPHeaders{ + types3_4.HTTPHeader{ Name: "Authorization", Value: util.StrP("Basic YWxhZGRpbjpvcGVuc2VzYW1l"), }, - types3_5.HTTPHeader{ + types3_4.HTTPHeader{ Name: "User-Agent", Value: util.StrP("Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)"), }, @@ -1976,48 +1976,48 @@ var ( }, }, { - Node: types3_5.Node{ + Node: types3_4.Node{ Path: "/empty", Overwrite: util.BoolPStrict(false), }, - FileEmbedded1: types3_5.FileEmbedded1{ + FileEmbedded1: types3_4.FileEmbedded1{ Mode: util.IntP(420), - Contents: types3_5.Resource{ + Contents: types3_4.Resource{ Source: util.StrPStrict(""), }, }, }, }, - Directories: []types3_5.Directory{ + Directories: []types3_4.Directory{ { - Node: types3_5.Node{ + Node: types3_4.Node{ Path: "/rootdir", Overwrite: util.BoolP(true), - User: types3_5.NodeUser{ + User: types3_4.NodeUser{ ID: util.IntP(1000), }, - Group: types3_5.NodeGroup{ + Group: types3_4.NodeGroup{ Name: util.StrP("groupname"), }, }, - DirectoryEmbedded1: types3_5.DirectoryEmbedded1{ + DirectoryEmbedded1: types3_4.DirectoryEmbedded1{ Mode: util.IntP(420), }, }, }, - Links: []types3_5.Link{ + Links: []types3_4.Link{ { - Node: types3_5.Node{ + Node: types3_4.Node{ Path: "/rootlink", Overwrite: util.BoolP(true), - User: types3_5.NodeUser{ + User: types3_4.NodeUser{ ID: util.IntP(1000), }, - Group: types3_5.NodeGroup{ + Group: types3_4.NodeGroup{ Name: util.StrP("groupname"), }, }, - LinkEmbedded1: types3_5.LinkEmbedded1{ + LinkEmbedded1: types3_4.LinkEmbedded1{ Hard: util.BoolP(false), Target: util.StrP("/foobar"), }, @@ -2895,6 +2895,7 @@ func TestTranslate3_4to3_3(t *testing.T) { assert.Error(t, err) } func TestTranslate3_5to3_4(t *testing.T) { + emptyConfig := types3_5.Config{ Ignition: types3_5.Ignition{ Version: "3.5.0", @@ -2906,21 +2907,28 @@ func TestTranslate3_5to3_4(t *testing.T) { t.Fatalf("Failed translation: %v", err) } - res, err := v35tov34.Translate(nonexhaustiveConfig3_4) + res, err := v35tov34.Translate(nonexhaustiveConfig3_5) if err != nil { t.Fatalf("Failed translation: %v", err) } - assert.Equal(t, downtranslateConfig3_3, res) + assert.Equal(t, downtranslateConfig3_4, res) // Translation with unsupported `Cex` type _, err = v35tov34.Translate(types3_5.Config{ Ignition: types3_5.Ignition{ Version: "3.5.0", }, + Storage: types3_5.Storage{ + Luks: []types3_5.Luks{ + { + Cex: types3_5.Cex{ + Enabled: util.BoolP(true), + }, + }, + }, + }, }) assert.Error(t, err) - assert.ErrorContains(t, err, "'Cex' type is not supported in spec v3.4") - } func TestRemoveDuplicateFilesUnitsUsers2_3(t *testing.T) {