Skip to content

storage: respect --zone when listing bucket objects - #924

Draft
natalie-o-perret wants to merge 2 commits into
masterfrom
fix/storage-list-zone
Draft

natalie-o-perret wants to merge 2 commits into
masterfrom
fix/storage-list-zone

Conversation

@natalie-o-perret

@natalie-o-perret natalie-o-perret commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Make exo storage list sos://BUCKET --zone ZONE use the explicit zone when creating the SOS client. Previously the command parsed --zone, but its initial HeadBucket request still used the profile's default zone.

Commands without an explicit zone keep the existing bucket-region discovery behaviour.

Checklist

(For exoscale contributors)

  • Changelog updated (under Unreleased block, and add the Pull Request #number for each bit you add to the CHANGELOG.md)
  • Testing

Testing

I ran both binaries against the same real default account and bucket. The account's default zone is ch-gva-2, while the selected bucket is in bg-sof-1. A local CONNECT proxy recorded only the SOS hostnames. The shell kept the bucket name private and printed only the number of returned objects.

Before the fix, the command contacts the default-zone endpoint before the requested endpoint:

$ bucket="$(./bin/exo-pr --output-format json storage list --zone bg-sof-1 | jq -er '.[0].name')"
$ ./bin/exo-master --output-format json storage list "sos://${bucket}/" --zone bg-sof-1 | jq '{objects: length}'
CONNECT sos-ch-gva-2.exo.io
CONNECT sos-bg-sof-1.exo.io
{
  "objects": 1
}

After the fix, the same command contacts only the requested endpoint:

$ ./bin/exo-pr --output-format json storage list "sos://${bucket}/" --zone bg-sof-1 | jq '{objects: length}'
CONNECT sos-bg-sof-1.exo.io
{
  "objects": 1
}

For an end-to-end CLI check, I used a local fake SOS endpoint that returns 503 for HeadBucket requests and one object for ListObjectsV2. This simulates an unavailable default-zone endpoint with the following profile:

defaultaccount = "test"

[[accounts]]
defaultZone = "ch-gva-2"
key = "fake-key"
name = "test"
secret = "fake-secret"
sosendpoint = "http://127.0.0.1:18765/{zone}"

Before the fix, the command contacts the profile's default zone and fails:

$ ./bin/exo --config /tmp/exoscale.toml --output-format json storage list sos://escape-test/ --zone ch-dk-2
received HEAD /ch-gva-2/escape-test
error: unable to initialize storage client: option error: operation error S3: HeadBucket, exceeded maximum number of attempts, 3, https response error StatusCode: 503, api error ServiceUnavailable: Service Unavailable

After the fix, the same command contacts only the requested zone and lists the object:

$ ./bin/exo --config /tmp/exoscale.toml --output-format json storage list sos://escape-test/ --zone ch-dk-2
received GET /ch-dk-2/escape-test?delimiter=%2F&list-type=2&prefix=
[{"name":"served-from-ch-dk-2.txt","size":23,"last_modified":"2026-10-02 12:00:00 UTC","dir":false,"version_id":null,"version_number":null}]

The focused regression test and full local checks pass with Go 1.26.6:

$ GOTOOLCHAIN=go1.26.6 go test ./cmd/storage -run '^TestStorageListUsesExplicitZoneForBucket$' -count=1
ok github.com/exoscale/cli/cmd/storage

make test-verbose with the race detector, make build, go vet ./..., staticcheck, and golangci-lint v2.12.2 also pass.


Note

AI assistance: PR description, test scaffolding.

This branch has not been deployed

No deployments
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.

1 participant