From d532226f1c009b76e375a69fd73a8cdb6bf0533a Mon Sep 17 00:00:00 2001 From: Steven Presti Date: Fri, 9 Feb 2024 12:00:33 -0500 Subject: [PATCH] base/v0_6_exp: add parent directory sugar Add a field called 'Parent' which is used to specify a file's parent directory. When a parent is specified, all directories from the parent to the file will be created, with the 'mode' supplied in the parent directory. Co-authored-by: Yasmin Valim Co-authored-by: Joseph Corchado Co-authored-by: Adam Piasecki --- base/v0_6_exp/schema.go | 6 +++ base/v0_6_exp/translate.go | 72 +++++++++++++++++++++++++++++++-- base/v0_6_exp/translate_test.go | 64 +++++++++++++++++++++++++++++ docs/release-notes.md | 2 + 4 files changed, 140 insertions(+), 4 deletions(-) diff --git a/base/v0_6_exp/schema.go b/base/v0_6_exp/schema.go index 67e7b95c..e9ffc223 100644 --- a/base/v0_6_exp/schema.go +++ b/base/v0_6_exp/schema.go @@ -67,6 +67,12 @@ type File struct { Append []Resource `yaml:"append"` Contents Resource `yaml:"contents"` Mode *int `yaml:"mode"` + Parent Parent `yaml:"parent"` +} + +type Parent struct { + Path *string `yaml:"path"` + Mode *int `yaml:"mode"` } type Filesystem struct { diff --git a/base/v0_6_exp/translate.go b/base/v0_6_exp/translate.go index 8cf2395f..789613fd 100644 --- a/base/v0_6_exp/translate.go +++ b/base/v0_6_exp/translate.go @@ -83,9 +83,7 @@ func (c Config) ToIgn3_5Unvalidated(options common.TranslateOptions) (types.Conf tr := translate.NewTranslator("yaml", "json", options) tr.AddCustomTranslator(translateIgnition) - tr.AddCustomTranslator(translateFile) - tr.AddCustomTranslator(translateDirectory) - tr.AddCustomTranslator(translateLink) + tr.AddCustomTranslator(translateStorage) tr.AddCustomTranslator(translateResource) tr.AddCustomTranslator(translatePasswdUser) tr.AddCustomTranslator(translateUnit) @@ -99,7 +97,6 @@ func (c Config) ToIgn3_5Unvalidated(options common.TranslateOptions) (types.Conf translate.MergeP(tr, tm, &r, "systemd", &c.Systemd, &ret.Systemd) c.addMountUnits(&ret, &tm) - tm2, r2 := c.processTrees(&ret, options) tm.Merge(tm2) r.Merge(r2) @@ -121,6 +118,64 @@ func translateIgnition(from Ignition, options common.TranslateOptions) (to types return } +func translateStorage(from Storage, options common.TranslateOptions) (to types.Storage, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tr.AddCustomTranslator(translateFile) + tr.AddCustomTranslator(translateDirectory) + tr.AddCustomTranslator(translateLink) + tr.AddCustomTranslator(translateLuks) + tm, r = translate.Prefixed(tr, "directories", &from.Directories, &to.Directories) + translate.MergeP(tr, tm, &r, "disks", &from.Disks, &to.Disks) + translate.MergeP(tr, tm, &r, "files", &from.Files, &to.Files) + translate.MergeP(tr, tm, &r, "filesystems", &from.Filesystems, &to.Filesystems) + translate.MergeP(tr, tm, &r, "links", &from.Links, &to.Links) + translate.MergeP(tr, tm, &r, "luks", &from.Luks, &to.Luks) + translate.MergeP(tr, tm, &r, "raid", &from.Raid, &to.Raid) + for _, file := range from.Files { + if util.NotEmpty(file.Parent.Path) { + c := path.New("yaml", "parent") + parentDirectory := types.Directory{ + Node: types.Node{ + Path: *file.Parent.Path, + Group: types.NodeGroup{ID: file.Group.ID, Name: file.Group.Name}, + User: types.NodeUser{ID: file.User.ID, Name: file.User.Name}, + }, + DirectoryEmbedded1: types.DirectoryEmbedded1{ + Mode: file.Parent.Mode, + }, + } + to.Directories = append(to.Directories, parentDirectory) + // find what is between parent and file path + theInBetween := strings.Replace(file.Path, *file.Parent.Path, "", 1) + + workingDirectory := *file.Parent.Path + // render all directories between the filepath and the parent with the parent's mode + arrayDirectory := strings.Split(theInBetween, "/") + for i := 0; i < len(arrayDirectory)-1; i++ { + dirTobeCreated := arrayDirectory[i] + if dirTobeCreated == "" { + continue + } + workingDirectory += "/" + dirTobeCreated + directoryToBeRendered := types.Directory{ + Node: types.Node{ + Path: workingDirectory, + Group: types.NodeGroup{ID: file.Group.ID, Name: file.Group.Name}, + User: types.NodeUser{ID: file.User.ID, Name: file.User.Name}, + }, + DirectoryEmbedded1: types.DirectoryEmbedded1{ + Mode: file.Parent.Mode, + }, + } + to.Directories = append(to.Directories, directoryToBeRendered) + } + tm.AddFromCommonSource(c, path.New("json", "directories"), to.Directories) + } + + } + return +} + func translateFile(from File, options common.TranslateOptions) (to types.File, tm translate.TranslationSet, r report.Report) { tr := translate.NewTranslator("yaml", "json", options) tr.AddCustomTranslator(translateResource) @@ -134,6 +189,15 @@ func translateFile(from File, options common.TranslateOptions) (to types.File, t return } +func translateLuks(from Luks, options common.TranslateOptions) (to types.Luks, tm translate.TranslationSet, r report.Report) { + tr := translate.NewTranslator("yaml", "json", options) + tm, r = translate.Prefixed(tr, "clevis", &from.Clevis, &to.Clevis) + translate.MergeP(tr, tm, &r, "device", &from.Device, &to.Device) + translate.MergeP(tr, tm, &r, "name", &from.Name, &to.Name) + translate.MergeP(tr, tm, &r, "wipe_volume", &from.WipeVolume, &to.WipeVolume) + return +} + func translateResource(from Resource, options common.TranslateOptions) (to types.Resource, tm translate.TranslationSet, r report.Report) { tr := translate.NewTranslator("yaml", "json", options) tm, r = translate.Prefixed(tr, "verification", &from.Verification, &to.Verification) diff --git a/base/v0_6_exp/translate_test.go b/base/v0_6_exp/translate_test.go index cf718d4a..87a05b8a 100644 --- a/base/v0_6_exp/translate_test.go +++ b/base/v0_6_exp/translate_test.go @@ -599,6 +599,70 @@ func TestTranslateFile(t *testing.T) { }) } } +func TestTranslateStorage(t *testing.T) { + tests := []struct { + in Storage + out types.Storage + }{ + { + Storage{ + Files: []File{ + { + Path: "/foo/bar/txt.txt", + Contents: Resource{}, + Mode: util.IntToPtr(420), + Parent: Parent{ + Path: util.StrToPtr("/foo"), + Mode: util.IntToPtr(420), + }, + }, + }, + }, + types.Storage{ + Files: []types.File{ + { + Node: types.Node{ + Path: "/foo/bar/txt.txt", + }, + FileEmbedded1: types.FileEmbedded1{ + Mode: util.IntToPtr(420), + Contents: types.Resource{}, + }, + }, + }, + Directories: []types.Directory{ + { + Node: types.Node{ + Path: "/foo", + }, + DirectoryEmbedded1: types.DirectoryEmbedded1{ + Mode: util.IntToPtr(420), + }, + }, + { + Node: types.Node{ + Path: "/foo/bar", + }, + DirectoryEmbedded1: types.DirectoryEmbedded1{ + Mode: util.IntToPtr(420), + }, + }, + }, + }, + }, + } + + for i, test := range tests { + t.Run(fmt.Sprintf("translate %d", i), func(t *testing.T) { + actual, translations, r := translateStorage(test.in, common.TranslateOptions{}) + r = confutil.TranslateReportPaths(r, translations) + baseutil.VerifyReport(t, test.in, r) + assert.Equal(t, test.out, actual, "translation mismatch") + assert.Equal(t, report.Report{}, r, "non-empty report") + assert.NoError(t, translations.DebugVerifyCoverage(actual), "incomplete TranslationSet coverage") + }) + } +} // TestTranslateDirectory tests translating the ct storage.directories.[i] entries to ignition storage.directories.[i] entires. func TestTranslateDirectory(t *testing.T) { diff --git a/docs/release-notes.md b/docs/release-notes.md index 25eda216..fea93a7a 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -13,6 +13,8 @@ nav_order: 9 ### Features - Support s390x layouts in `boot_device` section (fcos 1.6.0-exp, openshift 4.15.0-exp) +- Add `parent` field to `files`, to reduce verbosity when configuring a deeply + nested file. _(base 0.6.0-exp)_ ### Bug fixes