Skip to content

Commit a19b617

Browse files
fix: copilot review
1 parent 0d7c8b3 commit a19b617

6 files changed

Lines changed: 50 additions & 45 deletions

File tree

commands/object-storage/bucket/delete.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,11 @@ func deleteAllBuckets(c *core.CommandConfig) error {
7373

7474
if viper.IsSet(constants.FlagLocation) {
7575
filterRegion := viper.GetString(constants.FlagLocation)
76-
buckets = functional.Filter(buckets, func(b objectstorage.Bucket) bool {
77-
loc, _, locErr := s3.BucketsApi.GetBucketLocation(c.Context, b.GetName()).Execute()
78-
if locErr != nil {
79-
return false
80-
}
81-
return loc.GetLocationConstraint() == filterRegion
82-
})
76+
filtered, locErr := filterBucketsByLocation(c.Context, s3, buckets, filterRegion)
77+
if locErr != nil {
78+
return locErr
79+
}
80+
buckets = filtered
8381
}
8482

8583
return functional.ApplyAndAggregateErrors(buckets, func(b objectstorage.Bucket) error {
@@ -98,3 +96,19 @@ func deleteAllBuckets(c *core.CommandConfig) error {
9896
return nil
9997
})
10098
}
99+
100+
// filterBucketsByLocation filters buckets by region, returning an error if any
101+
// location lookup fails (to avoid silently skipping buckets from deletion).
102+
func filterBucketsByLocation(ctx context.Context, s3 *objectstorage.APIClient, buckets []objectstorage.Bucket, region string) ([]objectstorage.Bucket, error) {
103+
var filtered []objectstorage.Bucket
104+
for _, b := range buckets {
105+
loc, _, locErr := s3.BucketsApi.GetBucketLocation(ctx, b.GetName()).Execute()
106+
if locErr != nil {
107+
return nil, fmt.Errorf("cannot filter by location: failed to get location for bucket %q: %w", b.GetName(), locErr)
108+
}
109+
if loc.GetLocationConstraint() == region {
110+
filtered = append(filtered, b)
111+
}
112+
}
113+
return filtered, nil
114+
}

commands/object-storage/bucket/get.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,14 @@ func getBucketInfo(ctx context.Context, name string) (*bucketInfo, error) {
4242
return nil, fmt.Errorf("bucket %q not found", name)
4343
}
4444

45-
loc, _, err := client.MustObjectStorage().ObjectStorageClient.BucketsApi.GetBucketLocation(ctx, name).Execute()
46-
if err == nil && loc != nil {
45+
loc, apiResp, locErr := client.MustObjectStorage().ObjectStorageClient.BucketsApi.GetBucketLocation(ctx, name).Execute()
46+
if locErr != nil {
47+
if apiResp != nil {
48+
found.Region = fmt.Sprintf("<%s>", apiResp.Status)
49+
} else {
50+
found.Region = "<unknown>"
51+
}
52+
} else {
4753
found.Region = loc.GetLocationConstraint()
4854
}
4955

commands/object-storage/bucket/list.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ func ListBucketsCmd() *core.Command {
2929
return err
3030
}
3131

32+
filterByLocation := viper.IsSet(constants.FlagLocation)
33+
filterRegion := viper.GetString(constants.FlagLocation)
34+
3235
var buckets []bucketInfo
3336
for _, b := range result.GetBuckets() {
3437

@@ -39,6 +42,13 @@ func ListBucketsCmd() *core.Command {
3942

4043
loc, apiResp, locErr := client.MustObjectStorage().ObjectStorageClient.BucketsApi.GetBucketLocation(c.Context, b.GetName()).Execute()
4144
if locErr != nil {
45+
// When filtering by location, a failed lookup would silently
46+
// exclude the bucket. Fail loudly so the user knows results
47+
// may be incomplete.
48+
if filterByLocation {
49+
return fmt.Errorf("cannot filter by location: failed to get location for bucket %q: %w", b.GetName(), locErr)
50+
}
51+
4252
c.Verbose("failed to get location for bucket %q: %v", b.GetName(), locErr)
4353
if apiResp != nil {
4454
bi.Region = fmt.Sprintf("<%s>", apiResp.Status)
@@ -49,7 +59,7 @@ func ListBucketsCmd() *core.Command {
4959
bi.Region = loc.GetLocationConstraint()
5060
}
5161

52-
if viper.IsSet(constants.FlagLocation) && bi.Region != viper.GetString(constants.FlagLocation) {
62+
if filterByLocation && bi.Region != filterRegion {
5363
continue
5464
}
5565

commands/object-storage/bucket/policy/put.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import (
1515
"github.com/ionos-cloud/ionosctl/v6/internal/core"
1616
)
1717

18+
// policyExample uses S3-compatible IAM policy syntax. The "s3:" action prefix
19+
// and "arn:aws:s3:::" resource format are required by the S3-compatible API,
20+
// not references to AWS services.
1821
const policyExample = `{
1922
"Version": "2012-10-17",
2023
"Statement": [

commands/object-storage/object/delete.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package object
33
import (
44
"context"
55
"fmt"
6+
"strings"
67

78
"github.com/ionos-cloud/sdk-go-bundle/products/objectstorage/v2"
89
"github.com/spf13/viper"
@@ -200,9 +201,12 @@ func batchDelete(ctx context.Context, s3 *objectstorage.APIClient, bucket string
200201
}
201202

202203
if result != nil && len(result.Errors) > 0 {
203-
first := result.Errors[0]
204-
return fmt.Errorf("failed to delete %d object(s): %s: %s (key: %s)",
205-
len(result.Errors), first.GetCode(), first.GetMessage(), first.GetKey())
204+
var details []string
205+
for _, e := range result.Errors {
206+
details = append(details, fmt.Sprintf(" %s: %s (key: %s)", e.GetCode(), e.GetMessage(), e.GetKey()))
207+
}
208+
return fmt.Errorf("failed to delete %d object(s):\n%s",
209+
len(result.Errors), strings.Join(details, "\n"))
206210
}
207211

208212
return nil

test/suites/setup.bats

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -193,38 +193,6 @@ refute_stderr() {
193193
fi
194194
}
195195

196-
# assert_stderr: like assert_output but checks $stderr (captured via --separate-stderr).
197-
# Supports: assert_stderr -p "substring" | assert_stderr "exact match"
198-
assert_stderr() {
199-
local mode="equal"
200-
local expected
201-
202-
while [[ $# -gt 0 ]]; do
203-
case "$1" in
204-
-p|--partial) mode="partial"; shift ;;
205-
*) expected="$1"; shift ;;
206-
esac
207-
done
208-
209-
if [[ "$mode" == "partial" ]]; then
210-
if [[ "$stderr" != *"$expected"* ]]; then
211-
echo "-- stderr does not contain substring --"
212-
echo "substring : $expected"
213-
echo "stderr : $(echo "$stderr" | redact)"
214-
echo "--"
215-
return 1
216-
fi
217-
else
218-
if [[ "$stderr" != "$expected" ]]; then
219-
echo "-- stderr is not equal to expected --"
220-
echo "expected : $expected"
221-
echo "actual : $(echo "$stderr" | redact)"
222-
echo "--"
223-
return 1
224-
fi
225-
fi
226-
}
227-
228196
setup_file() {
229197
uuid_v4_regex='^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
230198
ip_regex='^([0-9]{1,3}\.){3}[0-9]{1,3}(\/[0-9]{1,2})?$'

0 commit comments

Comments
 (0)