diff --git a/src/PodCreateModal.jsx b/src/PodCreateModal.jsx index eae2c558..bfc0c49b 100644 --- a/src/PodCreateModal.jsx +++ b/src/PodCreateModal.jsx @@ -19,12 +19,12 @@ const _ = cockpit.gettext; const systemOwner = "system"; -export const PodCreateModal = ({ props, user }) => { +export const PodCreateModal = ({ user, selinuxAvailable, systemServiceAvailable, userServiceAvailable }) => { const [podName, setPodName] = useState(dockerNames.getRandomName()); const [nameError, setNameError] = useState(null); const [publish, setPublish] = useState([]); const [volumes, setVolumes] = useState([]); - const [owner, setOwner] = useState(props.systemServiceAvailable ? systemOwner : user); + const [owner, setOwner] = useState(systemServiceAvailable ? systemOwner : user); const [dialogError, setDialogError] = useState(null); const [dialogErrorDetail, setDialogErrorDetail] = useState(null); const Dialogs = useDialogs(); @@ -102,18 +102,20 @@ export const PodCreateModal = ({ props, user }) => { aria-label={nameError} onChange={value => onValueChanged('podName', value)} /> - - setOwner(systemOwner)} /> - setOwner(user)} /> - + { userServiceAvailable && systemServiceAvailable && + + setOwner(systemOwner)} /> + setOwner(user)} /> + + } { actionLabel={_("Add volume")} onChange={value => setVolumes(value)} default={{ containerPath: null, hostPath: null, mode: 'rw' }} - options={{ selinuxAvailable: props.selinuxAvailable }} + options={{ selinuxAvailable }} itemcomponent={ } /> diff --git a/test/check-application b/test/check-application index 55648e8b..15790584 100755 --- a/test/check-application +++ b/test/check-application @@ -4,6 +4,7 @@ # "class Browser" and "class MachineCase" for the available API. import os +import json import sys # import Cockpit's machinery for test VMs and its browser test API @@ -169,10 +170,10 @@ class TestApplication(testlib.MachineCase): else: self.browser.wait_not_present("#table-" + podName) - def waitPodContainer(self, podName, containerList): + def waitPodContainer(self, podName, containerList, system=True): if len(containerList): for container in containerList: - self.waitContainer(container["id"], True, name=container["name"], image=container["image"], + self.waitContainer(container["id"], system, name=container["name"], image=container["image"], cmd=container["command"], state=container["state"], pod=podName) else: if self.browser.val("#containers-containers-filter") == "all": @@ -2222,6 +2223,96 @@ class TestApplication(testlib.MachineCase): for i in range(31): self.execute(True, f"podman rm -f container{i}") + def testCreatePodSystem(self): + self._createPod(True) + + def testCreatePodUser(self): + self._createPod(False) + + def _createPod(self, auth): + b = self.browser + m = self.machine + pod_name = "testpod1" + + self.login(auth) + + b.click("#containers-containers-create-pod-btn") + b.set_input_text("#create-pod-dialog-name", pod_name) + + if auth: + print('owner') + else: + b.wait_not_present("#create-pod-dialog-owner-system") + + # Ports + b.click('.publish-port-form .btn-add') + b.set_input_text('#create-pod-dialog-publish-0-host-port', '6000') + b.set_input_text('#create-pod-dialog-publish-0-container-port', '5000') + b.click('.publish-port-form .btn-add') + b.set_input_text('#create-pod-dialog-publish-1-ip-address', '127.0.0.1') + b.set_input_text('#create-pod-dialog-publish-1-host-port', '6001') + b.set_input_text('#create-pod-dialog-publish-1-container-port', '5001') + b.set_val('#create-pod-dialog-publish-1-protocol', "udp") + b.click('.publish-port-form .btn-add') + b.set_input_text('#create-pod-dialog-publish-2-ip-address', '127.0.0.2') + b.set_input_text('#create-pod-dialog-publish-2-container-port', '9001') + + # Volumes + b.click('.volume-form .btn-add') + rodir, rwdir = m.execute("mktemp; mktemp").split('\n')[:2] + m.execute(f"chown admin:admin {rodir}") + m.execute(f"chown admin:admin {rwdir}") + + if self.has_selinux: + b.set_val('#create-pod-dialog-volume-0-selinux', "z") + else: + b.wait_not_present('#create-pod-dialog-volume-0-selinux') + + b.set_file_autocomplete_val("#create-pod-dialog-volume-0 .pf-c-select", rodir) + b.set_input_text('#create-pod-dialog-volume-0-container-path', '/tmp/ro') + b.click('.volume-form .btn-add') + + b.set_file_autocomplete_val("#create-pod-dialog-volume-1 .pf-c-select", rwdir) + b.set_input_text('#create-pod-dialog-volume-1-container-path', '/tmp/rw') + + b.click("#create-pod-create-btn") + b.set_val("#containers-containers-filter", "all") + self.waitPodContainer(pod_name, []) + + container_name = 'test-pod-1-system' if auth else 'test-pod-1' + containerId = self.execute(auth, f"podman run -d --pod {pod_name} --name {container_name} alpine sleep 1000").strip() + self.waitPodContainer(pod_name, [{"name": container_name, "image": "alpine", "command": "sleep 1000", "state": "Running", "id": containerId}], auth) + + self.toggleExpandedContainer(container_name) + b.click(".pf-m-expanded button:contains('Integration')") + b.wait_in_text('#containers-containers tr:contains("alpine") dt:contains("Volumes") + dd', f"{rodir} \u2194 /tmp/ro") + b.wait_in_text('#containers-containers tr:contains("alpine") dt:contains("Volumes") + dd', f"{rwdir} \u2194 /tmp/rw") + + b.wait_in_text('#containers-containers tr:contains("alpine") dt:contains("Ports") + dd', '0.0.0.0:6000 \u2192 5000/tcp') + b.wait_in_text('#containers-containers tr:contains("alpine") dt:contains("Ports") + dd', '127.0.0.1:6001 \u2192 5001/udp') + b.wait_in_text('#containers-containers tr:contains("alpine") dt:contains("Ports") + dd', ' \u2192 9001/tcp') + + # Validate ports via inspect as we do not show them in the UI yet + pod_info = json.loads(self.execute(auth, f"podman pod inspect {pod_name}").strip()) + port_bindings = pod_info['InfraConfig']['PortBindings'] + self.assertEqual(port_bindings['5000/tcp'], [{'HostIp': '', 'HostPort': '6000'}]) + self.assertEqual(port_bindings['5001/udp'], [{'HostIp': '127.0.0.1', 'HostPort': '6001'}]) + # Host port is randomized as not provided + self.assertTrue(port_bindings['9001/tcp']) + # Force stop, so tearDown does not hang + self.execute(auth, f"podman pod stop -t0 {pod_name} || true") + + # Create pod as admin + if auth: + pod_name = 'testpod2' + b.click("#containers-containers-create-pod-btn") + b.set_input_text("#create-pod-dialog-name", pod_name) + b.click("#create-pod-dialog-owner-user") + b.click("#create-pod-create-btn") + + b.set_val("#containers-containers-filter", "all") + self.waitPodContainer(pod_name, []) + if __name__ == '__main__': testlib.test_main()