Image tests: skip rpm-ostree-1-autovar.conf tmpfiles.d config on Fedora

The content of `/usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf` is
dynamically created and its lines are not ordered deterministically.
This causes the rpm-ostree based image test cases to fail often on
Fedora, because the diff of the expected and actual image-info report
always produces some different lines.

Add a new option `-skip-tmpfilesd-path` to `osbuild-image-tests`
accepting a tmpfiles.d configuration path, which should be ignored when
comparing the expected and actual image-info report. The option can be
specified multiple times and all paths will be ignored.

Modify the `image_tests.sh` test case to use the new option and ignore the
`/usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf` file when testing Fedora
images.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-10-07 19:18:18 +02:00 committed by Tom Gundersen
parent 9d5c16f623
commit 9497ef8ca9
2 changed files with 56 additions and 6 deletions

View file

@ -47,9 +47,28 @@ type testcaseStruct struct {
}
}
var disableLocalBoot = flag.Bool("disable-local-boot", false, "when this flag is given, no images are booted locally using qemu (this does not affect testing in clouds)")
var failLocalBoot = flag.Bool("fail-local-boot", true, "when this flag is on (default), local boot will fail. Usually indicates missing cloud credentials")
var skipSELinuxCtxCheck = flag.Bool("skip-selinux-ctx-check", false, "when this flag is on, the 'selinux/context-mismatch' part is removed from the image-info report before it is checked.")
type strArrayFlag []string
func (a *strArrayFlag) String() string {
return fmt.Sprintf("%+v", []string(*a))
}
func (a *strArrayFlag) Set(value string) error {
*a = append(*a, value)
return nil
}
var disableLocalBoot bool
var failLocalBoot bool
var skipSELinuxCtxCheck bool
var skipTmpfilesdPaths strArrayFlag
func init() {
flag.BoolVar(&disableLocalBoot, "disable-local-boot", false, "when this flag is given, no images are booted locally using qemu (this does not affect testing in clouds)")
flag.BoolVar(&failLocalBoot, "fail-local-boot", true, "when this flag is on (default), local boot will fail. Usually indicates missing cloud credentials")
flag.BoolVar(&skipSELinuxCtxCheck, "skip-selinux-ctx-check", false, "when this flag is on, the 'selinux/context-mismatch' part is removed from the image-info report before it is checked.")
flag.Var(&skipTmpfilesdPaths, "skip-tmpfilesd-path", "when this flag is given, the provided path is removed from the 'tmpfiles.d' section of the image-info report before it is checked.")
}
// runOsbuild runs osbuild with the specified manifest and output-directory.
func runOsbuild(manifest []byte, store, outputDirectory string, exports []string) error {
@ -93,6 +112,24 @@ func deleteSELinuxCtxFromImageInfoReport(imageInfoReport interface{}) {
}
}
// Delete the provided path form the 'tmpfiles.d' section of the image-info
// report. This is useful to workaround issues with non-deterministic content
// of dynamically generated tmpfiles.d configuration files present on the image.
func deleteTmpfilesdPathFromImageInfoReport(imageInfoReport interface{}, path string) {
dir := filepath.Dir(path)
file := filepath.Base(path)
imageInfoMap := imageInfoReport.(map[string]interface{})
tmpfilesdReport, exists := imageInfoMap["tmpfiles.d"]
if exists {
tmpfilesdReportMap := tmpfilesdReport.(map[string]interface{})
tmpfilesdConfigDir, exists := tmpfilesdReportMap[dir]
if exists {
tmpfilesdConfigDirMap := tmpfilesdConfigDir.(map[string]interface{})
delete(tmpfilesdConfigDirMap, file)
}
}
}
// testImageInfo runs image-info on image specified by imageImage and
// compares the result with expected image info
func testImageInfo(t *testing.T, imagePath string, rawImageInfoExpected []byte) {
@ -115,12 +152,18 @@ func testImageInfo(t *testing.T, imagePath string, rawImageInfoExpected []byte)
err = cmd.Wait()
require.NoErrorf(t, err, "running image-info failed: %v", err)
if *skipSELinuxCtxCheck {
if skipSELinuxCtxCheck {
fmt.Println("ignoring 'selinux/context-mismatch' part of the image-info report")
deleteSELinuxCtxFromImageInfoReport(imageInfoExpected)
deleteSELinuxCtxFromImageInfoReport(imageInfoGot)
}
for _, path := range skipTmpfilesdPaths {
fmt.Printf("ignoring %q path from the 'tmpfiles.d' part of the image-info report\n", path)
deleteTmpfilesdPathFromImageInfoReport(imageInfoExpected, path)
deleteTmpfilesdPathFromImageInfoReport(imageInfoGot, path)
}
assert.Equal(t, imageInfoExpected, imageInfoGot)
}
@ -210,7 +253,7 @@ func testSSH(t *testing.T, address string, privateKey string, ns *boot.NetNS) {
}
func testBootUsingQemu(t *testing.T, imagePath string) {
if *failLocalBoot {
if failLocalBoot {
t.Fatal("-fail-local-boot specified. Check missing cloud credentials!")
}
@ -219,7 +262,7 @@ func testBootUsingQemu(t *testing.T, imagePath string) {
// will not fail even if -fail-local-boot is specified
func bootWithQemu(t *testing.T, imagePath string) {
if *disableLocalBoot {
if disableLocalBoot {
t.Skip("local booting was disabled by -disable-local-boot, skipping")
}
err := boot.WithNetworkNamespace(func(ns boot.NetNS) error {