Skip to content

Commit 25067ec

Browse files
authored
fix(objsto): remove broken sections from object storage example (#682)
1 parent 4d9bf42 commit 25067ec

7 files changed

Lines changed: 214 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add commands for attaching, detaching, and listing policies attached to a user in managed object storage service.
13+
1014
## [3.29.0] - 2026-02-06
1115

1216
### Added

examples/use_object_storage.md

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,9 @@ Save the access key ID and secret access key from the output - you'll need these
4343

4444
Attach a policy to grant the user access to buckets:
4545

46-
1. **Using the UpCloud API:**
47-
48-
First, get your service UUID:
49-
```sh
50-
service_uuid=$(upctl object-storage list -o json | jq -r ".[] | select(.name == \"${prefix}service\") | .uuid")
51-
```
52-
53-
Then attach the policy (requires UPCLOUD_TOKEN environment variable):
54-
```sh when="false"
55-
# Note: This command requires a bearer token which can be created via the UpCloud Control Panel
56-
# The when=false flag skips this in automated tests since only username/password are available in CI
57-
curl -X POST "https://api.upcloud.com/1.3/object-storage-2/${service_uuid}/users/${prefix}user/policies" \
58-
-H "Authorization: Bearer ${UPCLOUD_TOKEN}" \
59-
-H "Content-Type: application/json" \
60-
-d '{"name": "ECSS3FullAccess"}'
61-
```
62-
63-
A successful response returns HTTP status 204.
64-
65-
2. **Using the UpCloud Control Panel:**
66-
Navigate to Object Storage → Users → Select user → Attach Policy → ECSS3FullAccess
67-
68-
**Note:** Without attaching a policy, the user won't have permission to access buckets via AWS CLI or S3-compatible tools.
46+
```sh
47+
upctl object-storage user policy attach ${prefix}service --username ${prefix}user --policy ECSS3FullAccess
48+
```
6949

7050
Verify S3 access with AWS CLI:
7151

internal/commands/base/base.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
objectstoragelabel "github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/objectstorage/label"
2626
objectstoragenetwork "github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/objectstorage/network"
2727
objectstorageuser "github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/objectstorage/user"
28+
objectstorageuserpolicy "github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/objectstorage/user/policy"
2829
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/partner"
2930
partneraccount "github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/partner/account"
3031
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands/root"
@@ -234,6 +235,12 @@ func BuildCommands(rootCmd *cobra.Command, conf *config.Config) {
234235
commands.BuildCommand(objectstorageuser.DeleteCommand(), userCommand.Cobra(), conf)
235236
commands.BuildCommand(objectstorageuser.ListCommand(), userCommand.Cobra(), conf)
236237

238+
// Object storage user policy management
239+
userPolicyCommand := commands.BuildCommand(objectstorageuserpolicy.BaseUserPolicyCommand(), userCommand.Cobra(), conf)
240+
commands.BuildCommand(objectstorageuserpolicy.AttachCommand(), userPolicyCommand.Cobra(), conf)
241+
commands.BuildCommand(objectstorageuserpolicy.DetachCommand(), userPolicyCommand.Cobra(), conf)
242+
commands.BuildCommand(objectstorageuserpolicy.ListCommand(), userPolicyCommand.Cobra(), conf)
243+
237244
// Object storage access key management
238245
accessKeyCommand := commands.BuildCommand(objectstorageAccesskey.BaseAccessKeyCommand(), objectStorageCommand.Cobra(), conf)
239246
commands.BuildCommand(objectstorageAccesskey.CreateCommand(), accessKeyCommand.Cobra(), conf)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package policy
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
7+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/completion"
8+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/output"
9+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/resolver"
10+
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
11+
)
12+
13+
// AttachCommand creates the 'object-storage user-policy attach' command
14+
func AttachCommand() commands.Command {
15+
return &attachCommand{
16+
BaseCommand: commands.New(
17+
"attach",
18+
"Attach a policy to a user in managed object storage service",
19+
"upctl object-storage user-policy attach <service-uuid> --username myuser --policy ECSS3FullAccess",
20+
"upctl object-storage user-policy attach my-service --username myuser --policy ECSS3ReadOnlyAccess",
21+
),
22+
}
23+
}
24+
25+
type attachCommand struct {
26+
*commands.BaseCommand
27+
completion.ObjectStorage
28+
resolver.CachingObjectStorage
29+
params request.AttachManagedObjectStorageUserPolicyRequest
30+
}
31+
32+
// InitCommand implements Command.InitCommand
33+
func (s *attachCommand) InitCommand() {
34+
fs := s.Cobra().Flags()
35+
fs.StringVar(&s.params.Username, "username", "", "The username to attach the policy to.")
36+
fs.StringVar(&s.params.Name, "policy", "", "The name of the policy to attach.")
37+
commands.Must(s.Cobra().MarkFlagRequired("username"))
38+
commands.Must(s.Cobra().MarkFlagRequired("policy"))
39+
}
40+
41+
// Execute implements Command.Execute
42+
func (s *attachCommand) Execute(exec commands.Executor, serviceUUID string) (output.Output, error) {
43+
s.params.ServiceUUID = serviceUUID
44+
svc := exec.All()
45+
46+
msg := fmt.Sprintf("Attaching policy %s to user %s in service %s", s.params.Name, s.params.Username, serviceUUID)
47+
exec.PushProgressStarted(msg)
48+
49+
err := svc.AttachManagedObjectStorageUserPolicy(exec.Context(), &s.params)
50+
if err != nil {
51+
return commands.HandleError(exec, msg, err)
52+
}
53+
54+
exec.PushProgressSuccess(msg)
55+
56+
return output.OnlyMarshaled{Value: fmt.Sprintf("Policy %s attached to user %s in service %s", s.params.Name, s.params.Username, serviceUUID)}, nil
57+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package policy
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
7+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/completion"
8+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/output"
9+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/resolver"
10+
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
11+
)
12+
13+
// DetachCommand creates the 'object-storage user-policy detach' command
14+
func DetachCommand() commands.Command {
15+
return &detachCommand{
16+
BaseCommand: commands.New(
17+
"detach",
18+
"Detach a policy from a user in managed object storage service",
19+
"upctl object-storage user-policy detach <service-uuid> --username myuser --policy ECSS3FullAccess",
20+
"upctl object-storage user-policy detach my-service --username myuser --policy ECSS3ReadOnlyAccess",
21+
),
22+
}
23+
}
24+
25+
type detachCommand struct {
26+
*commands.BaseCommand
27+
completion.ObjectStorage
28+
resolver.CachingObjectStorage
29+
params request.DetachManagedObjectStorageUserPolicyRequest
30+
}
31+
32+
// InitCommand implements Command.InitCommand
33+
func (s *detachCommand) InitCommand() {
34+
fs := s.Cobra().Flags()
35+
fs.StringVar(&s.params.Username, "username", "", "The username to detach the policy from.")
36+
fs.StringVar(&s.params.Name, "policy", "", "The name of the policy to detach.")
37+
commands.Must(s.Cobra().MarkFlagRequired("username"))
38+
commands.Must(s.Cobra().MarkFlagRequired("policy"))
39+
}
40+
41+
// Execute implements Command.Execute
42+
func (s *detachCommand) Execute(exec commands.Executor, serviceUUID string) (output.Output, error) {
43+
s.params.ServiceUUID = serviceUUID
44+
svc := exec.All()
45+
46+
msg := fmt.Sprintf("Detaching policy %s from user %s in service %s", s.params.Name, s.params.Username, serviceUUID)
47+
exec.PushProgressStarted(msg)
48+
49+
err := svc.DetachManagedObjectStorageUserPolicy(exec.Context(), &s.params)
50+
if err != nil {
51+
return commands.HandleError(exec, msg, err)
52+
}
53+
54+
exec.PushProgressSuccess(msg)
55+
56+
return output.OnlyMarshaled{Value: fmt.Sprintf("Policy %s detached from user %s in service %s", s.params.Name, s.params.Username, serviceUUID)}, nil
57+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package policy
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
7+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/completion"
8+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/output"
9+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/resolver"
10+
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
11+
)
12+
13+
// ListCommand creates the 'object-storage user-policy list' command
14+
func ListCommand() commands.Command {
15+
return &listCommand{
16+
BaseCommand: commands.New(
17+
"list",
18+
"List policies attached to a user in managed object storage service",
19+
"upctl object-storage user-policy list <service-uuid> --username myuser",
20+
"upctl object-storage user-policy list my-service --username myuser",
21+
),
22+
}
23+
}
24+
25+
type listCommand struct {
26+
*commands.BaseCommand
27+
completion.ObjectStorage
28+
resolver.CachingObjectStorage
29+
params request.GetManagedObjectStorageUserPoliciesRequest
30+
}
31+
32+
// InitCommand implements Command.InitCommand
33+
func (s *listCommand) InitCommand() {
34+
fs := s.Cobra().Flags()
35+
fs.StringVar(&s.params.Username, "username", "", "The username to list policies for.")
36+
commands.Must(s.Cobra().MarkFlagRequired("username"))
37+
}
38+
39+
// Execute implements Command.Execute
40+
func (s *listCommand) Execute(exec commands.Executor, serviceUUID string) (output.Output, error) {
41+
s.params.ServiceUUID = serviceUUID
42+
svc := exec.All()
43+
44+
msg := fmt.Sprintf("Listing policies for user %s in service %s", s.params.Username, serviceUUID)
45+
exec.PushProgressStarted(msg)
46+
47+
res, err := svc.GetManagedObjectStorageUserPolicies(exec.Context(), &s.params)
48+
if err != nil {
49+
return commands.HandleError(exec, msg, err)
50+
}
51+
52+
exec.PushProgressSuccess(msg)
53+
54+
rows := []output.TableRow{}
55+
for _, policy := range res {
56+
rows = append(rows, output.TableRow{
57+
policy.Name,
58+
})
59+
}
60+
61+
return output.MarshaledWithHumanOutput{
62+
Value: res,
63+
Output: output.Table{
64+
Columns: []output.TableColumn{
65+
{Key: "name", Header: "Policy Name"},
66+
},
67+
Rows: rows,
68+
},
69+
}, nil
70+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package policy
2+
3+
import (
4+
"github.com/UpCloudLtd/upcloud-cli/v3/internal/commands"
5+
)
6+
7+
// BaseUserPolicyCommand creates the base "object-storage user policy" command
8+
func BaseUserPolicyCommand() commands.Command {
9+
return &userPolicyCommand{
10+
BaseCommand: commands.New("policy", "Manage policies attached to a managed object storage user"),
11+
}
12+
}
13+
14+
type userPolicyCommand struct {
15+
*commands.BaseCommand
16+
}

0 commit comments

Comments
 (0)