diff --git a/config/shared/errors/errors.go b/config/shared/errors/errors.go index 44852cb902..b0a52f8dcd 100644 --- a/config/shared/errors/errors.go +++ b/config/shared/errors/errors.go @@ -70,6 +70,8 @@ var ( ErrNoPath = errors.New("path not specified") ErrPathRelative = errors.New("path not absolute") ErrDirtyPath = errors.New("path is not fully simplified") + ErrPartitionsOverwritten = errors.New("filesystem overwrites partitioned device") + ErrFilesystemImplicitWipe = errors.New("device matches disk with wipeTable enabled; filesystem will be wiped") ErrRaidLevelRequired = errors.New("raid level is required") ErrSparesUnsupportedForLevel = errors.New("spares unsupported for linear and raid0 arrays") ErrUnrecognizedRaidLevel = errors.New("unrecognized raid level") diff --git a/config/v3_0/types/storage.go b/config/v3_0/types/storage.go index eac98e74b5..2fb1e53842 100644 --- a/config/v3_0/types/storage.go +++ b/config/v3_0/types/storage.go @@ -67,5 +67,20 @@ func (s Storage) Validate(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) + } + } + } return } diff --git a/config/v3_0/types/storage_test.go b/config/v3_0/types/storage_test.go index 00c5861af1..f869e57d5d 100644 --- a/config/v3_0/types/storage_test.go +++ b/config/v3_0/types/storage_test.go @@ -25,7 +25,7 @@ import ( "github.com/coreos/vcontext/report" ) -func TestStorageValidate(t *testing.T) { +func TestStorageValidateErrors(t *testing.T) { tests := []struct { in Storage at path.ContextPath @@ -148,3 +148,104 @@ func TestStorageValidate(t *testing.T) { } } } + +func TestStorageValidateWarnings(t *testing.T) { + tests := []struct { + in Storage + at path.ContextPath + out error + }{ + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + Partitions: []Partition{ + {}, {}, + }, + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrPartitionsOverwritten, + at: path.New("", "filesystems", 0, "device"), + }, + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(true), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + WipeFilesystem: nil, + }, + }, + }, + out: errors.ErrFilesystemImplicitWipe, + at: path.New("", "filesystems", 0, "device"), + }, + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(false), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: nil, + }, + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sdb", + }, + }, + }, + out: nil, + }, + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: nil, + }, + } + + for i, test := range tests { + r := test.in.Validate(path.ContextPath{}) + expected := report.Report{} + expected.AddOnWarn(test.at, test.out) + if !reflect.DeepEqual(expected, r) { + t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) + } + } +} diff --git a/config/v3_1/types/storage.go b/config/v3_1/types/storage.go index eac98e74b5..2fb1e53842 100644 --- a/config/v3_1/types/storage.go +++ b/config/v3_1/types/storage.go @@ -67,5 +67,20 @@ func (s Storage) Validate(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) + } + } + } return } diff --git a/config/v3_1/types/storage_test.go b/config/v3_1/types/storage_test.go index 00c5861af1..05ac694e58 100644 --- a/config/v3_1/types/storage_test.go +++ b/config/v3_1/types/storage_test.go @@ -25,16 +25,18 @@ import ( "github.com/coreos/vcontext/report" ) -func TestStorageValidate(t *testing.T) { +func TestStorageValidateErrors(t *testing.T) { tests := []struct { in Storage at path.ContextPath out error }{ + // test empty storage config returns nil { in: Storage{}, out: nil, }, + // test a storage config with no conflicting paths returns nil { in: Storage{ Links: []Link{ @@ -58,6 +60,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a file uses a configured symlink path returns ErrFileUsedSymlink { in: Storage{ Links: []Link{ @@ -74,6 +77,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrFileUsedSymlink, at: path.New("", "files", 0), }, + // test when a directory uses a configured symlink path returns ErrDirectoryUsedSymlink { in: Storage{ Links: []Link{ @@ -90,6 +94,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrDirectoryUsedSymlink, at: path.New("", "directories", 0), }, + // test the same path listed for two separate symlinks returns ErrLinkUsedSymlink { in: Storage{ Links: []Link{ @@ -104,6 +109,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkUsedSymlink, at: path.New("", "links", 1), }, + // test that two symlinks can be configured at a time { in: Storage{ Links: []Link{ @@ -117,6 +123,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a directory uses a configured symlink with the 'Hard:= true' returns ErrHardLinkToDirectory { in: Storage{ Links: []Link{ @@ -148,3 +155,94 @@ func TestStorageValidate(t *testing.T) { } } } + +func TestStorageValidateWarnings(t *testing.T) { + tests := []struct { + in Storage + at path.ContextPath + out error + }{ + // test a disk with saved partitions with the same 'device' as a filesystem returns ErrPartitionsOverwritten + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + Partitions: []Partition{ + {}, {}, + }, + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrPartitionsOverwritten, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=true' as a configured filesystem returns ErrFilesystemImplicitWipe + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(true), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + WipeFilesystem: util.BoolToPtr(false), + }, + }, + }, + out: errors.ErrFilesystemImplicitWipe, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=false' as a configured filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(false), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + WipeFilesystem: util.BoolToPtr(false), + }, + }, + }, + out: nil, + }, + // test a disk with no saved partitions with the same 'device' as a filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sdb", + }, + }, + }, + out: nil, + }, + } + + for i, test := range tests { + r := test.in.Validate(path.ContextPath{}) + expected := report.Report{} + expected.AddOnWarn(test.at, test.out) + if !reflect.DeepEqual(expected, r) { + t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) + } + } +} diff --git a/config/v3_2/types/storage.go b/config/v3_2/types/storage.go index fd1b8cecf6..c9cf447236 100644 --- a/config/v3_2/types/storage.go +++ b/config/v3_2/types/storage.go @@ -67,5 +67,20 @@ func (s Storage) Validate(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) + } + } + } return } diff --git a/config/v3_2/types/storage_test.go b/config/v3_2/types/storage_test.go index 7d27bd550f..ee23e6a932 100644 --- a/config/v3_2/types/storage_test.go +++ b/config/v3_2/types/storage_test.go @@ -25,16 +25,18 @@ import ( "github.com/coreos/vcontext/report" ) -func TestStorageValidate(t *testing.T) { +func TestStorageValidateErrors(t *testing.T) { tests := []struct { in Storage at path.ContextPath out error }{ + // test empty storage config returns nil { in: Storage{}, out: nil, }, + // test a storage config with no conflicting paths returns nil { in: Storage{ Links: []Link{ @@ -58,6 +60,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a file uses a configured symlink path returns ErrFileUsedSymlink { in: Storage{ Links: []Link{ @@ -74,6 +77,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrFileUsedSymlink, at: path.New("", "files", 0), }, + // test when a directory uses a configured symlink path returns ErrDirectoryUsedSymlink { in: Storage{ Links: []Link{ @@ -90,6 +94,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrDirectoryUsedSymlink, at: path.New("", "directories", 0), }, + // test the same path listed for two separate symlinks returns ErrLinkUsedSymlink { in: Storage{ Links: []Link{ @@ -104,6 +109,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkUsedSymlink, at: path.New("", "links", 1), }, + // test that two symlinks can be configured at a time { in: Storage{ Links: []Link{ @@ -117,6 +123,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a directory uses a configured symlink with the 'Hard:= true' returns ErrHardLinkToDirectory { in: Storage{ Links: []Link{ @@ -148,3 +155,94 @@ func TestStorageValidate(t *testing.T) { } } } + +func TestStorageValidateWarnings(t *testing.T) { + tests := []struct { + in Storage + at path.ContextPath + out error + }{ + // test a disk with saved partitions with the same 'device' as a filesystem returns ErrPartitionsOverwritten + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + Partitions: []Partition{ + {}, {}, + }, + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrPartitionsOverwritten, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=true' as a configured filesystem returns ErrFilesystemImplicitWipe + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(true), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + WipeFilesystem: util.BoolToPtr(false), + }, + }, + }, + out: errors.ErrFilesystemImplicitWipe, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=false' as a configured filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(false), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + WipeFilesystem: util.BoolToPtr(false), + }, + }, + }, + out: nil, + }, + // test a disk with no saved partitions with the same 'device' as a filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sdb", + }, + }, + }, + out: nil, + }, + } + + for i, test := range tests { + r := test.in.Validate(path.ContextPath{}) + expected := report.Report{} + expected.AddOnWarn(test.at, test.out) + if !reflect.DeepEqual(expected, r) { + t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) + } + } +} diff --git a/config/v3_3/types/storage.go b/config/v3_3/types/storage.go index 0210861312..3787bec76b 100644 --- a/config/v3_3/types/storage.go +++ b/config/v3_3/types/storage.go @@ -71,5 +71,20 @@ func (s Storage) Validate(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) + } + } + } return } diff --git a/config/v3_3/types/storage_test.go b/config/v3_3/types/storage_test.go index cb9256cf16..1c0eec6032 100644 --- a/config/v3_3/types/storage_test.go +++ b/config/v3_3/types/storage_test.go @@ -25,16 +25,18 @@ import ( "github.com/coreos/vcontext/report" ) -func TestStorageValidate(t *testing.T) { +func TestStorageValidateErrors(t *testing.T) { tests := []struct { in Storage at path.ContextPath out error }{ + // test empty storage config returns nil { in: Storage{}, out: nil, }, + // test a storage config with no conflicting paths returns nil { in: Storage{ Links: []Link{ @@ -60,6 +62,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a file uses a configured symlink path returns ErrFileUsedSymlink { in: Storage{ Links: []Link{ @@ -77,6 +80,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrFileUsedSymlink, at: path.New("", "files", 0), }, + // test when a directory uses a configured symlink path returns ErrDirectoryUsedSymlink { in: Storage{ Links: []Link{ @@ -94,6 +98,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrDirectoryUsedSymlink, at: path.New("", "directories", 0), }, + // test the same path listed for two separate symlinks returns ErrLinkUsedSymlink { in: Storage{ Links: []Link{ @@ -110,6 +115,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkUsedSymlink, at: path.New("", "links", 1), }, + // test a configured symlink with no target returns ErrLinkTargetRequired { in: Storage{ Links: []Link{ @@ -122,6 +128,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkTargetRequired, at: path.New("", "links", 0, "target"), }, + // test a configured symlink with a nil target returns ErrLinkTargetRequired { in: Storage{ Links: []Link{ @@ -134,6 +141,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkTargetRequired, at: path.New("", "links", 0, "target"), }, + // test that two symlinks can be configured at a time { in: Storage{ Links: []Link{ @@ -149,6 +157,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a directory uses a configured symlink with the 'Hard:= true' returns ErrHardLinkToDirectory { in: Storage{ Links: []Link{ @@ -180,3 +189,92 @@ func TestStorageValidate(t *testing.T) { } } } + +func TestStorageValidateWarnings(t *testing.T) { + tests := []struct { + in Storage + at path.ContextPath + out error + }{ + // test a disk with saved partitions with the same 'device' as a filesystem returns ErrPartitionsOverwritten + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + Partitions: []Partition{ + {}, {}, + }, + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrPartitionsOverwritten, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=true' as a configured filesystem returns ErrFilesystemImplicitWipe + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(true), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrFilesystemImplicitWipe, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=false' as a configured filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(false), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: nil, + }, + // test a disk with no saved partitions with the same 'device' as a filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sdb", + }, + }, + }, + out: nil, + }, + } + + for i, test := range tests { + r := test.in.Validate(path.ContextPath{}) + expected := report.Report{} + expected.AddOnWarn(test.at, test.out) + if !reflect.DeepEqual(expected, r) { + t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) + } + } +} diff --git a/config/v3_4_experimental/types/storage.go b/config/v3_4_experimental/types/storage.go index 0210861312..3787bec76b 100644 --- a/config/v3_4_experimental/types/storage.go +++ b/config/v3_4_experimental/types/storage.go @@ -71,5 +71,20 @@ func (s Storage) Validate(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) + } + } + } return } diff --git a/config/v3_4_experimental/types/storage_test.go b/config/v3_4_experimental/types/storage_test.go index cb9256cf16..1c0eec6032 100644 --- a/config/v3_4_experimental/types/storage_test.go +++ b/config/v3_4_experimental/types/storage_test.go @@ -25,16 +25,18 @@ import ( "github.com/coreos/vcontext/report" ) -func TestStorageValidate(t *testing.T) { +func TestStorageValidateErrors(t *testing.T) { tests := []struct { in Storage at path.ContextPath out error }{ + // test empty storage config returns nil { in: Storage{}, out: nil, }, + // test a storage config with no conflicting paths returns nil { in: Storage{ Links: []Link{ @@ -60,6 +62,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a file uses a configured symlink path returns ErrFileUsedSymlink { in: Storage{ Links: []Link{ @@ -77,6 +80,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrFileUsedSymlink, at: path.New("", "files", 0), }, + // test when a directory uses a configured symlink path returns ErrDirectoryUsedSymlink { in: Storage{ Links: []Link{ @@ -94,6 +98,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrDirectoryUsedSymlink, at: path.New("", "directories", 0), }, + // test the same path listed for two separate symlinks returns ErrLinkUsedSymlink { in: Storage{ Links: []Link{ @@ -110,6 +115,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkUsedSymlink, at: path.New("", "links", 1), }, + // test a configured symlink with no target returns ErrLinkTargetRequired { in: Storage{ Links: []Link{ @@ -122,6 +128,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkTargetRequired, at: path.New("", "links", 0, "target"), }, + // test a configured symlink with a nil target returns ErrLinkTargetRequired { in: Storage{ Links: []Link{ @@ -134,6 +141,7 @@ func TestStorageValidate(t *testing.T) { out: errors.ErrLinkTargetRequired, at: path.New("", "links", 0, "target"), }, + // test that two symlinks can be configured at a time { in: Storage{ Links: []Link{ @@ -149,6 +157,7 @@ func TestStorageValidate(t *testing.T) { }, out: nil, }, + // test when a directory uses a configured symlink with the 'Hard:= true' returns ErrHardLinkToDirectory { in: Storage{ Links: []Link{ @@ -180,3 +189,92 @@ func TestStorageValidate(t *testing.T) { } } } + +func TestStorageValidateWarnings(t *testing.T) { + tests := []struct { + in Storage + at path.ContextPath + out error + }{ + // test a disk with saved partitions with the same 'device' as a filesystem returns ErrPartitionsOverwritten + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + Partitions: []Partition{ + {}, {}, + }, + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrPartitionsOverwritten, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=true' as a configured filesystem returns ErrFilesystemImplicitWipe + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(true), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: errors.ErrFilesystemImplicitWipe, + at: path.New("", "filesystems", 0, "device"), + }, + // test a disk with the same 'device' and 'Wipetable:=false' as a configured filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sda", + WipeTable: util.BoolToPtr(false), + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sda", + }, + }, + }, + out: nil, + }, + // test a disk with no saved partitions with the same 'device' as a filesystem returns nil + { + in: Storage{ + Disks: []Disk{ + { + Device: "/dev/sdb", + }, + }, + Filesystems: []Filesystem{ + { + Device: "/dev/sdb", + }, + }, + }, + out: nil, + }, + } + + for i, test := range tests { + r := test.in.Validate(path.ContextPath{}) + expected := report.Report{} + expected.AddOnWarn(test.at, test.out) + if !reflect.DeepEqual(expected, r) { + t.Errorf("#%d: bad report: want %v, got %v", i, expected, r) + } + } +} diff --git a/docs/release-notes.md b/docs/release-notes.md index 122edc67c0..38a5db46dc 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -16,6 +16,8 @@ nav_order: 9 ### Changes - Warn if template for enabled systemd instance unit has no `Install` section +- Warn if filesystem overwrites partitioned disk +- Warn if `wipeTable` overwrites a filesystem that would otherwise be reused - Install ignition-apply in `/usr/libexec` - Convert `NEWS` to Markdown and move to docs site