From 9497ef8ca9e05a177dc8ec5cbb80b98ad450b041 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Thu, 7 Oct 2021 19:18:18 +0200 Subject: [PATCH] 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 --- cmd/osbuild-image-tests/main_test.go | 55 +++++++++++++++++++++++++--- test/cases/image_tests.sh | 7 ++++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/cmd/osbuild-image-tests/main_test.go b/cmd/osbuild-image-tests/main_test.go index f73bab3de..6a6793abc 100644 --- a/cmd/osbuild-image-tests/main_test.go +++ b/cmd/osbuild-image-tests/main_test.go @@ -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 { diff --git a/test/cases/image_tests.sh b/test/cases/image_tests.sh index e2f8dae0c..9acc234c2 100755 --- a/test/cases/image_tests.sh +++ b/test/cases/image_tests.sh @@ -26,6 +26,13 @@ if [[ "${DISTRO_CODE}" =~ "rhel-84" ]]; then IMAGE_TEST_CASE_RUNNER="${IMAGE_TEST_CASE_RUNNER} -skip-selinux-ctx-check" fi +# Skip the /usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf file form the 'tmpfiles.d' +# section of the image-info report. The content of the file is dynamically generated +# and lines are not deterministically sorted, thus the diff often fails. +if [[ "${DISTRO_CODE}" =~ "fedora" ]]; then + IMAGE_TEST_CASE_RUNNER="${IMAGE_TEST_CASE_RUNNER} -skip-tmpfilesd-path /usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf" +fi + PASSED_TESTS=() FAILED_TESTS=()