LCOV - code coverage report
Current view: top level - src - PodActions.jsx Coverage Total Hit
Test: cockpit-podman Lines: 79.6 % 167 133
Test Date: 2025-05-21 17:35:03

            Line data    Source code
       1           43 : import React, { useState } from 'react';
       2              : 
       3              : import { Alert } from "@patternfly/react-core/dist/esm/components/Alert";
       4              : import { Button } from "@patternfly/react-core/dist/esm/components/Button";
       5              : import { Divider } from '@patternfly/react-core/dist/esm/components/Divider/index.js';
       6              : import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/index.js';
       7              : import { List, ListItem } from "@patternfly/react-core/dist/esm/components/List";
       8              : import {
       9              :     Modal
      10              : } from '@patternfly/react-core/dist/esm/deprecated/components/Modal';
      11              : import { Stack } from "@patternfly/react-core/dist/esm/layouts/Stack";
      12              : import { KebabDropdown } from "cockpit-components-dropdown.jsx";
      13              : import { useDialogs } from "dialogs.jsx";
      14              : 
      15              : import cockpit from 'cockpit';
      16              : 
      17              : import * as client from './client.js';
      18              : 
      19           43 : const _ = cockpit.gettext;
      20              : 
      21            1 : const PodDeleteModal = ({ con, pod }) => {
      22            1 :     const Dialogs = useDialogs();
      23            1 :     const [deleteError, setDeleteError] = useState(null);
      24            1 :     const [force, setForce] = useState(false);
      25              : 
      26            0 :     const containers = (pod.Containers || []).filter(ct => ct.Id !== pod.InfraId);
      27              : 
      28            1 :     function handlePodDelete() {
      29            1 :         client.delPod(con, pod.Id, force)
      30            1 :                 .then(() => {
      31            1 :                     Dialogs.close();
      32            1 :                 })
      33            1 :                 .catch(ex => {
      34            1 :                     setDeleteError(ex.message);
      35            1 :                     setForce(true);
      36            1 :                 });
      37            1 :     }
      38              : 
      39            1 :     return (
      40            1 :         <Modal isOpen
      41            1 :                   position="top" variant="medium"
      42            1 :                   titleIconVariant="warning"
      43            1 :                   title={force
      44            1 :                       ? cockpit.format(_("Force delete pod $0?"), pod.Name)
      45            1 :                       : cockpit.format(_("Delete pod $0?"), pod.Name)}
      46            1 :                   onClose={Dialogs.close}
      47            1 :                   footer={<>
      48            1 :                       <Button variant="danger"
      49            1 :                                       onClick={handlePodDelete}>
      50            1 :                           {force ? _("Force delete") : _("Delete")}
      51            1 :                       </Button>
      52            1 :                       {' '}
      53            1 :                       <Button variant="link" onClick={Dialogs.close}>
      54            1 :                           {_("Cancel")}
      55            1 :                       </Button>
      56            1 :                   </>}
      57              :         >
      58            1 :             {deleteError &&
      59            1 :             <Alert variant="danger" isInline title={_("An error occurred")}>{deleteError}</Alert>}
      60            1 :             {containers.length === 0 &&
      61            1 :             <p>{cockpit.format(_("Empty pod $0 will be permanently removed."), pod.Name)}</p>
      62              :             }
      63            1 :             {containers.length > 0 &&
      64            1 :             <Stack hasGutter>
      65            1 :                 <p>{_("Deleting this pod will remove the following containers:")}</p>
      66            1 :                 <List>
      67            1 :                     {containers.map(container => <ListItem key={container.Names}>{container.Names}</ListItem>)}
      68            1 :                 </List>
      69            1 :             </Stack>}
      70            1 :         </Modal>
      71              :     );
      72            1 : };
      73              : 
      74           10 : export const PodActions = ({ con, onAddNotification, pod, isPodService }) => {
      75           10 :     const Dialogs = useDialogs();
      76              : 
      77           10 :     const dropdownItems = [];
      78              :     // Possible Pod Statuses can be found here https://github.com/containers/podman/blob/main/libpod/define/podstate.go
      79            4 :     if (pod.Status == "Running" || pod.Status == "Paused") {
      80            6 :         dropdownItems.push(
      81            6 :             <DropdownItem key="action-stop"
      82            6 :                               className="pod-action-stop"
      83            1 :                               onClick={() =>
      84            1 :                                   client.postPod(con, "stop", pod.Id, {})
      85            0 :                                           .catch(ex => {
      86            0 :                                               const error = cockpit.format(_("Failed to stop pod $0"), pod.Name);
      87            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
      88            0 :                                           })}
      89            6 :                               component="button">
      90            6 :                 {_("Stop")}
      91            6 :             </DropdownItem>,
      92            6 :             <DropdownItem key="action-force-stop"
      93            6 :                               className="pod-action-force-stop"
      94            0 :                               onClick={() =>
      95            0 :                                   client.postPod(con, "stop", pod.Id, { t: 0 })
      96            0 :                                           .catch(ex => {
      97            0 :                                               const error = cockpit.format(_("Failed to force stop pod $0"), pod.Name);
      98            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
      99            0 :                                           })}
     100            6 :                               component="button">
     101            6 :                 {_("Force stop")}
     102            6 :             </DropdownItem>,
     103            6 :             <DropdownItem key="action-restart"
     104            6 :                               className="pod-action-restart"
     105            1 :                               onClick={() =>
     106            1 :                                   client.postPod(con, "restart", pod.Id, {})
     107            0 :                                           .catch(ex => {
     108            0 :                                               const error = cockpit.format(_("Failed to restart pod $0"), pod.Name);
     109            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
     110            0 :                                           })}
     111            6 :                               component="button">
     112            6 :                 {_("Restart")}
     113            6 :             </DropdownItem>,
     114            6 :             <DropdownItem key="action-force-restart"
     115            6 :                               className="pod-action-force-restart"
     116            0 :                               onClick={() =>
     117            0 :                                   client.postPod(con, "restart", pod.Id, { t: 0 })
     118            0 :                                           .catch(ex => {
     119            0 :                                               const error = cockpit.format(_("Failed to force restart pod $0"), pod.Name);
     120            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
     121            0 :                                           })}
     122            6 :                               component="button">
     123            6 :                 {_("Force restart")}
     124            6 :             </DropdownItem>,
     125            6 :         );
     126            6 :     }
     127            4 :     if (pod.Status == "Created" || pod.Status == "Exited" || pod.Status == "Stopped") {
     128            6 :         dropdownItems.push(
     129            6 :             <DropdownItem key="action-start"
     130            6 :                               className="pod-action-start"
     131            1 :                               onClick={() =>
     132            1 :                                   client.postPod(con, "start", pod.Id, {})
     133            0 :                                           .catch(ex => {
     134            0 :                                               const error = cockpit.format(_("Failed to start pod $0"), pod.Name);
     135            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
     136            0 :                                           })}
     137            6 :                               component="button">
     138            6 :                 {_("Start")}
     139            6 :             </DropdownItem>,
     140            6 :         );
     141            6 :     }
     142            1 :     if (pod.Status == "Paused") {
     143            1 :         dropdownItems.push(
     144            1 :             <DropdownItem key="action-unpause"
     145            1 :                               className="pod-action-unpause"
     146            1 :                               onClick={() =>
     147            1 :                                   client.postPod(con, "unpause", pod.Id, {})
     148            0 :                                           .catch(ex => {
     149            0 :                                               const error = cockpit.format(_("Failed to resume pod $0"), pod.Name);
     150            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
     151            0 :                                           })}
     152            1 :                               component="button">
     153            1 :                 {_("Resume")}
     154            1 :             </DropdownItem>,
     155            1 :         );
     156            1 :     }
     157            6 :     if (pod.Status == "Running") {
     158            6 :         dropdownItems.push(
     159            6 :             <DropdownItem key="action-pause"
     160            6 :                               className="pod-action-pause"
     161            1 :                               onClick={() =>
     162            1 :                                   client.postPod(con, "pause", pod.Id, {})
     163            0 :                                           .catch(ex => {
     164            0 :                                               const error = cockpit.format(_("Failed to pause pod $0"), pod.Name);
     165            0 :                                               onAddNotification({ type: 'danger', error, errorDetail: ex.message });
     166            0 :                                           })}
     167            6 :                               component="button">
     168            6 :                 {_("Pause")}
     169            6 :             </DropdownItem>,
     170            6 :         );
     171            6 :     }
     172              : 
     173            6 :     if (dropdownItems.length > 1) {
     174            6 :         dropdownItems.push(<Divider key="separator-1" />);
     175            6 :     }
     176           10 :     dropdownItems.push(
     177           10 :         <DropdownItem key="action-delete"
     178           10 :                           className="pod-action-delete pf-m-danger"
     179            1 :                           onClick={() => {
     180            1 :                               Dialogs.show(<PodDeleteModal con={con} pod={pod} />);
     181            1 :                           }}
     182           10 :                           component="button">
     183           10 :             {_("Delete")}
     184           10 :         </DropdownItem>,
     185           10 :     );
     186              : 
     187           10 :     if (!dropdownItems.length)
     188            0 :         return null;
     189              : 
     190           10 :     return (
     191           10 :         <KebabDropdown
     192            2 :             toggleButtonId={"pod-" + pod.Name + (pod.uid === 0 ? "-system" : "-user") + "-action-toggle"}
     193           10 :             position="right"
     194           10 :             dropdownItems={dropdownItems}
     195           10 :             isDisabled={isPodService}
     196           10 :         />
     197              :     );
     198           10 : };
        

Generated by: LCOV version 2.0-1