diff --git a/src/ContainerDetails.jsx b/src/ContainerDetails.jsx index c873a3be..3d99744d 100644 --- a/src/ContainerDetails.jsx +++ b/src/ContainerDetails.jsx @@ -37,10 +37,12 @@ const ContainerDetails = ({ container }) => { {_("Image")} {container.ImageName} + {container.Config?.Cmd && {_("Command")} - {utils.quote_cmdline(container.Config?.Cmd)} + {utils.quote_cmdline(container.Config.Cmd)} + } diff --git a/src/ImageDetails.jsx b/src/ImageDetails.jsx index fb057ca2..0da9240d 100644 --- a/src/ImageDetails.jsx +++ b/src/ImageDetails.jsx @@ -12,7 +12,7 @@ const _ = cockpit.gettext; const ImageDetails = ({ containers, image, showAll }) => { return ( - {image.Command !== "" && + {image.Command && {_("Command")} {utils.quote_cmdline(image.Command)} diff --git a/test/check-application b/test/check-application index 70260cb4..d2e1b5d3 100755 --- a/test/check-application +++ b/test/check-application @@ -912,6 +912,37 @@ class TestApplication(testlib.MachineCase): b.wait_not_in_text("#containers-images", ":") b.wait_not_in_text("#containers-containers", IMG_INTERMEDIATE) + # Image without a Command, shows no Command. This is common for podman quadlets + IMG_ENTRYPOINT = "localhost/test-entrypoint" + tmpdir = self.execute(auth, "mktemp -d").strip() + self.addCleanup(self.execute, auth, f"rm -r {tmpdir}") + self.execute(auth, f"echo 'FROM {IMG_REGISTRY}\nENTRYPOINT /entrypoint' > {tmpdir}/Dockerfile") + self.execute(auth, f"podman build -t {IMG_ENTRYPOINT} {tmpdir}") + + b.click(f"#containers-images tr:contains('{IMG_ENTRYPOINT}') td.pf-v5-c-table__toggle button") + b.wait_in_text("#containers-images tbody.pf-m-expanded tr .image-details", "/bin/sh -c /entrypoint") + b.wait_not_in_text("#containers-images tbody.pf-m-expanded tr .image-details", "Command") + + b.click(f'#containers-images tbody tr:contains("{IMG_ENTRYPOINT}") .ct-container-create') + b.wait_visible('div.pf-v5-c-modal-box header:contains("Create container")') + b.set_input_text("#run-image-dialog-name", "no-cmd") + b.wait_visible("#run-image-dialog-command[value='']") + b.wait_text("#run-image-dialog-entrypoint", "/bin/sh -c /entrypoint") + + b.click('.pf-v5-c-modal-box__footer #create-image-create-run-btn') + b.wait_not_present("div.pf-v5-c-modal-box") + self.waitContainerRow("no-cmd") + self.toggleExpandedContainer("no-cmd") + b.wait_in_text("#containers-containers tbody tr:contains('no-cmd')", IMG_ENTRYPOINT) + b.wait_not_in_text("#containers-containers tbody tr:contains('no-cmd')", "Command") + + sha = self.execute(auth, f"podman inspect --format '{{{{.Id}}}}' {IMG_ENTRYPOINT}").strip() + entrypoint_sel = f"#containers-images tbody tr[data-row-id=\"{sha}{auth}\"]".lower() + clickDeleteImage(entrypoint_sel) + self.confirm_modal("Delete") + self.confirm_modal("Force delete") + b.wait_not_in_text("#containers-images", ":") + def testCommitUser(self): self._testCommit(False)