rgw

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 33 Imported by: 0

README

Ceph RGW

Import github.com/JSYoo5B/ceph-testcontainers-go/rgw to give an application that uses S3 (or Swift) a disposable Ceph cluster with one or more gateways and the server-side state its integration test needs: an S3 endpoint the test can reach (optionally native HTTPS), users with explicit Admin Ops capabilities, tenants and accounts, quotas and suspension, storage counters, and placement targets with storage classes. Object operations belong to the S3 client under test; the package adds no S3 SDK. See API purpose and purpose tags.

go get github.com/JSYoo5B/ceph-testcontainers-go/rgw

Order of use

  1. Start a cluster with a gateway: rgw.Run(ctx, ceph.DefaultImage, opts...); rgw.WithGateways(rgw.Config{...}) selects other gateways (also on ceph.Run, rbd.Run and cephfs.Run), and rgw.Start adds one to a running cluster. When the test needs server-side RGW options (lifecycle clock, usage log, STS key, KMS backend), start with ceph.Run, apply them with override.SetConfig, then call rgw.Start: gateways read them at start.
  2. Prepare the identities and placement the scenario needs on a *rgw.Gateway (from Gateways or Start): CreateUser (with tenant, Admin Ops caps, bucket limit), CreateAccount and Account.CreateRootUser, User.SetQuota / SetBucketQuota, User.Suspend, CreatePlacement then ApplyPlacement, User.SetPlacement.
  3. Hand the endpoint to the SUT: S3Endpoint (or S3SecureEndpoint) for a client on the test host, DaemonEndpoint for a client in the cluster network, with User.Credentials (or the gateway's own AccessKey / SecretKey) and Gateway.Region, path-style addressing.
  4. Observe and verify: User.Info, User.Usage, Account.Info, Placement.Status, and Gateway.Admin for anything without a typed API.
  5. Clean up: terminate the cluster; gateways, users and data go with it. Gateway.Remove, User.Remove and Account.Remove are for tests of those steps.

The smallest S3 fixture keeps one daemon of each kind and single-copy pools:

cluster, err := rgw.Run(ctx, ceph.DefaultImage,
	ceph.WithClusterConfig(ceph.ClusterConfig{}.WithMonitorCount(1).WithManagerCount(1).WithOSDCount(1).WithPoolDefaults(1, 1)),
)
testcontainers.CleanupContainer(t, cluster)
if err != nil {
	t.Fatal(err)
}
gateways, err := rgw.Gateways(ctx, cluster.Container)
if err != nil {
	t.Fatal(err)
}
gateway := gateways[0]
endpoint, err := gateway.S3Endpoint(ctx)
if err != nil {
	t.Fatal(err)
}
// Use endpoint, gateway.AccessKey, gateway.SecretKey and gateway.Region with a
// path-style S3 client. Keep the keys out of test logs.

It runs four containers (MON with the Ceph CLIs, MGR, OSD, gateway). With one OSD and one copy nothing recovers from an OSD failure; tests of OSD faults or recovery need the default two OSDs or more.

Concepts and limits

  • Everything in ceph applies to the cluster. Multisite (one realm across clusters, zones, zonegroups, sync policy) is in rgw/multisite.
  • Images: the Run image is the essential image; ceph.ImageOptions.WithRGWImage selects the gateway image, which must contain radosgw and radosgw-admin (Gateway.Admin runs inside the gateway). Keep every role on the same Ceph release and architecture. ceph.DefaultImage is Tentacle 20.2.4; Squid 19.2.5 is supported (use 19.2.5, not 19.2.6, for multisite). See Releases and images.
  • Identities belong to the cluster and scope that created them, not to one gateway: user, account and placement handles run through any running gateway of their scope, and a gateway can be removed without removing them.
  • Endpoints change on restart: in bridge mode a restarted gateway can get a new mapped host port. Resolve S3Endpoint again after any restart, including the ones done by ApplyPlacement, ReloadPlacement and multisite changes.
  • Quota enforcement, suspension, placement defaults and usage counters go through caches and asynchronous accounting: poll with new requests instead of asserting right after a change. Usage log persistence is asynchronous too.
  • HTTPS is native Beast TLS without a proxy; clients must trust the CA. NetworkConfig.WithMessengerMode encrypts Ceph messenger traffic only.
  • Printing a handle never writes keys; Gateway.Admin output can contain keys, and a failed call never includes native output.
  • Gateways run 4 worker threads: functional tests, not load tests. Docker exec cancellation does not stop a native worker already running (such as bucket sync run).
  • Out of scope: production Vault setups and other KMS backends, Swift large objects, temporary URLs and Keystone catalogues.

Reference

Documentation

Overview

Package rgw prepares RADOS Gateway fixtures in disposable Ceph clusters: gateways, S3 users, tenants and accounts, quotas, placement targets and storage classes, and native TLS. Multisite orchestration across clusters is in package rgw/multisite.

Run starts a cluster with at least one gateway. Start adds a gateway to a cluster created by ceph.Run or another service package's Run, and WithGateways selects gateways for any of those Run functions.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithGateways

func WithGateways(configs ...Config) ceph.Option

WithGateways starts named gateways during Run. No arguments starts one default gateway. Repeated options replace the list. All gateways share this cluster's backing zone; multisite scope is configured separately by multisite.Run.

Types

type Account

type Account struct {
	// contains filtered or unexported fields
}

Account is a fresh account owned by this fixture. Its native metadata version tag distinguishes its lifetime from a deleted/recreated account. Copies share lifecycle state. Removing a gateway does not remove the account. Its operations run through the first running registered gateway, by name, in the scope of the gateway that created it.

func (*Account) CreateRootUser added in v0.4.0

func (a *Account) CreateRootUser(ctx context.Context, config UserConfig) (*User, error)

CreateRootUser creates a fresh root identity inside an owned account. Empty Tenant inherits the account tenant; a different tenant is rejected. Account root grants permissions within the account; global admin and multisite system flags remain false. IAM operations remain on the consuming client.

func (Account) Format added in v0.4.0

func (a Account) Format(f fmt.State, _ rune)

Format prints String for every verb and flag, so no verb, such as %d or %t, walks the fields.

func (Account) GoString

func (a Account) GoString() string

func (*Account) ID

func (a *Account) ID() string

ID returns the native account ID, or "" for a nil handle.

func (*Account) Info added in v0.4.0

func (a *Account) Info(ctx context.Context) (AccountInfo, error)

Info reads the owned account's authoritative native policy.

func (*Account) Remove added in v0.4.0

func (a *Account) Remove(ctx context.Context) error

Remove removes only an owned, empty account, without purge-data. Native Ceph refuses remaining users, buckets, roles, groups, OIDC providers or topics. Remove these through their ordinary clients first. Success is idempotent across copies. Native external account edits must not race these fixture helpers.

func (*Account) SetBucketQuota added in v0.4.0

func (a *Account) SetBucketQuota(ctx context.Context, quota Quota) error

SetBucketQuota applies individual bucket limits to every bucket owned by this account, independent of which account identity created the bucket.

func (*Account) SetQuota added in v0.4.0

func (a *Account) SetQuota(ctx context.Context, quota Quota) error

SetQuota replaces aggregate account limits and their enabled state. Native account quota size is rounded to KiB, so byte limits must be -1, zero or a positive multiple of 1024. Readback does not promise cache enforcement.

func (Account) String

func (a Account) String() string

type AccountConfig

type AccountConfig struct {
	ID, Name, Tenant, Email string
	MaxBuckets              *int
}

AccountConfig creates a new native account. Empty ID generates a unique RGW-prefixed 17-digit ID; Name defaults to a unique fixture name. Tenant is optional and isolates bucket names. Account IDs and email are globally unique. MaxBuckets nil preserves the native default. No user migration is performed.

type AccountInfo

type AccountInfo struct {
	ID, Name, Tenant, Email                            string
	MaxUsers, MaxRoles, MaxGroups, MaxBuckets, MaxKeys int
	AccountQuota, BucketQuota                          Quota
}

AccountInfo contains account-wide limits and the individual bucket policy. AccountQuota applies across all account users, buckets and roles, rather than to one user's storage. Quota readback does not flush native accounting caches.

type AdminCapability

type AdminCapability struct {
	Type       string `json:"type"`
	Permission string `json:"perm"`
}

AdminCapability is one admin capability of a user. Type is the capability type, such as users, usage, ratelimit or buckets; Permission is read, write, or * when both were granted (* does not mean global admin).

type Config

type Config struct {
	Name, Realm, Zonegroup, Zone, Region string
	SkipUserCreation                     bool
	TLS                                  *TLSConfig
}

Config selects a gateway instance and optional native RGW multisite scope. Name defaults to default; different names allow multiple gateways in one zone. Realm, Zonegroup and Zone must already exist when supplied. Region defaults to us-east-1. SkipUserCreation is useful when sharing existing S3 credentials or configuring multisite users through radosgw-admin.

type Container

type Container struct {
	*ceph.Container
}

Container is a cluster started by Run. It embeds *ceph.Container, so every cluster method is available on it; pass its Container field to functions that take a *ceph.Container, such as those of this and the other service packages.

func Run

Run starts a disposable cluster for S3 and Swift clients. It accepts every ceph.Run option and the options of other service packages. When no WithGateways option is given, it starts the default gateway and creates its test user. Bootstrap options that leave the cluster without OSDs or managers for the gateway, such as ceph.ClusterConfig.WithNoInitialOSDs, are rejected; use ceph.Run for those stages. A non-nil Container returned with an error must still be terminated.

Example
package main

import (
	"context"
	"log"

	"github.com/JSYoo5B/ceph-testcontainers-go/ceph"
	"github.com/JSYoo5B/ceph-testcontainers-go/rgw"
	"github.com/testcontainers/testcontainers-go"
)

func main() {
	ctx := context.Background()
	cluster, err := rgw.Run(ctx, ceph.DefaultImage,
		rgw.WithGateways(rgw.Config{Name: "s3", SkipUserCreation: true}),
	)
	defer func() {
		if err := testcontainers.TerminateContainer(cluster); err != nil {
			log.Printf("failed to terminate container: %s", err)
		}
	}()
	if err != nil {
		panic(err)
	}
	gateways, err := rgw.Gateways(ctx, cluster.Container)
	if err != nil {
		panic(err)
	}
	gateway := gateways[0]
	user, err := gateway.CreateUser(ctx, rgw.UserConfig{ID: "app"})
	if err != nil {
		panic(err)
	}
	endpoint, err := gateway.S3Endpoint(ctx)
	if err != nil {
		panic(err)
	}
	// Sign S3 requests to endpoint with user.Credentials().
	_, _ = user, endpoint
}

type Gateway

type Gateway struct {
	testcontainers.Container
	GatewayName string
	AccessKey   string
	SecretKey   string
	// Region is the SigV4 signing region: Config.Region, which defaults to
	// us-east-1, or for a multisite gateway its zonegroup name. RGW itself
	// is not configured with it.
	Region string
	// contains filtered or unexported fields
}

Gateway is an optional S3 gateway owned by its Ceph cluster. AccessKey and SecretKey belong to a generated ordinary S3 user for trusted tests.

Gateway embeds testcontainers.Container, so Stop, Start, Logs, Exec and Inspect act on the gateway container. Formatting a Gateway, User, Account, Placement or TLSConfig with any fmt verb, including %+v and %#v, prints only an identifying label such as "RGW gateway s3"; credentials and TLS keys are read explicitly from the fields or User.Credentials. A gateway runs with 4 worker threads: enough for functional tests, not for load tests. Rate limits are enforced by each gateway separately.

func Gateways

func Gateways(ctx context.Context, c *ceph.Container) ([]*Gateway, error)

Gateways returns sorted owned gateway descriptors, including partial startup attempts, while bounding the wait for fixture topology by ctx.

func Start

Start starts an independently owned, named gateway on an existing cluster. A zero config starts the default gateway and creates its test user. Customizers are applied last; preserve the required command, network and listener settings. A non-nil result returned with an error remains owned by the cluster for cleanup.

In host mode the port is reserved on the Docker host and released just before the daemon binds it; if another process takes it in between, startup is retried with a new port, up to five attempts. Server-side RGW options are read when a gateway starts: set them with override.SetConfig on a cluster from ceph.Run, then call Start. RGW runs as client.admin, so options in a ceph.WithConfigFile file belong in [client] or [client.admin].

func (*Gateway) Admin

func (g *Gateway) Admin(ctx context.Context, args ...string) ([]byte, error)

Admin invokes radosgw-admin inside this running gateway, preserving its realm, zonegroup, zone, Ceph configuration and keyring. The RGW role image supplies the CLI. Native arguments are passed individually, without a shell. Success output may contain credentials; failed command output is redacted. This is an explicit escape hatch for native operations beyond typed helpers; do not race raw user edits with owned-user creation or mutation.

--format json is always added. Arguments must not contain control characters, so pass JSON documents (policies, trust documents) as single-line strings. Arguments that would change the scope or connection are refused with ceph.ErrInvalidRequest: --rgw-realm, --rgw-zonegroup, --rgw-zone and their ID and name variants, --conf/-c, --keyring/-k, --name/-n, --id, --mon-host/-m, --cluster and similar flags.

The call is bounded by ctx and by the cluster's startup timeout, and no radosgw-admin outlives it: a small sh supervisor in the gateway container stops the command with SIGTERM, then SIGKILL after 2 s, 15 s before the bound (at half the bound for a short one; ceph.ErrNativeFailure, "radosgw-admin still ran after Ns and was stopped"), when ctx ends first (Admin then stops it under its own budget of about 10 s and returns ctx's error only after the command is gone; a call that ends before Docker started the command makes sure it never starts), or when the cluster's Terminate starts. When Admin cannot confirm the stop, for example because the gateway is paused or the engine is unreachable, it returns a *ceph.NativeCommandUnstoppedError whose Stop retries; Terminate retries too. Stopping radosgw-admin does not undo a request it already sent: the outcome of a stopped mutation is unknown and Admin never repeats it.

A failure keeps a *ceph.NativeFailure with the exit code and errno but no reason, so errors.Is(err, fs.ErrNotExist) works; run the same command with Exec to see the native text.

func (*Gateway) ApplyPlacement

func (g *Gateway) ApplyPlacement(ctx context.Context, p *Placement) error

ApplyPlacement activates a confirmed new policy. Standalone mode explicitly restarts only this owned gateway; resolve S3Endpoint again because Docker can assign a new mapped host port. Other gateways in the same zone require their own ApplyPlacement. Realm mode requires the current metadata master and commits a new period only when its topology differs solely by this new placement. Coordinate mappings in other zones before publishing a realm policy, import the committed period into those clusters and call ReloadPlacement there. It never changes defaults, deletes resources or silently rolls back a partial failure.

func (*Gateway) CreateAccount

func (g *Gateway) CreateAccount(ctx context.Context, config AccountConfig) (*Account, error)

CreateAccount creates a fresh account exclusively in the actual native gateway scope. Existing IDs are rejected and never adopted. A partial handle may be returned after a native failure, but ownership requires a validated creation response and native metadata version tag. Inspect uncertain results through Admin or terminate the disposable cluster; do not migrate users into them or blindly delete an identity whose creation was not confirmed.

func (*Gateway) CreatePlacement

func (g *Gateway) CreatePlacement(ctx context.Context, config PlacementConfig) (*Placement, error)

CreatePlacement creates a named target and all its storage classes in this gateway's actual running zone/zonegroup, even if global native defaults changed after it started. Existing targets in either scope are rejected. Every pool must already exist; native IDs are rechecked before each mutation. Changes are sequential and partial failure leaves inspectable configuration. On a realm, all participating zones need compatible local mappings before publication.

func (*Gateway) CreateUser

func (g *Gateway) CreateUser(ctx context.Context, config UserConfig) (*User, error)

CreateUser creates a fresh S3 identity and, optionally, explicit Admin Ops capabilities. Existing IDs are rejected without changing their keys or policy. A non-nil handle with an error records an attempted or partial creation. If the generated credentials were confirmed, the handle supports Info and Remove even after a later capability setup failure. If the creation response is malformed, truncated or missing keys, credentials and ownership cannot be confirmed: inspect through Admin or terminate the cluster rather than adopting native keys or blindly retrying the same ID. Native user edits from external clients must not race this operation.

func (*Gateway) DaemonEndpoint

func (c *Gateway) DaemonEndpoint(ctx context.Context) (string, error)

DaemonEndpoint returns the HTTP address used by peers in the gateway's Docker network or daemon-host namespace. Host mode returns the advertised address; bridge mode returns the gateway's IP in its Ceph cluster network. The caller must share or reach that network. Use S3Endpoint for host application clients.

On a ceph.AddressDualStack cluster it returns the gateway's IPv4 address; the gateway listens on 0.0.0.0:7480 and [::]:7480, so clients in the cluster network reach it over its IPv6 address on port 7480 too.

func (Gateway) Format added in v0.4.0

func (g Gateway) Format(f fmt.State, _ rune)

Format prints String for every verb and flag, so no verb, such as %d or %t, walks the fields.

func (Gateway) GoString

func (g Gateway) GoString() string

GoString formats the gateway like String, so %#v does not print its credentials.

func (*Gateway) ReloadPlacement

func (g *Gateway) ReloadPlacement(ctx context.Context, p *Placement) error

ReloadPlacement activates a confirmed policy in this owned gateway through restart, including a secondary realm zone. In realm mode the latest locally stored committed period must contain the exact owned target and zone. Import the published period through the multicluster fixture before reloading another cluster. This method never publishes, pulls or rewrites federation topology. Resolve S3Endpoint again because Docker may assign a new mapped host port.

func (*Gateway) Remove added in v0.4.0

func (g *Gateway) Remove(ctx context.Context) error

Remove removes this owned gateway container. Zone configuration, S3 users, buckets and data remain available through other gateways or a replacement. Multisite period endpoints are not changed automatically. The last gateway can be removed because RGW is optional. Failed cleanup remains tracked. A gateway that Remove already removed, or that is not the one the cluster owns for its name, returns an error.

func (*Gateway) S3Endpoint

func (c *Gateway) S3Endpoint(ctx context.Context) (string, error)

S3Endpoint returns the HTTP endpoint for host S3 clients. Bridge mode uses its mapped port; host mode uses the selected daemon port. The default 127.0.0.1 address uses the Docker provider host, while a custom host address is returned directly, matching the gateway's bind address. Configure clients to use path-style addressing and the test credentials.

Sign with Gateway.Region. In bridge mode the mapped port can change whenever the gateway container restarts (ApplyPlacement, ReloadPlacement, multisite sync group and zone changes, or the caller's own Stop and Start): call S3Endpoint again afterwards.

func (*Gateway) S3SecureEndpoint

func (g *Gateway) S3SecureEndpoint(ctx context.Context) (string, error)

S3SecureEndpoint returns the native HTTPS listener's mapped or selected host endpoint. It returns an error when TLS was not configured. This method does not disable certificate verification or alter application TLS settings.

func (Gateway) String

func (g Gateway) String() string

String names the gateway without its S3 credentials or TLS key.

type Placement

type Placement struct {
	Name, RealmID, ZonegroupID, ZoneID, LocationConstraint string
	// contains filtered or unexported fields
}

Placement identifies a newly created native policy and its exact runtime scope. LocationConstraint can be passed to S3 CreateBucket. Creation stores configuration; ApplyPlacement restarts a standalone gateway or publishes a guarded realm period. Import that period into other clusters before explicitly activating their gateways with ReloadPlacement. Failed creation may return a partial handle for inspection; it is never rolled back by deleting pools, policies, buckets or data.

func (Placement) Format added in v0.4.0

func (p Placement) Format(f fmt.State, _ rune)

Format prints String for every verb and flag, so no verb, such as %d or %t, walks the fields.

func (Placement) GoString

func (p Placement) GoString() string

GoString formats the placement target like String.

func (*Placement) Status added in v0.4.0

func (p *Placement) Status(ctx context.Context) (PlacementState, error)

Status reads the exact native scope of a created or partial policy, through the first running registered gateway, by name, in the scope of the gateway that created it. Incomplete or changed mappings return an error; use Gateway.Admin for detailed partial inspection. It does not claim a running gateway reloaded this configuration.

func (Placement) String

func (p Placement) String() string

String names the placement target.

type PlacementConfig

type PlacementConfig struct {
	Name, IndexPool, DataExtraPool string
	StorageClasses                 []StorageClassConfig
	InlineData                     *bool
	// Tags restrict creation of new buckets using this target to users with
	// at least one matching placement tag. An empty list permits every user.
	// These tags do not grant access to existing buckets or their objects.
	Tags []string
}

PlacementConfig adds a fresh, non-default bucket placement target. IndexPool and DataExtraPool must be existing replicated pools supporting omap. It never changes the zonegroup default or any existing bucket's immutable placement. InlineData nil preserves Ceph's true default; false separates object heads and data. Native external placement/topology edits must not race these helpers.

DataExtraPool holds incomplete multipart metadata.

type PlacementState

type PlacementState struct {
	PlacementConfig
	RealmID, ZonegroupID, ZoneID, LocationConstraint, DefaultPlacement string
	// Confirmed reports successful creation/readback of this owned handle.
	// It does not assert that a gateway reloaded the policy or a realm published it.
	Confirmed bool
}

PlacementState is a native policy snapshot. DefaultPlacement is the zonegroup default, which these helpers never modify. Creation and activation do not assign any user's default placement or storage class.

type Quota

type Quota struct {
	Enabled      bool
	MaxSizeBytes int64
	MaxObjects   int64
}

Quota uses bytes, matching modern radosgw-admin output. For each limit, -1 disables that limit; zero is an actual zero limit. Enabled controls whether the configured limits are enforced. Native RGW quota caches and asynchronous accounting can delay enforcement; reading this policy does not flush caches.

type StorageClassConfig

type StorageClassConfig struct {
	Name, DataPool string
}

StorageClassConfig maps one native S3 storage class to an existing data pool. STANDARD is required. Other class names, for example STANDARD_IA, must also be accepted by the consumer's S3 SDK. Data pools may be replicated or EC; RGW does not require EC overwrites because it writes complete objects.

type TLSConfig

type TLSConfig struct {
	CertificatePEM, PrivateKeyPEM []byte
}

TLSConfig enables a native Beast HTTPS listener alongside HTTP. Supply a PEM certificate chain and matching unencrypted private key. No proxy is involved. Clients must explicitly trust its CA and use a matching hostname. Files live only in the owned RGW container; descriptors never log key bytes.

The bytes are copied; the certificate and key are written to /tc/rgw-tls.pem with mode 0600 inside the gateway container only. In bridge mode container ports 7480 (HTTP) and 7481 (HTTPS) are mapped to random host ports; in host mode two free host ports are reserved. Startup verifies that the gateway process owns the HTTPS socket and that the listener presents the configured certificate. ceph.NetworkConfig.WithMessengerMode does not enable HTTPS.

func (TLSConfig) Format added in v0.4.0

func (c TLSConfig) Format(f fmt.State, _ rune)

Format prints String for every verb and flag, so no verb, such as %d or %t, walks the fields.

func (TLSConfig) GoString

func (c TLSConfig) GoString() string

GoString formats the configuration like String, so %#v does not print the key.

func (TLSConfig) String

func (TLSConfig) String() string

String describes the configuration without the certificate or key.

type User

type User struct {
	// contains filtered or unexported fields
}

User is an identity created through a gateway. Credentials are returned explicitly by Credentials; formatting this handle never includes secrets. Users remain in Ceph when a gateway is removed, until explicitly removed or the disposable cluster is terminated. Its operations run through the first running registered gateway, by name, in the scope of the gateway that created it, so they keep working after that gateway is removed if another one serves it.

func (*User) Credentials

func (u *User) Credentials() (accessKey, secretKey string, err error)

Credentials returns the generated S3 access and secret keys as explicit copies. Previously copied credentials are not erased by user removal.

func (User) Format added in v0.4.0

func (u User) Format(f fmt.State, _ rune)

Format prints String for every verb and flag, so no verb, such as %d or %t, walks the fields.

func (User) GoString

func (u User) GoString() string

GoString formats the user like String, so %#v does not print its keys.

func (*User) ID

func (u *User) ID() string

ID returns the canonical native ID, tenant$localID for a tenanted user. Empty-tenant identities retain their existing unprefixed IDs.

func (*User) Info added in v0.4.0

func (u *User) Info(ctx context.Context) (UserInfo, error)

Info reads an owned user's quota, capabilities, suspension and placement defaults/tags. Placement tags control new bucket placement, not object access. It verifies the created key, original native user type and original account association remain present before returning the policy. Account roots also require the creation-owned account's native metadata lifetime to remain valid.

func (*User) Remove added in v0.4.0

func (u *User) Remove(ctx context.Context) error

Remove removes an owned identity without purging buckets or objects. The handle must contain its confirmed generated credentials; an incomplete creation response never permits adopting keys from a later native query. Ceph refuses ordinary users that still own buckets; remove those through the S3 client first. Account buckets belong to the account and may outlive a root user's removal; Account.Remove independently refuses a nonempty account. Success is idempotent across copies of a handle. After an uncertain native failure, an absent user is accepted as completed removal; a user still present remains tracked and its created key is verified before retrying.

func (*User) SetBucketQuota added in v0.4.0

func (u *User) SetBucketQuota(ctx context.Context, quota Quota) error

SetBucketQuota configures the per-bucket limits for all buckets owned by this user. Use Gateway.Admin for a policy on a single named bucket.

The limits apply to each bucket the user owns, individually. Quota enforcement depends on native statistics and caches, so a write right after a quota change, or right after the quota is reached, may still be accepted: poll with new writes when testing rejection.

func (*User) SetPlacement added in v0.4.0

func (u *User) SetPlacement(ctx context.Context, p *Placement, config UserPlacementConfig) error

SetPlacement sets an owned user's default placement/storage class and, optionally, replaces its placement tags. It uses the gateway's actual native zone IDs, validates the confirmed placement and its unchanged pool IDs and class mappings, and verifies that unrelated native user policy and keys did not change. Mutable public placement fields never select the native target.

Existing buckets keep their immutable placement. This changes user metadata; it does not activate pending zone configuration or publish a realm period. ApplyPlacement/ReloadPlacement must activate the target before S3 uses it. Native metadata caches may delay new S3 requests. External user/placement edits must not race this operation. A failed readback may follow a persisted change; Info reads native state, and the same request can be retried.

func (*User) SetQuota added in v0.4.0

func (u *User) SetQuota(ctx context.Context, quota Quota) error

SetQuota replaces both user limits and the enabled state. If a later native command fails, a policy change may already have persisted; Info reads the authoritative state and the same request can safely be retried.

func (User) String

func (u User) String() string

String names the user without its keys.

func (*User) Suspend added in v0.4.0

func (u *User) Suspend(ctx context.Context, suspended bool) error

Suspend disables or re-enables S3 access for an owned user and reads back native state. Gateway metadata caches may delay the observed HTTP response; callers should poll new requests when testing suspension or re-enablement.

func (*User) Usage added in v0.4.0

func (user *User) Usage(ctx context.Context) (UserUsage, error)

Usage reads current storage counters for an owned user's effective native owner. For an account root it returns the account aggregate with Scope account and OwnerID equal to the originally owned account ID. It rechecks the user key, type, account lifetime and scope before returning; no user, account, bucket or statistics are created, changed, synchronized, reset or adopted.

Poll until the expected values appear. For an explicit synchronisation step run gateway.Admin(ctx, "user", "stats", "--uid", user.ID(), "--sync-stats") as separate setup.

type UserConfig

type UserConfig struct {
	ID, DisplayName, Email string
	Tenant                 string
	AdminCaps              string
	MaxBuckets             *int
}

UserConfig describes a new S3 identity. Empty ID generates a unique ID; DisplayName defaults to Testcontainers. AdminCaps is an explicit native expression such as "users=read;usage=read" for the RGW Admin Ops REST API. Neither the global admin nor the multisite system flag is granted. MaxBuckets nil preserves Ceph's default; zero allows unlimited buckets and -1 forbids creating buckets. Tenant selects a native namespace; empty preserves the legacy namespace. ID is the local user ID, without a tenant prefix.

Tenant is letters, digits and underscores and must not look like an account ID; a tenant user's canonical ID is tenant$id, and buckets with the same name can exist in different tenants.

type UserInfo

type UserInfo struct {
	ID, DisplayName, Email                      string
	Tenant, LocalID, Namespace, Type, AccountID string
	Suspended, Admin, System                    bool
	MaxBuckets                                  int
	AdminCaps                                   []AdminCapability
	UserQuota, BucketQuota                      Quota
	DefaultPlacement, DefaultStorageClass       string
	PlacementTags                               []string
}

UserInfo is a current native policy snapshot, deliberately excluding keys. BucketQuota applies individually to every bucket owned by this user. DefaultStorageClass preserves native representation: STANDARD on a named default placement is persisted and later read back as an empty string.

Type is rgw (or empty) for ordinary users and root for account root users. The fixture never sets Admin or System. PlacementTags allow the user to create buckets in tagged placement targets and grant no object access.

type UserPlacementConfig

type UserPlacementConfig struct {
	StorageClass string
	Tags         []string
}

UserPlacementConfig selects an owned placement as a user's default for future buckets. StorageClass defaults to STANDARD. Tags nil preserves the user's current placement tags; a nonempty list replaces them exactly. An explicitly empty list is unsupported by radosgw-admin and is rejected. Replace matching tags with nonmatching tags to revoke access to a restricted target. Placement tags authorize new bucket placement, not object access.

type UserUsage

type UserUsage struct {
	UserID, Tenant, Scope, OwnerID string
	// SizeBytes is native size; SizeActualBytes is native size_actual (rounded
	// accounting bytes), not physical allocation or replica/billing bytes.
	SizeBytes, SizeActualBytes, NumObjects uint64
	// Preserve native timestamp strings, including native zero timestamps.
	LastStatsSync, LastStatsUpdate string
}

UserUsage is a native storage-accounting snapshot, not dated request or bandwidth usage. Scope is "user" for an ordinary user and "account" for an account identity. OwnerID identifies that effective aggregation owner; account stats cover all of the account's users, roles and buckets, not only UserID. Native accounting updates asynchronously; this snapshot does not force sync, flush quota caches, prove quota enforcement or verify object content.

Directories

Path Synopsis
Package multisite orchestrates RGW multisite fixtures across independent Ceph clusters: one realm, zones and zonegroups, period transfer, sync status and sync policies.
Package multisite orchestrates RGW multisite fixtures across independent Ceph clusters: one realm, zones and zonegroups, period transfer, sync status and sync policies.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL