fix: include per-bucket CORS in bucket metadata export and import - #127
Merged
Conversation
The admin bucket-metadata handlers enumerate every bucket config by name, and per-bucket CORS was never added to that enumeration: export omitted cors.xml (cmd/admin-bucket-handlers.go:414 cfgFiles) and import ignored the entry outright, with no case in applyImportedBucketMetadata (:598) or SetStatus (:629), so a CORS-only archive reported 0/0 buckets imported and a restored bucket silently lost its configuration. Export now writes the stored document verbatim and import validates it with the same parser and validator as PutBucketCorsHandler, merging it under the existing bucket metadata lock and announcing it through the dedicated SRBucketMetaTypeCorsConfig event; the local CORS timestamp rule is extracted into localCORSUpdatedAt and reused so an imported document always lands strictly above bucket creation, which matters because the import stamps its fields before creating any missing bucket and a CORS event below Created is dropped as an older bucket incarnation. The import reads one byte past the declared entry size so archive/zip reaches EOF and verifies the entry checksum, otherwise a corrupt or over-long entry carrying well formed XML would overwrite the stored document; and the CORS event is sent even when the shared bucket metadata hook failed, so an unreachable peer cannot withhold an already committed CORS document from the reachable ones. Tests: TestAdminBucketMetadataCORSRoundTrip and TestAdminBucketMetadataCORSImportReplicatesPastPeerFailure (new, ErasureSD and Erasure). Compatibility: the ZIP gains one entry, older archives stay importable and leave CORS untouched; no mcli or madmin-go change is needed because madmin.BucketStatus already carries Cors and mcli copies the export ZIP verbatim. Fixes #112 Signed-off-by: Feng Ruohang <rh@vonng.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7qJqWwy8oFA6aCXWRzXQe
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution Licensing (no CLA, inbound=outbound, DCO required)
This project does not use a CLA; contributions are accepted inbound=outbound.
By submitting this pull request I represent that I have the right to contribute
the changes, which are licensed under this repository's
GNU Affero General Public License v3.0 or later
and remain my copyright. Every commit carries a DCO
Signed-off-bytrailer.Description
Per-bucket CORS was absent from the admin bucket-metadata export/import: export emitted no
cors.xml, import ignored acors.xmlentry, and both reported success. This addscors.xmlto the export list (the stored document verbatim), an import case that validates the document with the same parser and validator asPutBucketCorsand reports per-file status inBucketStatus.Cors, the merge into the bucket metadata under the existing lock with a timestamp clamped above bucket creation and the previous CORS timestamp (localCORSUpdatedAt, extracted from the localPutBucketCorspath so both stay identical), and the dedicated CORS site-replication event after the save. Two corrections required by the adversarial review: the import reads one byte past the declared entry size soarchive/zipverifies the entry CRC (a CRC-corrupted but well-formed document was otherwise stored), and the CORS event is sent even when the shared bucket-metadata hook failed, with both errors kept viaerrors.Join.Fixes #112. Fix plan agreed with the Codex reviewer: #112 (comment). Adversarial Codex review of this implementation: round 1 FAIL (two MAJOR: zip checksum, suppressed CORS hook), round 2 FAIL (one required MINOR: partial-peer-failure test; one NIT), round 3 PASS with no findings.
Motivation and Context
Bucket backup and migration were incomplete for the newly supported configuration while reporting success. Integration omission of the per-bucket CORS feature (
ce4525632,ff3395d3c); not an upstream inheritance. No mcli or madmin-go change is needed:madmin.BucketStatusalready definesCorsand mcli copies the server-produced ZIP verbatim.How to test this PR?
TestAdminBucketMetadataCORSRoundTrip(ErasureSD and Erasure): export contains the stored bytes; re-export after deletion omitscors.xml; import restores the document with a timestamp after bucket creation; an archive withoutcors.xmlleaves CORS alone; a bucket the import itself creates also lands above its creation time; a malformed document is reported inBucketStatus.Cors.Errwith the stored configuration unchanged. The added replication test drives both hooks through HTTP stubs and asserts the healthy peer receives the saved CORS payload and timestamp even when the shared hook fails, and that both failures are reported. Red on main (export emits nocors.xml; import stores nothing), green with the fix. Counter-checks, each run and reverted: dropping the timestamp clamp fails the fresh-bucket assertion (CORS stamped before creation); dropping the extra-byte read accepts a CRC-corrupted document; restoring theerr == nilcondition starves the healthy peer of the CORS event. The plan's 58-test CORS and bucket-metadata selector passes;gofmtclean,go vetclean, golangci-lint 0 issues.Compatibility impact
The admin API wire format is unchanged; the ZIP gains one entry. Archives taken before the fix stay importable and leave CORS untouched, as every other absent config does. A restored bucket announces its CORS through the existing
SRBucketMetaTypeCorsConfigevent; a peer that predates per-bucket CORS ignores the unknown field. No data or on-disk change; no resync needed.Types of changes
Checklist:
git commit -s) per the DCOmake verifiersequivalent: gofmt clean, go vet clean, golangci-lint 0 issues on./cmd/...pgsty/silo.pgsty.com(none needed; the migration guides do not enumerate config types)🤖 Generated with Claude Code
https://claude.ai/code/session_01L7qJqWwy8oFA6aCXWRzXQe