Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Validate volume name before cloning #71

Merged
merged 1 commit into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ export function App() {

{openCloneDialog && (
<CloneDialog
volumes={rows}
open={openCloneDialog}
onClose={handleCloneDialogClose}
onCompletion={handleCloneDialogOnCompletion}
Expand Down
26 changes: 12 additions & 14 deletions ui/src/components/CloneDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext } from "react";
import { Button, TextField, Typography, Grid } from "@mui/material";
import { Button, Typography, Grid } from "@mui/material";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
Expand All @@ -10,19 +10,22 @@ import { createDockerDesktopClient } from "@docker/extension-api-client";
import { MyContext } from "../index";
import { useNotificationContext } from "../NotificationContext";
import { track } from "../common/track";
import { IVolumeRow } from "../hooks/useGetVolumes";
import { VolumeInput } from "./VolumeInput";

const ddClient = createDockerDesktopClient();

interface Props {
open: boolean;
onClose(): void;
onCompletion(clonedVolumeName: string, v?: boolean): void;
volumes: IVolumeRow[];
}

export default function CloneDialog({ ...props }: Props) {
const context = useContext(MyContext);
const { sendNotification } = useNotificationContext();

const [hasError, setHasError] = React.useState<boolean>(false);
const [volumeName, setVolumeName] = React.useState<string>(
`${context.store.volume.volumeName}-cloned`
);
Expand Down Expand Up @@ -65,17 +68,12 @@ export default function CloneDialog({ ...props }: Props) {

<Grid container direction="column" spacing={2}>
<Grid item mt={2}>
<TextField
required
autoFocus
id="volume-name"
label="Volume name"
fullWidth
defaultValue={`${context.store.volume.volumeName}-cloned`}
spellCheck={false}
onChange={(e) => {
setVolumeName(e.target.value);
}}
<VolumeInput
volumes={props.volumes}
value={volumeName}
onChange={setVolumeName}
hasError={hasError}
setHasError={setHasError}
/>
</Grid>

Expand All @@ -101,7 +99,7 @@ export default function CloneDialog({ ...props }: Props) {
<Button
variant="contained"
onClick={cloneVolume}
disabled={volumeName === ""}
disabled={volumeName === "" || hasError}
>
Clone
</Button>
Expand Down
6 changes: 5 additions & 1 deletion ui/src/components/VolumeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@ export const VolumeInput = ({
setHasError,
}: Props) => {
const handleChange = (newName: string) => {
const exists = volumes.some((volume) => volume.volumeName === newName);
const exists = volumes.some(
(volume) => volume.volumeName.toLowerCase() === newName.toLowerCase()
);
setHasError(exists);
onChange(newName);
};

return (
<TextField
autoFocus
fullWidth
label="Volume name"
value={value}
error={hasError}
onChange={(event) => handleChange(event.target.value)}
onBlur={(event) => handleChange(event.target.value)}
helperText={
hasError
? "This name is already in use"
Expand Down
6 changes: 6 additions & 0 deletions vm/internal/handler/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ func (h *Handler) CloneVolume(ctx echo.Context) error {
return err
}

// Check if destination volume already exists
destVolInspect, _ := cli.VolumeInspect(ctx.Request().Context(), destVolume)
if destVolInspect.Name != "" {
return ctx.String(http.StatusConflict, fmt.Sprintf("destination volume %q already exists", destVolInspect.Name))
}

// Stop container(s)
stoppedContainers, err := backend.StopContainersAttachedToVolume(ctxReq, cli, volumeName)
if err != nil {
Expand Down