Skip to content

feat(seaweedfs): add storage pools support for tiered storage#2097

Merged
kvaps merged 5 commits intomainfrom
feat/seaweedfs-storage-pools
Feb 27, 2026
Merged

feat(seaweedfs): add storage pools support for tiered storage#2097
kvaps merged 5 commits intomainfrom
feat/seaweedfs-storage-pools

Conversation

@sircthulhu
Copy link
Contributor

@sircthulhu sircthulhu commented Feb 25, 2026

What this PR does

  • Add volume.pools (Simple topology) and volume.zones[name].pools (MultiZone topology) for creating separate Volume StatefulSets per disk type (SSD/HDD/NVMe)
  • Add nodeSelector, storageClass, and dataCenter overrides for zones in MultiZone topology
  • Create per-pool BucketClass and BucketAccessClass COSI resources (including WORM and readonly variants)
  • Bump seaweedfs-cosi-driver to v0.3.0 (adds disk parameter support in BucketClass)
  • Add volume.diskType field to tag default volume servers with a disk type

How It Works

Simple Topology

Each storage pool in volume.pools creates an additional Volume StatefulSet alongside the default one. All pods (default + pool) may run on the same nodes. SeaweedFS distinguishes storage via the -disk=<type> flag on volume servers.

volume:
  replicas: 2
  size: 10Gi
  diskType: ""
  pools:
    ssd:
      diskType: ssd
      size: 50Gi
      storageClass: local-nvme

MultiZone Topology

Pools are defined per-zone in volume.zones[name].pools. A StatefulSet is created for each zone × pool combination (e.g., us-east-ssd, us-west-ssd), inheriting nodeSelector and dataCenter from its parent zone.

volume:
  replicas: 2
  size: 10Gi
  zones:
    us-east:
      replicas: 2
      size: 100Gi
      # nodeSelector defaults to: topology.kubernetes.io/zone: us-east
      pools:
        ssd:
          diskType: ssd
          size: 50Gi
    us-west:
      replicas: 3

In Simple topology, volume.pools is used. In MultiZone, volume.zones[name].pools is used — volume.pools is explicitly blocked to prevent BucketClasses without backing StatefulSets.

Zone Overrides (MultiZone)

Zones now support:

  • nodeSelector — YAML string, defaults to topology.kubernetes.io/zone: <zoneName>
  • storageClass — defaults to volume.storageClass
  • dataCenter — SeaweedFS data center name, defaults to zone name

COSI Resources

Each unique pool name generates 4 cluster-scoped COSI resources:

  • <namespace>-<pool> BucketClass (Delete policy, disk: <type>)
  • <namespace>-<pool>-worm BucketClass (Retain policy, object lock)
  • <namespace>-<pool> BucketAccessClass (readwrite)
  • <namespace>-<pool>-readonly BucketAccessClass (readonly)

Validation

  • Pool names must be valid DNS labels (no dots)
  • Pool names must not end with -worm or -readonly (reserved COSI suffixes)
  • diskType is required and must be lowercase alphanumeric
  • Pool diskType must differ from volume.diskType
  • Pool name + zone name composed names must not collide with existing zone names
  • volume.pools is blocked in Client and MultiZone topologies
  • All replicas have minimum: 1 in JSON schema

Inheritance Chain

Field Pool fallback (Simple) Pool fallback (MultiZone)
replicas pool → volume pool → zone → volume
size pool → volume pool → zone → volume
storageClass pool → volume pool → zone → volume
resources pool → volume pool → volume (zone resources inherited)

Backward Compatibility

  • Default volume.pools: {} produces identical output to current chart
  • Default volume.diskType: "" adds no extra flags
  • Existing default BucketClass remains unchanged
  • No migration needed — pools create new StatefulSets

Test plan

  • helm template with empty pools — output identical to current
  • helm template with Simple + volume.pools — additional volume StatefulSets, BucketClasses, WorkloadMonitors
  • helm template with MultiZone + zone.pools — zone × pool cross-product StatefulSets
  • helm template with volume.diskType: hdd — extraArgs includes -disk=hdd
  • helm template with Client + volume.pools — fails with validation error
  • helm template with MultiZone + volume.pools — fails with validation error
  • helm template with reserved pool name suffix — fails with validation
  • Deploy to test cluster and verify volume servers register with correct disk types

Release note

[seaweedfs] add storage pools support for tiered storage with per-pool COSI resources

Summary by CodeRabbit

  • New Features

    • Added support for multiple storage pools with configurable disk types and resource allocation.
    • Introduced per-pool bucket and access classes for storage management.
    • Added zone-aware pool configurations for multi-zone deployments.
    • Enhanced topology-driven resource monitoring and allocation.
  • Documentation

    • Updated service documentation with expanded configuration parameters and improved formatting.
  • Chores

    • Updated container image to latest version.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

This pull request extends the SeaweedFS Helm chart to support hierarchical pool and zone configurations. It introduces a new StoragePool typedef with pool-level properties (diskType, replicas, resources, size, storageClass), extends the Volume and Zone types with pools and diskType fields, and adds comprehensive validation, normalization, and dynamic resource generation logic in Helm templates, including new bucket class templates and topology-aware WorkloadMonitor resources.

Changes

Cohort / File(s) Summary
Documentation & Versioning
packages/extra/seaweedfs/README.md, packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag
README title corrected from "Managed NATS Service" to "Managed SeaweedFS Service" with expanded parameter documentation. Image tag updated from v0.2.0 to v0.3.0.
Helm Templates - Volume & Topology Management
packages/extra/seaweedfs/templates/seaweedfs.yaml, packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml, packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml
Extensive validation and normalization for pool and zone configurations across topology modes (Client, Simple, MultiZone). Dynamic rendering of per-pool volume entries, WorkloadMonitor resources, and bucket/access classes. Dashboard resource map extended with topology-driven volume resource entries.
Schema & Values Definition
packages/extra/seaweedfs/values.schema.json, packages/extra/seaweedfs/values.yaml, packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml
Added hierarchical pool configuration schema with StoragePool typedef containing diskType, replicas, resources, size, and storageClass. Extended Volume and Zone types with pools and additional metadata fields (dataCenter, nodeSelector). Updated RD openAPISchema to reflect new structure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A warren of pools now nested so deep,
With zones and diskTypes for storage to keep,
Where Simple meets Multi, each one gets its share,
Validation and buckets—oh, what careful care!
The SeaweedFS sprawls with topology's grace,
Our fluffy crew cheers this well-structured place! 🌱

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main feature: adding storage pools support for tiered storage in SeaweedFS, which aligns with the comprehensive changes across documentation, schema, templates, and deployment configurations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/seaweedfs-storage-pools

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sircthulhu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the SeaweedFS Helm chart by introducing robust support for tiered storage through configurable storage pools. This feature enables users to define distinct storage tiers based on disk types (e.g., SSD, HDD, NVMe), each managed by its own set of volume servers. The changes ensure seamless integration with both Simple and MultiZone cluster topologies and lay the groundwork for future COSI driver integration, allowing for more granular control over data placement and cost optimization.

Highlights

  • Tiered Storage Support: Added optional storagePools configuration to create separate Volume StatefulSets per disk type (SSD/HDD/NVMe), enabling tiered storage.
  • Topology Compatibility: Implemented storagePools support for both Simple and MultiZone topologies, ensuring flexibility in deployment.
  • Disk Type Tagging: Introduced volume.diskType field to tag default volume servers with a specific disk type.
  • COSI Driver Integration Preparation: Generated BucketClass and BucketAccessClass resources per storage pool to prepare the infrastructure for future COSI driver integration.
  • Configuration Validation: Included comprehensive validation for storagePools and volume.diskType configurations, enforcing required fields and naming conventions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • packages/extra/seaweedfs/README.md
    • Updated the service name from "Managed NATS Service" to "Managed SeaweedFS Service".
    • Documented new configuration parameters for volume.diskType and storagePools.
  • packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml
    • Extended WorkloadMonitor rules to include S3 components and dynamically generated volume StatefulSets for storage pools in both Simple and MultiZone topologies.
  • packages/extra/seaweedfs/templates/seaweedfs.yaml
    • Added validation logic to prevent storagePools usage with "Client" topology and enforce required fields (diskType, storageClass) and naming conventions for pools and volume.diskType.
    • Modified volume server configurations to apply diskType tags to default volumes and dynamically create volume StatefulSets for each storage pool, adapting to Simple and MultiZone topologies.
    • Included resource defaulting for volume.zones and storagePools.
    • Introduced WorkloadMonitor resources for each created storage pool volume StatefulSet.
  • packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml
    • Created a new template to generate Kubernetes BucketClass and BucketAccessClass resources for each defined storage pool, facilitating COSI driver integration.
  • packages/extra/seaweedfs/values.schema.json
    • Updated the schema to define the structure and validation rules for the new storagePools object and the volume.diskType field.
  • packages/extra/seaweedfs/values.yaml
    • Added diskType to the default volume configuration.
    • Introduced the storagePools section with detailed documentation and commented-out examples for configuration.
  • packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml
    • Updated the OpenAPI schema and keysOrder to reflect the addition of volume.diskType and storagePools parameters.
Activity
  • No human activity (comments, reviews) detected on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for storage pools in SeaweedFS, allowing for tiered storage based on disk types. The changes are comprehensive, covering configuration, validation, resource generation for both Simple and MultiZone topologies, and integration points for COSI. The documentation has also been updated.

My review has identified a few issues:

  • A potential critical issue in the usage of cozy-lib.resources.defaultingSanitize which may lead to incorrect resource allocation.
  • Some documentation gaps regarding the defaulting behavior of pool properties in MultiZone topology.
  • A minor error in the README.md parameter table.

Overall, this is a great feature addition. Addressing these points will improve its correctness and usability.

{{ with $zone.replicas }}
replicas: {{ . }}
{{- end }}
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list $.Values.volume.resourcesPreset $.Values.volume.resources $) | nindent 12 }}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

There appears to be a logic issue in the cozy-lib.resources.defaultingSanitize helper function that this PR introduces new usages of. The current implementation in cozy-lib seems to prioritize preset values over user-provided resource values due to the order of mergeOverwrite. This is contrary to the function's documentation and will lead to user-specified resources being ignored in favor of the preset.

For example, deepCopy (default (dict) $resources) | mergeOverwrite $presetMap will result in values from $presetMap overwriting values in $resources. It should be the other way around.

This will cause incorrect resource allocation for the new volume statefulsets. Please verify the implementation of mergeOverwrite and correct the merge order in cozy-lib/_resources.tpl, or implement the defaulting logic directly here to avoid using the potentially buggy helper.

| `storagePools[name].resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
| `storagePools[name].resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` |
| `storagePools[name].resources.memory` | Amount of memory allocated. | `quantity` | `""` |
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` |
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The default value for storagePools[name].resourcesPreset is documented as {}, but its type is string. This is inconsistent and may confuse users. It should be "" to indicate that it falls back to volume.resourcesPreset.

Suggested change
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` |
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `""` |

Comment on lines +104 to +105
## @field {int} [replicas] - Number of volume replicas. Defaults to volume.replicas.
## @field {quantity} [size] - Persistent Volume size. Defaults to volume.size.
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The documentation for replicas and size within a StoragePool is incomplete for the MultiZone topology. The implementation uses a pool -> zone -> global fallback chain (e.g., {{ $pool.replicas | default $zone.replicas | default $.Values.volume.replicas }}), but the documentation only mentions defaulting to the global volume values. This should be clarified to avoid confusion.

A similar clarification is needed for size.

## @field {int} [replicas] - Number of volume replicas. In MultiZone, defaults to `volume.zones.<zoneName>.replicas`, then `volume.replicas`. In Simple topology, defaults to `volume.replicas`.
## @field {quantity} [size] - Persistent Volume size. In MultiZone, defaults to `volume.zones.<zoneName>.size`, then `volume.size`. In Simple topology, defaults to `volume.size`.

@sircthulhu
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for storage pools, enabling tiered storage for SeaweedFS. The changes are comprehensive, covering Helm templates, configuration, schema, and documentation. You've added robust validation for the new configuration options, which is great for preventing misconfigurations. The implementation correctly handles both Simple and MultiZone topologies, creating separate Volume StatefulSets and corresponding WorkloadMonitor resources for each pool. The addition of BucketClass resources for COSI integration is a thoughtful preparation for future work.

I have a couple of minor suggestions. One is a documentation consistency fix in the README.md. The other points out a small pre-existing issue in the dashboard-resourcemap.yaml that becomes more apparent with the new topology-specific logic you've added. Overall, this is a solid feature addition.

| `storagePools[name].resources` | Explicit CPU and memory configuration. When omitted, the preset defined in `resourcesPreset` is applied. | `object` | `{}` |
| `storagePools[name].resources.cpu` | Number of CPU cores allocated. | `quantity` | `""` |
| `storagePools[name].resources.memory` | Amount of memory allocated. | `quantity` | `""` |
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` |
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The default Value for storagePools[name].resourcesPreset is documented as {}, but its Type is string. This is inconsistent with other string-typed parameters and likely a copy-paste error from the resources field which is an object. For other optional string parameters that default to another value, the Value is typically "". Please update for consistency.

Suggested change
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `{}` |
| `storagePools[name].resourcesPreset` | Default sizing preset used when `resources` is omitted. Defaults to volume.resourcesPreset. | `string` | `""` |

Comment on lines +31 to +44
{{- if eq .Values.topology "Simple" }}
{{- range $poolName, $pool := .Values.storagePools }}
- {{ $.Release.Name }}-volume-{{ $poolName }}
{{- end }}
{{- else if eq .Values.topology "MultiZone" }}
{{- range $zoneName, $zone := .Values.volume.zones }}
- {{ $.Release.Name }}-volume-{{ $zoneName }}
{{- end }}
{{- range $poolName, $pool := .Values.storagePools }}
{{- range $zoneName, $zone := $.Values.volume.zones }}
- {{ $.Release.Name }}-volume-{{ $zoneName }}-{{ $poolName }}
{{- end }}
{{- end }}
{{- end }}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The logic to add WorkloadMonitor resource names for different topologies is a good addition. However, I've noticed a related issue on line 28 (an unchanged context line): {{ $.Release.Name }}-volume is included unconditionally. The corresponding WorkloadMonitor resource is only created when .Values.topology is Simple. In a MultiZone deployment, this will cause the Role to reference a non-existent resource. To fix this, - {{ $.Release.Name }}-volume should be moved from line 28 to inside this new if eq .Values.topology "Simple" block (e.g., before line 32).

@sircthulhu sircthulhu self-assigned this Feb 26, 2026
sircthulhu and others added 5 commits February 27, 2026 11:53
Add optional storagePools configuration that creates separate Volume
StatefulSets per disk type (SSD/HDD/NVMe), enabling tiered storage
within a single SeaweedFS tenant. Each pool gets its own BucketClass
and BucketAccessClass to prepare infrastructure for COSI driver
integration.

Supported in both Simple and MultiZone topologies:
- Simple: one StatefulSet per pool
- MultiZone: one StatefulSet per zone×pool combination

Also adds volume.diskType field for tagging default volume servers.

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Kirill Ilin <[email protected]>
…s inheritance

Make storageClass optional in storagePools — pools inherit from
volume.storageClass when not explicitly set. Add full COSI resource set
per storage pool: BucketClass, BucketClass-worm (Retain + object lock),
BucketAccessClass readwrite, and BucketAccessClass readonly.

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Kirill Ilin <[email protected]>
- Document MultiZone fallback chain for pool replicas and size
- Move `-volume` WorkloadMonitor reference inside Simple topology block in dashboard-resourcemap.yaml (it is only created for Simple)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Kirill Ilin <[email protected]>
- Remove dots from pool name regex (K8s resources don't allow dots)
- Add zone×pool name collision validation for MultiZone topology
- Use conditional storageClass rendering to omit empty values
- Fix README resourcesPreset default value

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Kirill Ilin <[email protected]>
…s and zone.pools

Redesign storage pools architecture:
- Move storagePools map from top-level into volume.pools (Simple topology)
  and volume.zones[name].pools (MultiZone topology)
- Add nodeSelector, storageClass, dataCenter overrides for zones
- Add reserved suffix validation (-worm, -readonly) for pool names
- Block volume.pools usage in MultiZone (must use zone.pools instead)
- Use ternary/hasKey pattern for all optional replicas to handle 0 correctly
- Fix nodeSelector rendering for multiline values using indent
- Use disk: parameter (not diskType:) for COSI driver v0.3.0 BucketClass
- Bump seaweedfs-cosi-driver tag to v0.3.0
- Add minimum: 1 constraint for volume/zone/pool replicas in schema
- Regenerate README, CRD, and openAPISchema

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Kirill Ilin <[email protected]>
@sircthulhu sircthulhu force-pushed the feat/seaweedfs-storage-pools branch from f8fa302 to b0b0dad Compare February 27, 2026 06:53
@sircthulhu sircthulhu marked this pull request as ready for review February 27, 2026 07:44
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. enhancement New feature or request labels Feb 27, 2026
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/extra/seaweedfs/templates/seaweedfs.yaml`:
- Around line 71-75: The template only checks $composedName against existing
zone keys ($.Values.volume.zones) but doesn't ensure uniqueness among all
composed "{zone}-{pool}" names; update the Helm template to build a set/map of
composed names while iterating zones and pools and fail when a composed name is
already present to prevent collisions (reference the $composedName variable, the
zoneName and poolName loop variables, and $.Values.volume.zones); in practice,
create a composedNames map before/while generating names, use hasKey on that map
to detect duplicates and call fail with a clear message when a duplicate
composedName is found, otherwise add the composedName to the map.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75f2e23 and b0b0dad.

📒 Files selected for processing (8)
  • packages/extra/seaweedfs/README.md
  • packages/extra/seaweedfs/images/seaweedfs-cosi-driver.tag
  • packages/extra/seaweedfs/templates/dashboard-resourcemap.yaml
  • packages/extra/seaweedfs/templates/seaweedfs.yaml
  • packages/extra/seaweedfs/templates/storage-pool-bucket-classes.yaml
  • packages/extra/seaweedfs/values.schema.json
  • packages/extra/seaweedfs/values.yaml
  • packages/system/seaweedfs-rd/cozyrds/seaweedfs.yaml

Comment on lines +71 to +75
{{- $composedName := printf "%s-%s" $zoneName $poolName }}
{{- if hasKey $.Values.volume.zones $composedName }}
{{- fail (printf "Composed volume name '%s' (from zone '%s' and pool '%s') collides with an existing zone name." $composedName $zoneName $poolName) }}
{{- end }}
{{- end }}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add uniqueness validation for composed zone-pool names.

Current logic checks collision against existing zone names, but not collisions between different {zone, pool} pairs (e.g., a+b-c vs a-b+c). That can create duplicate generated keys/names and unstable manifests.

💡 Proposed fix
 {{- if eq .Values.topology "MultiZone" }}
+{{-   $seenComposedPoolNames := dict }}
 {{-   range $zoneName, $zone := .Values.volume.zones }}
 {{-     range $poolName, $pool := (dig "pools" dict $zone) }}
@@
 {{-       $_ := set $allPools $poolName $pool.diskType }}
 {{-       $composedName := printf "%s-%s" $zoneName $poolName }}
+{{-       if hasKey $seenComposedPoolNames $composedName }}
+{{-         fail (printf "Composed volume name '%s' is ambiguous between '%s' and '%s/%s'." $composedName (get $seenComposedPoolNames $composedName) $zoneName $poolName) }}
+{{-       end }}
+{{-       $_ := set $seenComposedPoolNames $composedName (printf "%s/%s" $zoneName $poolName) }}
 {{-       if hasKey $.Values.volume.zones $composedName }}
 {{-         fail (printf "Composed volume name '%s' (from zone '%s' and pool '%s') collides with an existing zone name." $composedName $zoneName $poolName) }}
 {{-       end }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/extra/seaweedfs/templates/seaweedfs.yaml` around lines 71 - 75, The
template only checks $composedName against existing zone keys
($.Values.volume.zones) but doesn't ensure uniqueness among all composed
"{zone}-{pool}" names; update the Helm template to build a set/map of composed
names while iterating zones and pools and fail when a composed name is already
present to prevent collisions (reference the $composedName variable, the
zoneName and poolName loop variables, and $.Values.volume.zones); in practice,
create a composedNames map before/while generating names, use hasKey on that map
to detect duplicates and call fail with a clear message when a duplicate
composedName is found, otherwise add the composedName to the map.

Copy link
Collaborator

@IvanHunters IvanHunters left a comment

Choose a reason for hiding this comment

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

LGTM

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 27, 2026
@kvaps kvaps merged commit 3862e7c into main Feb 27, 2026
12 checks passed
@kvaps kvaps deleted the feat/seaweedfs-storage-pools branch February 27, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants