Skip to content

feat: volume inspection page#75

Merged
kmendell merged 2 commits intomainfrom
feat/volume-inspection
Apr 27, 2025
Merged

feat: volume inspection page#75
kmendell merged 2 commits intomainfrom
feat/volume-inspection

Conversation

@kmendell
Copy link
Member

@kmendell kmendell commented Apr 27, 2025

Fixes: #62

Summary by CodeRabbit

  • New Features

    • Introduced a detailed volume inspection page, allowing users to view comprehensive information about individual Docker volumes.
    • Added the ability to inspect and delete volumes directly from a dropdown menu with improved confirmation dialogs and force deletion support.
    • Added a new function to retrieve detailed volume information with enhanced error handling.
  • Improvements

    • Updated the compose template in the stack creation page to use named volumes and improved service naming.
    • Enhanced error handling and feedback during volume deletion, providing clearer messages for different error scenarios.
    • Improved UI consistency with updated badge styling and more intuitive dropdown actions for containers and volumes.
    • Renamed container action label from "View" to "Inspect" for clarity.
  • Bug Fixes

    • Fixed issues with deletion logic to better handle volumes that are in use and provide accurate UI feedback.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 27, 2025

"""

Walkthrough

This set of changes introduces a new Docker Volume Details page, including both server-side and client-side Svelte components to display and manage individual Docker volumes. The backend logic for retrieving and deleting volumes is implemented with enhanced error handling and type augmentation for Docker volume inspection data. UI components for volume actions, such as inspect and delete (with force option), are refactored to use dropdown menus and confirmation dialogs. The Docker Compose template is updated to use named volumes, and minor improvements are made to badge and column rendering for volume lists.

Changes

File(s) Change Summary
src/app.d.ts Augments the VolumeInspectInfo interface from dockerode to include a CreatedAt property.
src/lib/services/docker/volume-service.ts Adds getVolume function to retrieve volume details; enhances removeVolume with granular error handling and updated documentation.
src/routes/volumes/[volumeName]/+page.server.ts Adds a new server-side page module with load and actions.remove for fetching and deleting volumes with robust error handling.
src/routes/volumes/[volumeName]/+page.svelte Adds a new Svelte page component for displaying detailed volume information and actions (refresh, delete, force delete).
src/routes/volumes/VolumeActions.svelte Refactors UI to use a dropdown for inspect/delete, confirmation dialog for delete, and updates state management and navigation.
src/routes/volumes/columns.ts Passes inUse and a detail page link directly to the UnusedTextBadge component; removes redundant variable.
src/lib/components/badges/unused-text-badge.svelte Adds styling classes for truncation and link appearance in the badge component.
src/routes/containers/ContainerActions.svelte Changes dropdown item label from "View" to "Inspect".
src/routes/stacks/new/+page.svelte Updates Docker Compose template to use named volumes, changes service and volume names, and adjusts formatting.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant VolumeDetailsPage (+page.svelte)
    participant ServerLoad (+page.server.ts)
    participant VolumeService (volume-service.ts)
    participant Dockerode

    User->>VolumeDetailsPage: Navigate to /volumes/[volumeName]
    VolumeDetailsPage->>ServerLoad: load(volumeName)
    ServerLoad->>VolumeService: getVolume(volumeName)
    VolumeService->>Dockerode: volume.inspect()
    Dockerode-->>VolumeService: VolumeInspectInfo
    VolumeService-->>ServerLoad: VolumeInspectInfo
    ServerLoad-->>VolumeDetailsPage: {volume, inUse}

    User->>VolumeDetailsPage: Click "Delete"
    VolumeDetailsPage->>ServerLoad: actions.remove(volumeName, [force])
    ServerLoad->>VolumeService: removeVolume(volumeName, [force])
    VolumeService->>Dockerode: volume.remove({force})
    Dockerode-->>VolumeService: Success/Error
    VolumeService-->>ServerLoad: Success/Error
    ServerLoad-->>VolumeDetailsPage: Redirect or Error
Loading

Assessment against linked issues

Objective Addressed Explanation
Create Volume Details Page with detailed information and actions (inspect, delete, force delete) (#62)

Possibly related PRs

  • refactor: reorganize services and types #71: Refactors and reorganizes Docker service and types, including moving and splitting volume-related logic, which is directly related to the new and updated volume service code in this PR.
    """

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/lib/services/docker/volume-service.ts

Oops! Something went wrong! :(

ESLint: 9.25.1

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/adapter-node' imported from /svelte.config.js
at packageResolve (node:internal/modules/esm/resolve:839:9)
at moduleResolve (node:internal/modules/esm/resolve:908:18)
at defaultResolve (node:internal/modules/esm/resolve:1038:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:557:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:525:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:246:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)
(node:13880) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use node --trace-warnings ... to show where the warning was created)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32c7e17 and 3c3e772.

📒 Files selected for processing (1)
  • src/lib/services/docker/volume-service.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/lib/services/docker/volume-service.ts (2)
src/lib/services/docker/core.ts (1)
  • getDockerClient (24-32)
src/lib/types/errors.ts (3)
  • NotFoundError (34-40)
  • DockerApiError (55-65)
  • ConflictError (68-74)
🔇 Additional comments (4)
src/lib/services/docker/volume-service.ts (4)

3-5: Good additions to imports

The addition of VolumeInspectInfo type import is appropriate for the new functionality, and importing custom error classes improves error handling throughout the file.


65-86: Well-implemented volume inspection function

The new getVolume function provides a clean API for retrieving detailed volume information with proper error handling. The error classification between "not found" vs other Docker API errors is particularly helpful for consumers of this API.


137-142: Good JSDoc enhancement

The improved documentation clearly specifies the different error types that can be thrown, which helps API consumers handle errors appropriately.


148-148: Improved error handling and logging

The enhanced error handling with specific error types and improved logging (including the force parameter state) makes debugging and error handling more robust. The ConflictError for in-use volumes provides a clearer message to users about why the operation failed and what they can do about it.

Also applies to: 150-157

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3f5665 and 32c7e17.

📒 Files selected for processing (9)
  • src/app.d.ts (2 hunks)
  • src/lib/components/badges/unused-text-badge.svelte (1 hunks)
  • src/lib/services/docker/volume-service.ts (3 hunks)
  • src/routes/containers/ContainerActions.svelte (1 hunks)
  • src/routes/stacks/new/+page.svelte (1 hunks)
  • src/routes/volumes/VolumeActions.svelte (2 hunks)
  • src/routes/volumes/[volumeName]/+page.server.ts (1 hunks)
  • src/routes/volumes/[volumeName]/+page.svelte (1 hunks)
  • src/routes/volumes/columns.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/lib/services/docker/volume-service.ts (2)
src/lib/services/docker/core.ts (1)
  • getDockerClient (24-32)
src/lib/types/errors.ts (3)
  • NotFoundError (34-40)
  • DockerApiError (55-65)
  • ConflictError (68-74)
🪛 Biome (1.9.4)
src/lib/services/docker/volume-service.ts

[error] 143-143: This type annotation is trivially inferred from its initialization.

Safe fix: Remove the type annotation.

(lint/style/noInferrableTypes)

🔇 Additional comments (19)
src/routes/containers/ContainerActions.svelte (1)

99-99: Good UI terminology alignment!

Changing the label from "View" to "Inspect" improves consistency throughout the app, matching the volume inspection terminology also used elsewhere.

src/lib/components/badges/unused-text-badge.svelte (1)

15-16: Nice styling improvements!

Adding text truncation and hover feedback for links enhances both the UI consistency and user experience:

  • The truncate class prevents long names from breaking the layout
  • The font-medium and hover:underline provide better interactive feedback
src/app.d.ts (2)

1-2: Good type import for extension

Importing the original interface as OriginalVolumeInspectInfo is a clean approach to prepare for extending it.


15-20: Well-implemented type extension

Correctly extending the VolumeInspectInfo interface to include the missing CreatedAt property ensures type safety when working with Docker volume inspection data. This approach properly handles the gap between the third-party library type definitions and the actual API response.

src/routes/volumes/columns.ts (1)

18-19: Good UX enhancement with linked volume names

Adding the link property enables navigation to the volume detail page directly from the volume list, which improves user experience. The direct use of row.original.inUse also simplifies the code by removing an unnecessary intermediate variable.

src/routes/stacks/new/+page.svelte (1)

23-36: Add Compose version key and reconsider container_name.

Including an explicit version (e.g. version: "3.9") keeps the template self-documenting and avoids ambiguity when Docker Compose decides defaults.
Also, hard-coding container_name (nginx_service) prevents scaling and may create name collisions across stacks. Unless you have a specific reason, it’s usually better to omit this key.

+version: "3.9"
 services:
   nginx:
     image: nginx:alpine
-    container_name: nginx_service
+#    container_name: nginx_service   # ← remove or comment-out unless required

[ suggest_nitpick ]

src/routes/volumes/[volumeName]/+page.server.ts (3)

11-17: Safety fallback could mask real problems.

Returning true when isVolumeInUse fails treats every transient error as “volume busy”, which blocks legitimate removals for reasons unrelated to real usage (e.g. Docker socket hiccups).
Consider surfacing the error to the UI or retrying instead of silently assuming the worst.
[ suggest_optional_refactor ][ request_verification ]


24-31: error() must be thrown to abort the load.

error() only creates the HttpError; it doesn’t throw it.
Without throw, the function continues and ends without a return, causing a 500 and type-checking complaints.

-			error(404, { message: err.message });
+			throw error(404, err.message);
 ...
-			error(err.status || 500, {
-				message: err.message || `Failed to load volume details for "${volumeName}".`
-			});
+			throw error(
+				err.status || 500,
+				err.message || `Failed to load volume details for "${volumeName}".`
+			);

[ flag_critical_issue ]


41-44: Missing throw (or return) prevents redirect after deletion.

redirect() returns a Redirect response but you have to throw or return it for SvelteKit to act on it.

-			redirect(303, '/volumes');
+			throw redirect(303, '/volumes');

[ flag_critical_issue ]

src/routes/volumes/[volumeName]/+page.svelte (4)

41-42: Query-string concatenation produces an invalid URL.

?/remove&force=true misses the second ?. It should be ?/remove?force=true.

-			removeForm.action = `?/remove${forceRemove ? '&force=true' : ''}`;
+			removeForm.action = `?/remove${forceRemove ? '?force=true' : ''}`;

[ flag_critical_issue ]


24-30: Unmanaged setTimeout may leak after navigation.

If the user navigates away before the 500 ms timeout fires, isRefreshing will flip after the component is destroyed.
Store the timer id and clear it in onDestroy().

 let refreshTid: ReturnType<typeof setTimeout>;
 async function refreshData() {
 	isRefreshing = true;
 	await invalidateAll();
-	setTimeout(() => {
+	refreshTid = setTimeout(() => {
 		isRefreshing = false;
 	}, 500);
 }
 
+onDestroy(() => clearTimeout(refreshTid));

[ suggest_optional_refactor ]


177-184: Avoid repeated Object.keys inside each-block.

Object.keys(volume.Labels) is recomputed for every iteration.
Svelte’s each block already exposes an index, so you can pre-compute entries once and use the index to decide whether to render a separator.

-{#each Object.entries(volume.Labels) as [key, value]}
+{#each Object.entries(volume.Labels) as [key, value], i (key)}
 ...
-{#if !Object.is(Object.keys(volume.Labels).length - 1, Object.keys(volume.Labels).indexOf(key))}
+{#if i < Object.entries(volume.Labels).length - 1}

(Apply the same pattern for volume.Options.)
[ suggest_essential_refactor ]


196-203: See previous comment — same optimisation applies here.
[ duplicate_comment ]

src/routes/volumes/VolumeActions.svelte (2)

26-29: Consider URLSearchParams for safer query construction.

Manually appending ?force=true risks double question-marks or stray &. Using URL or URLSearchParams avoids encoding errors.

-	const endpoint = `/api/volumes/${encodeURIComponent(name)}${force ? '?force=true' : ''}`;
+	const url = new URL(`/api/volumes/${encodeURIComponent(name)}`, window.location.origin);
+	if (force) url.searchParams.set('force', 'true');
+	const endpoint = url.pathname + url.search;

[ suggest_optional_refactor ]


47-48: isAnyLoading can be inlined.

With only one flag (isDeleting), a derived store adds indirection.
Either reference isDeleting directly or extend isAnyLoading to aggregate multiple states.
[ suggest_nitpick ]

src/lib/services/docker/volume-service.ts (4)

3-5: Appropriate imports added for new functionality

The imports have been correctly updated to include the VolumeInspectInfo type from dockerode and the necessary custom error classes. These additions support the new volume inspection functionality and enhanced error handling.


65-86: Well-implemented volume inspection function with proper error handling

The new getVolume function is well-structured with detailed error handling that differentiates between "not found" scenarios and other Docker API errors. The function properly logs both successful operations and errors, which will be valuable for troubleshooting.


137-141: Improved JSDoc documentation for error handling

The JSDoc for removeVolume has been enhanced to clearly document the different error types that can be thrown. This improvement helps API consumers understand the possible failure scenarios and how to handle them appropriately.


148-158: Enhanced error handling with specific error types

The error handling in removeVolume has been improved to throw specific error types based on the Docker API response. This allows consumers to handle different error scenarios more precisely.

@kmendell kmendell merged commit 1e6da7d into main Apr 27, 2025
1 check passed
@kmendell kmendell deleted the feat/volume-inspection branch April 27, 2025 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

⚡️ Feature: Create Volume Details Page

1 participant