diff --git a/base/v0_6_exp/validate.go b/base/v0_6_exp/validate.go index ad3917be..9f4c7586 100644 --- a/base/v0_6_exp/validate.go +++ b/base/v0_6_exp/validate.go @@ -18,7 +18,9 @@ import ( baseutil "github.com/coreos/butane/base/util" "github.com/coreos/butane/config/common" + "github.com/coreos/ignition/v2/config/shared/errors" "github.com/coreos/ignition/v2/config/util" + exp "github.com/coreos/ignition/v2/config/v3_5_experimental" "github.com/coreos/vcontext/path" "github.com/coreos/vcontext/report" ) @@ -26,24 +28,67 @@ import ( func (rs Resource) Validate(c path.ContextPath) (r report.Report) { var field string sources := 0 - if rs.Local != nil { + var config string + var butaneReport report.Report + switch { + case rs.Local != nil: sources++ - field = "local" - } - if rs.Inline != nil { + if field == "" { + field = "local" + config = *rs.Local + } + fallthrough + case rs.Inline != nil: sources++ - field = "inline" - } - if rs.Source != nil { + if field == "" { + field = "inline" + config = *rs.Inline + } + fallthrough + case rs.Source != nil: sources++ field = "source" } if sources > 1 { r.AddOnError(c.Append(field), common.ErrTooManyResourceSources) } + if field == "local" || field == "inline" { + // check if it's an ignition config, will fix error on fcos + if len(config) > 0 && config[0] != '{' { + _, report, err := exp.Parse([]byte(config)) + if len(report.Entries) > 0 { + butaneReport = MapIgnitionReportToButane(report) + // convert report into butane specific report then merge it + r.Merge(butaneReport) + } + if err != nil { + if err == errors.ErrUnknownVersion { + r.AddOnError(c.Append(field), errors.ErrUnknownVersion) + } + } + } else { + r.AddOnError(c.Append(field), common.ErrNoFilesDir) + } + + } + return } +func MapIgnitionReportToButane(ignitionReport report.Report) report.Report { + var butaneRep report.Report + for _, entry := range ignitionReport.Entries { + butaneEntry := report.Entry{ + Kind: entry.Kind, + Message: entry.Message, + Context: entry.Context, + Marker: entry.Marker, + } + butaneRep.Entries = append(butaneRep.Entries, butaneEntry) + } + return butaneRep +} + func (fs Filesystem) Validate(c path.ContextPath) (r report.Report) { if !util.IsTrue(fs.WithMountUnit) { return diff --git a/base/v0_6_exp/validate_test.go b/base/v0_6_exp/validate_test.go index 78e72910..d7e2bb28 100644 --- a/base/v0_6_exp/validate_test.go +++ b/base/v0_6_exp/validate_test.go @@ -52,7 +52,7 @@ func TestValidateResource(t *testing.T) { // inline specified { Resource{ - Inline: util.StrToPtr("hello"), + // Inline: util.StrToPtr("hello"), Compression: util.StrToPtr("gzip"), Verification: Verification{ Hash: util.StrToPtr("this isn't validated"), @@ -64,7 +64,7 @@ func TestValidateResource(t *testing.T) { // local specified { Resource{ - Local: util.StrToPtr("hello"), + // Local: util.StrToPtr("hello"), Compression: util.StrToPtr("gzip"), Verification: Verification{ Hash: util.StrToPtr("this isn't validated"), @@ -90,7 +90,7 @@ func TestValidateResource(t *testing.T) { { Resource{ Source: util.StrToPtr("data:,hello"), - Local: util.StrToPtr("hello"), + Local: util.StrToPtr("{\"ignition\": {\"version\": \"3.5.0\"}}"), Compression: util.StrToPtr("gzip"), Verification: Verification{ Hash: util.StrToPtr("this isn't validated"), @@ -103,21 +103,21 @@ func TestValidateResource(t *testing.T) { { Resource{ Inline: util.StrToPtr("hello"), - Local: util.StrToPtr("hello"), + Local: util.StrToPtr("{\"ignition\": {\"version\": \"3.5.0\"}}"), Compression: util.StrToPtr("gzip"), Verification: Verification{ Hash: util.StrToPtr("this isn't validated"), }, }, common.ErrTooManyResourceSources, - path.New("yaml", "inline"), + path.New("yaml", "source"), }, // source + inline + local, invalid { Resource{ Source: util.StrToPtr("data:,hello"), - Inline: util.StrToPtr("hello"), - Local: util.StrToPtr("hello"), + Inline: util.StrToPtr("{\"ignition\": {\"version\": \"3.5.0\"}}"), + Local: util.StrToPtr("{\"ignition\": {\"version\": \"3.5.0\"}}"), Compression: util.StrToPtr("gzip"), Verification: Verification{ Hash: util.StrToPtr("this isn't validated"), @@ -139,6 +139,9 @@ func TestValidateResource(t *testing.T) { } } +func TestMapperFunction(t *testing.T) { + +} func TestValidateTree(t *testing.T) { tests := []struct { in Tree diff --git a/config/common/errors.go b/config/common/errors.go index a5f8d5b2..1831094a 100644 --- a/config/common/errors.go +++ b/config/common/errors.go @@ -34,6 +34,7 @@ var ( ErrRhcosVariantUnsupported = errors.New("rhcos variant has been removed; use openshift variant instead: https://coreos.github.io/butane/upgrading-openshift/") // resources and trees + ErrEmptyReport = errors.New("error merging report, report empty") ErrTooManyResourceSources = errors.New("only one of the following can be set: inline, local, source") ErrFilesDirEscape = errors.New("local file path traverses outside the files directory") ErrFileType = errors.New("trees may only contain files, directories, and symlinks") diff --git a/docs/release-notes.md b/docs/release-notes.md index f7596971..f9f8e187 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -21,6 +21,7 @@ key](https://getfedora.org/security/). openshift 4.14.0-exp)_ - Require `storage.filesystems.path` to start with `/etc` or `/var` if `with_mount_unit` is true _(fcos 1.6.0-exp, openshift 4.14.0-exp)_ +- Validate merged/replaced ignition configs if they are local/inline _(fcos 1.6.0-exp)_ ### Bug fixes diff --git a/vendor/github.com/coreos/ignition/v2/config/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/translate/translate.go new file mode 100644 index 00000000..05d8ce2c --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/translate/translate.go @@ -0,0 +1,187 @@ +// Copyright 2019 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 translate + +import ( + "fmt" + "reflect" + + "github.com/coreos/ignition/v2/config/util" +) + +/* + * This is an automatic translator that replace boilerplate code to copy one + * struct into a nearly identical struct in another package. To use it first + * call NewTranslator() to get a translator instance. This can then have + * additional translation rules (in the form of functions) to translate from + * types in one struct to the other. Those functions are in the form: + * func(typeFromInputStruct) -> typeFromOutputStruct + * These can be closures that reference the translator as well. This allows for + * manually translating some fields but resuming automatic translation on the + * other fields through the Translator.Translate() function. + */ + +// Returns if this type can be translated without a custom translator. Children or other +// ancestors might require custom translators however +func (t translator) translatable(t1, t2 reflect.Type) bool { + k1 := t1.Kind() + k2 := t2.Kind() + if k1 != k2 { + return false + } + switch { + case util.IsPrimitive(k1): + return true + case util.IsInvalidInConfig(k1): + panic(fmt.Sprintf("Encountered invalid kind %s in config. This is a bug, please file a report", k1)) + case k1 == reflect.Ptr || k1 == reflect.Slice: + return t.translatable(t1.Elem(), t2.Elem()) || t.hasTranslator(t1.Elem(), t2.Elem()) + case k1 == reflect.Struct: + return t.translatableStruct(t1, t2) + default: + panic(fmt.Sprintf("Encountered unknown kind %s in config. This is a bug, please file a report", k1)) + } +} + +// precondition: t1, t2 are both of Kind 'struct' +func (t translator) translatableStruct(t1, t2 reflect.Type) bool { + if t1.NumField() != t2.NumField() || t1.Name() != t2.Name() { + return false + } + for i := 0; i < t1.NumField(); i++ { + t1f := t1.Field(i) + t2f, ok := t2.FieldByName(t1f.Name) + + if !ok { + return false + } + if !t.translatable(t1f.Type, t2f.Type) && !t.hasTranslator(t1f.Type, t2f.Type) { + return false + } + } + return true +} + +// checks that t could reasonably be the type of a translator function +func couldBeValidTranslator(t reflect.Type) bool { + if t.Kind() != reflect.Func { + return false + } + if t.NumIn() != 1 || t.NumOut() != 1 { + return false + } + if util.IsInvalidInConfig(t.In(0).Kind()) || util.IsInvalidInConfig(t.Out(0).Kind()) { + return false + } + return true +} + +// translate from one type to another, but deep copy all data +// precondition: vFrom and vTo are the same type as defined by translatable() +// precondition: vTo is addressable and settable +func (t translator) translateSameType(vFrom, vTo reflect.Value) { + k := vFrom.Kind() + switch { + case util.IsPrimitive(k): + // Use convert, even if not needed; type alias to primitives are not + // directly assignable and calling Convert on primitives does no harm + vTo.Set(vFrom.Convert(vTo.Type())) + case k == reflect.Ptr: + if vFrom.IsNil() { + return + } + vTo.Set(reflect.New(vTo.Type().Elem())) + t.translate(vFrom.Elem(), vTo.Elem()) + case k == reflect.Slice: + if vFrom.IsNil() { + return + } + vTo.Set(reflect.MakeSlice(vTo.Type(), vFrom.Len(), vFrom.Len())) + for i := 0; i < vFrom.Len(); i++ { + t.translate(vFrom.Index(i), vTo.Index(i)) + } + case k == reflect.Struct: + for i := 0; i < vFrom.NumField(); i++ { + t.translate(vFrom.Field(i), vTo.FieldByName(vFrom.Type().Field(i).Name)) + } + default: + panic("Encountered types that are not the same when they should be. This is a bug, please file a report") + } +} + +// helper to return if a custom translator was defined +func (t translator) hasTranslator(tFrom, tTo reflect.Type) bool { + return t.getTranslator(tFrom, tTo).IsValid() +} + +// vTo must be addressable, should be acquired by calling reflect.ValueOf() on a variable of the correct type +func (t translator) translate(vFrom, vTo reflect.Value) { + tFrom := vFrom.Type() + tTo := vTo.Type() + if fnv := t.getTranslator(tFrom, tTo); fnv.IsValid() { + vTo.Set(fnv.Call([]reflect.Value{vFrom})[0]) + return + } + if t.translatable(tFrom, tTo) { + t.translateSameType(vFrom, vTo) + return + } + + panic(fmt.Sprintf("Translator not defined for %v to %v", tFrom, tTo)) +} + +type Translator interface { + AddCustomTranslator(t interface{}) + Translate(from, to interface{}) +} + +func NewTranslator() Translator { + return &translator{} +} + +type translator struct { + // List of custom translation funcs, must pass couldBeValidTranslator + // This is only for fields that cannot or should not be trivially translated, + // All trivially translated fields use the default behavior. + translators []reflect.Value +} + +func (t *translator) AddCustomTranslator(fn interface{}) { + fnv := reflect.ValueOf(fn) + if !couldBeValidTranslator(fnv.Type()) { + panic("Tried to register invalid translator function") + } + t.translators = append(t.translators, fnv) +} + +func (t translator) getTranslator(from, to reflect.Type) reflect.Value { + for _, fn := range t.translators { + if fn.Type().In(0) == from && fn.Type().Out(0) == to { + return fn + } + } + return reflect.Value{} +} + +func (t translator) Translate(from, to interface{}) { + fv := reflect.ValueOf(from) + tv := reflect.ValueOf(to) + if fv.Kind() != reflect.Ptr || tv.Kind() != reflect.Ptr { + panic("Translate needs to be called on pointers") + } + fv = fv.Elem() + tv = tv.Elem() + t.translate(fv, tv) +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_0/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_0/config.go new file mode 100644 index 00000000..ca32f7ad --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_0/config.go @@ -0,0 +1,73 @@ +// Copyright 2015 CoreOS, 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 v3_0 + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + "github.com/coreos/ignition/v2/config/v3_0/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.0.0 into +// a 3.0 types.Config struct and generates a report of any errors, warnings, +// info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + + return types.Config{}, report.Report{}, errors.ErrUnknownVersion +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_1/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_1/config.go new file mode 100644 index 00000000..a40ae56c --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_1/config.go @@ -0,0 +1,78 @@ +// Copyright 2019 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 v3_1 + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + prev "github.com/coreos/ignition/v2/config/v3_0" + "github.com/coreos/ignition/v2/config/v3_1/translate" + "github.com/coreos/ignition/v2/config/v3_1/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.1.0 or lesser +// into a 3.1 types.Config struct and generates a report of any errors, warnings, +// info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + prevCfg, r, err := prev.ParseCompatibleVersion(raw) + if err != nil { + return types.Config{}, r, err + } + return translate.Translate(prevCfg), r, nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_1/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/v3_1/translate/translate.go new file mode 100644 index 00000000..5921c42c --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_1/translate/translate.go @@ -0,0 +1,106 @@ +// Copyright 2019 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 translate + +import ( + "github.com/coreos/ignition/v2/config/translate" + "github.com/coreos/ignition/v2/config/util" + old_types "github.com/coreos/ignition/v2/config/v3_0/types" + "github.com/coreos/ignition/v2/config/v3_1/types" +) + +func translateFilesystem(old old_types.Filesystem) (ret types.Filesystem) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.Translate(&old.Device, &ret.Device) + tr.Translate(&old.Format, &ret.Format) + tr.Translate(&old.Label, &ret.Label) + tr.Translate(&old.Options, &ret.Options) + tr.Translate(&old.Path, &ret.Path) + tr.Translate(&old.UUID, &ret.UUID) + tr.Translate(&old.WipeFilesystem, &ret.WipeFilesystem) + return +} + +func translateConfigReference(old old_types.ConfigReference) (ret types.Resource) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.Translate(&old.Source, &ret.Source) + tr.Translate(&old.Verification, &ret.Verification) + return +} + +func translateCAReference(old old_types.CaReference) (ret types.Resource) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + ret.Source = util.StrToPtr(old.Source) + tr.Translate(&old.Verification, &ret.Verification) + return +} + +func translateFileContents(old old_types.FileContents) (ret types.Resource) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.Translate(&old.Compression, &ret.Compression) + tr.Translate(&old.Source, &ret.Source) + tr.Translate(&old.Verification, &ret.Verification) + return +} + +func translateIgnitionConfig(old old_types.IgnitionConfig) (ret types.IgnitionConfig) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateConfigReference) + tr.Translate(&old.Merge, &ret.Merge) + tr.Translate(&old.Replace, &ret.Replace) + return +} + +func translateSecurity(old old_types.Security) (ret types.Security) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateTLS) + tr.Translate(&old.TLS, &ret.TLS) + return +} + +func translateTLS(old old_types.TLS) (ret types.TLS) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateCAReference) + tr.Translate(&old.CertificateAuthorities, &ret.CertificateAuthorities) + return +} + +func translateIgnition(old old_types.Ignition) (ret types.Ignition) { + // use a new translator so we don't recurse infinitely + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnitionConfig) + tr.AddCustomTranslator(translateSecurity) + tr.Translate(&old.Config, &ret.Config) + tr.Translate(&old.Security, &ret.Security) + tr.Translate(&old.Timeouts, &ret.Timeouts) + ret.Version = types.MaxVersion.String() + return +} + +func Translate(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateFileContents) + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateFilesystem) + tr.Translate(&old, &ret) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_2/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_2/config.go new file mode 100644 index 00000000..c6c7d94d --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_2/config.go @@ -0,0 +1,78 @@ +// 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 v3_2 + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + prev "github.com/coreos/ignition/v2/config/v3_1" + "github.com/coreos/ignition/v2/config/v3_2/translate" + "github.com/coreos/ignition/v2/config/v3_2/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.2.0 or lesser +// into a 3.2 types.Config struct and generates a report of any errors, warnings, +// info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + prevCfg, r, err := prev.ParseCompatibleVersion(raw) + if err != nil { + return types.Config{}, r, err + } + return translate.Translate(prevCfg), r, nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_2/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/v3_2/translate/translate.go new file mode 100644 index 00000000..0fd4f420 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_2/translate/translate.go @@ -0,0 +1,90 @@ +// 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 translate + +import ( + "github.com/coreos/ignition/v2/config/translate" + old_types "github.com/coreos/ignition/v2/config/v3_1/types" + "github.com/coreos/ignition/v2/config/v3_2/types" +) + +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 translateStorage(old old_types.Storage) (ret types.Storage) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translatePartition) + tr.Translate(&old.Directories, &ret.Directories) + tr.Translate(&old.Disks, &ret.Disks) + tr.Translate(&old.Files, &ret.Files) + tr.Translate(&old.Filesystems, &ret.Filesystems) + tr.Translate(&old.Links, &ret.Links) + tr.Translate(&old.Raid, &ret.Raid) + return +} + +func translatePasswdUser(old old_types.PasswdUser) (ret types.PasswdUser) { + tr := translate.NewTranslator() + tr.Translate(&old.Gecos, &ret.Gecos) + tr.Translate(&old.Groups, &ret.Groups) + tr.Translate(&old.HomeDir, &ret.HomeDir) + tr.Translate(&old.Name, &ret.Name) + tr.Translate(&old.NoCreateHome, &ret.NoCreateHome) + tr.Translate(&old.NoLogInit, &ret.NoLogInit) + tr.Translate(&old.NoUserGroup, &ret.NoUserGroup) + tr.Translate(&old.PasswordHash, &ret.PasswordHash) + tr.Translate(&old.PrimaryGroup, &ret.PrimaryGroup) + tr.Translate(&old.SSHAuthorizedKeys, &ret.SSHAuthorizedKeys) + tr.Translate(&old.Shell, &ret.Shell) + tr.Translate(&old.System, &ret.System) + tr.Translate(&old.UID, &ret.UID) + return +} + +func translatePasswdGroup(old old_types.PasswdGroup) (ret types.PasswdGroup) { + tr := translate.NewTranslator() + tr.Translate(&old.Gid, &ret.Gid) + tr.Translate(&old.Name, &ret.Name) + tr.Translate(&old.PasswordHash, &ret.PasswordHash) + tr.Translate(&old.System, &ret.System) + return +} + +func translatePartition(old old_types.Partition) (ret types.Partition) { + tr := translate.NewTranslator() + tr.Translate(&old.GUID, &ret.GUID) + tr.Translate(&old.Label, &ret.Label) + tr.Translate(&old.Number, &ret.Number) + tr.Translate(&old.ShouldExist, &ret.ShouldExist) + tr.Translate(&old.SizeMiB, &ret.SizeMiB) + tr.Translate(&old.StartMiB, &ret.StartMiB) + tr.Translate(&old.TypeGUID, &ret.TypeGUID) + tr.Translate(&old.WipePartitionEntry, &ret.WipePartitionEntry) + return +} + +func Translate(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateStorage) + tr.AddCustomTranslator(translatePasswdUser) + tr.AddCustomTranslator(translatePasswdGroup) + tr.Translate(&old, &ret) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_3/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_3/config.go new file mode 100644 index 00000000..446ea67d --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_3/config.go @@ -0,0 +1,78 @@ +// 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 v3_3 + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + prev "github.com/coreos/ignition/v2/config/v3_2" + "github.com/coreos/ignition/v2/config/v3_3/translate" + "github.com/coreos/ignition/v2/config/v3_3/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.3.0 or +// lesser into a 3.3 types.Config struct and generates a report of any errors, +// warnings, info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + prevCfg, r, err := prev.ParseCompatibleVersion(raw) + if err != nil { + return types.Config{}, r, err + } + return translate.Translate(prevCfg), r, nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_3/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/v3_3/translate/translate.go new file mode 100644 index 00000000..656ad0a4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_3/translate/translate.go @@ -0,0 +1,95 @@ +// 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 translate + +import ( + "github.com/coreos/ignition/v2/config/translate" + "github.com/coreos/ignition/v2/config/util" + old_types "github.com/coreos/ignition/v2/config/v3_2/types" + "github.com/coreos/ignition/v2/config/v3_3/types" +) + +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 translateRaid(old old_types.Raid) (ret types.Raid) { + tr := translate.NewTranslator() + tr.Translate(&old.Devices, &ret.Devices) + ret.Level = util.StrToPtr(old.Level) + tr.Translate(&old.Name, &ret.Name) + tr.Translate(&old.Options, &ret.Options) + tr.Translate(&old.Spares, &ret.Spares) + return +} + +func translateLuks(old old_types.Luks) (ret types.Luks) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateClevis) + if old.Clevis != nil { + 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.Options, &ret.Options) + tr.Translate(&old.UUID, &ret.UUID) + tr.Translate(&old.WipeVolume, &ret.WipeVolume) + return +} + +func translateClevis(old old_types.Clevis) (ret types.Clevis) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateClevisCustom) + if old.Custom != nil { + tr.Translate(old.Custom, &ret.Custom) + } + tr.Translate(&old.Tang, &ret.Tang) + tr.Translate(&old.Threshold, &ret.Threshold) + tr.Translate(&old.Tpm2, &ret.Tpm2) + return +} + +func translateClevisCustom(old old_types.Custom) (ret types.ClevisCustom) { + tr := translate.NewTranslator() + ret.Config = util.StrToPtr(old.Config) + tr.Translate(&old.NeedsNetwork, &ret.NeedsNetwork) + ret.Pin = util.StrToPtr(old.Pin) + return +} + +func translateLinkEmbedded1(old old_types.LinkEmbedded1) (ret types.LinkEmbedded1) { + tr := translate.NewTranslator() + tr.Translate(&old.Hard, &ret.Hard) + ret.Target = util.StrToPtr(old.Target) + return +} + +func Translate(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateRaid) + tr.AddCustomTranslator(translateLuks) + tr.AddCustomTranslator(translateLinkEmbedded1) + tr.Translate(&old.Ignition, &ret.Ignition) + tr.Translate(&old.Passwd, &ret.Passwd) + tr.Translate(&old.Storage, &ret.Storage) + tr.Translate(&old.Systemd, &ret.Systemd) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_4/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_4/config.go new file mode 100644 index 00000000..e83abb0b --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_4/config.go @@ -0,0 +1,78 @@ +// 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 v3_4 + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + prev "github.com/coreos/ignition/v2/config/v3_3" + "github.com/coreos/ignition/v2/config/v3_4/translate" + "github.com/coreos/ignition/v2/config/v3_4/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.4.0 or +// lesser into a 3.4 types.Config struct and generates a report of any errors, +// warnings, info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + prevCfg, r, err := prev.ParseCompatibleVersion(raw) + if err != nil { + return types.Config{}, r, err + } + return translate.Translate(prevCfg), r, nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_4/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/v3_4/translate/translate.go new file mode 100644 index 00000000..5d748d82 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_4/translate/translate.go @@ -0,0 +1,85 @@ +// 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 translate + +import ( + "github.com/coreos/ignition/v2/config/translate" + "github.com/coreos/ignition/v2/config/util" + old_types "github.com/coreos/ignition/v2/config/v3_3/types" + "github.com/coreos/ignition/v2/config/v3_4/types" +) + +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 translateFileEmbedded1(old old_types.FileEmbedded1) (ret types.FileEmbedded1) { + tr := translate.NewTranslator() + tr.Translate(&old.Append, &ret.Append) + tr.Translate(&old.Contents, &ret.Contents) + if old.Mode != nil { + // We support the special mode bits for specs >=3.4.0, so if + // the user provides special mode bits in an Ignition config + // with the version < 3.4.0, then we need to explicitly mask + // those bits out during translation. + ret.Mode = util.IntToPtr(*old.Mode & ^07000) + } + return +} + +func translateDirectoryEmbedded1(old old_types.DirectoryEmbedded1) (ret types.DirectoryEmbedded1) { + if old.Mode != nil { + // We support the special mode bits for specs >=3.4.0, so if + // the user provides special mode bits in an Ignition config + // with the version < 3.4.0, then we need to explicitly mask + // those bits out during translation. + ret.Mode = util.IntToPtr(*old.Mode & ^07000) + } + 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.Options, &ret.Options) + 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 Translate(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnition) + tr.AddCustomTranslator(translateDirectoryEmbedded1) + tr.AddCustomTranslator(translateFileEmbedded1) + tr.AddCustomTranslator(translateLuks) + tr.Translate(&old, &ret) + return +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/config.go b/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/config.go new file mode 100644 index 00000000..9a92bf2a --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/config.go @@ -0,0 +1,78 @@ +// 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 v3_5_experimental + +import ( + "github.com/coreos/ignition/v2/config/merge" + "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/config/util" + prev "github.com/coreos/ignition/v2/config/v3_4" + "github.com/coreos/ignition/v2/config/v3_5_experimental/translate" + "github.com/coreos/ignition/v2/config/v3_5_experimental/types" + "github.com/coreos/ignition/v2/config/validate" + + "github.com/coreos/go-semver/semver" + "github.com/coreos/vcontext/report" +) + +func Merge(parent, child types.Config) types.Config { + res, _ := merge.MergeStructTranscribe(parent, child) + return res.(types.Config) +} + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if len(rawConfig) == 0 { + return types.Config{}, report.Report{}, errors.ErrEmpty + } + + var config types.Config + if rpt, err := util.HandleParseErrors(rawConfig, &config); err != nil { + return types.Config{}, rpt, err + } + + version, err := semver.NewVersion(config.Ignition.Version) + + if err != nil || *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateWithContext(config, rawConfig) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +// ParseCompatibleVersion parses the raw config of version 3.5.0-experimental or +// lesser into a 3.5-exp types.Config struct and generates a report of any errors, +// warnings, info, and deprecations it encountered +func ParseCompatibleVersion(raw []byte) (types.Config, report.Report, error) { + version, rpt, err := util.GetConfigVersion(raw) + if err != nil { + return types.Config{}, rpt, err + } + + if version == types.MaxVersion { + return Parse(raw) + } + prevCfg, r, err := prev.ParseCompatibleVersion(raw) + if err != nil { + return types.Config{}, r, err + } + return translate.Translate(prevCfg), r, nil +} diff --git a/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/translate/translate.go b/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/translate/translate.go new file mode 100644 index 00000000..5647e629 --- /dev/null +++ b/vendor/github.com/coreos/ignition/v2/config/v3_5_experimental/translate/translate.go @@ -0,0 +1,35 @@ +// 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 translate + +import ( + "github.com/coreos/ignition/v2/config/translate" + old_types "github.com/coreos/ignition/v2/config/v3_4/types" + "github.com/coreos/ignition/v2/config/v3_5_experimental/types" +) + +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 Translate(old old_types.Config) (ret types.Config) { + tr := translate.NewTranslator() + tr.AddCustomTranslator(translateIgnition) + tr.Translate(&old, &ret) + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d4ea6695..20d35e43 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -20,12 +20,24 @@ github.com/coreos/ignition/v2/config/merge 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/translate github.com/coreos/ignition/v2/config/util +github.com/coreos/ignition/v2/config/v3_0 github.com/coreos/ignition/v2/config/v3_0/types +github.com/coreos/ignition/v2/config/v3_1 +github.com/coreos/ignition/v2/config/v3_1/translate github.com/coreos/ignition/v2/config/v3_1/types +github.com/coreos/ignition/v2/config/v3_2 +github.com/coreos/ignition/v2/config/v3_2/translate github.com/coreos/ignition/v2/config/v3_2/types +github.com/coreos/ignition/v2/config/v3_3 +github.com/coreos/ignition/v2/config/v3_3/translate github.com/coreos/ignition/v2/config/v3_3/types +github.com/coreos/ignition/v2/config/v3_4 +github.com/coreos/ignition/v2/config/v3_4/translate github.com/coreos/ignition/v2/config/v3_4/types +github.com/coreos/ignition/v2/config/v3_5_experimental +github.com/coreos/ignition/v2/config/v3_5_experimental/translate github.com/coreos/ignition/v2/config/v3_5_experimental/types github.com/coreos/ignition/v2/config/validate # github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687