radosgw-admin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1599 @@
1
+ /**
2
+ * Configuration for the RadosGW Admin Client.
3
+ */
4
+ interface ClientConfig {
5
+ /** RGW endpoint, e.g. "http://192.168.1.10" or "https://ceph.example.com" */
6
+ host: string;
7
+ /** Port number. Omit to use the default from the host URL. */
8
+ port?: number;
9
+ /** Admin access key for AWS SigV4 authentication */
10
+ accessKey: string;
11
+ /** Admin secret key for AWS SigV4 authentication */
12
+ secretKey: string;
13
+ /** Admin API path prefix. Default: "/admin" */
14
+ adminPath?: string;
15
+ /** Request timeout in milliseconds. Default: 10000 */
16
+ timeout?: number;
17
+ /** Skip TLS certificate verification. Default: false */
18
+ insecure?: boolean;
19
+ /** Enable debug logging of requests and responses. Default: false */
20
+ debug?: boolean;
21
+ /** Maximum number of retries for transient errors (5xx, timeouts, network errors). Default: 0 (no retries) */
22
+ maxRetries?: number;
23
+ /** Base delay in ms for exponential backoff between retries. Default: 200 */
24
+ retryDelay?: number;
25
+ /** AWS region for SigV4 signing. Default: "us-east-1" */
26
+ region?: string;
27
+ }
28
+ /** HTTP methods used by the RGW Admin API */
29
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
30
+ /** Internal request options passed to the base client */
31
+ interface RequestOptions {
32
+ method: HttpMethod;
33
+ path: string;
34
+ query?: Record<string, string | number | boolean | undefined>;
35
+ body?: Record<string, unknown>;
36
+ }
37
+
38
+ /**
39
+ * Core HTTP client for making signed requests to the RGW Admin API.
40
+ * @internal
41
+ */
42
+ declare class BaseClient {
43
+ private readonly host;
44
+ private readonly port;
45
+ private readonly accessKey;
46
+ private readonly secretKey;
47
+ private readonly adminPath;
48
+ private readonly timeout;
49
+ private readonly region;
50
+ private readonly debug;
51
+ private readonly maxRetries;
52
+ private readonly retryDelay;
53
+ private readonly insecure;
54
+ constructor(config: ClientConfig);
55
+ /**
56
+ * Logs a debug message with optional structured data.
57
+ */
58
+ private log;
59
+ /**
60
+ * Determines whether an error is retryable (5xx, timeouts, network errors).
61
+ */
62
+ private isRetryable;
63
+ /**
64
+ * Checks an error and its cause chain for network error patterns.
65
+ */
66
+ private hasNetworkErrorPattern;
67
+ /**
68
+ * Returns a promise that resolves after the given number of milliseconds.
69
+ */
70
+ private delay;
71
+ /**
72
+ * Makes a signed HTTP request to the RGW Admin API with retry support.
73
+ *
74
+ * @param options - Request method, path, query params, and optional body
75
+ * @returns Parsed and camelCase-transformed JSON response, or void for empty responses
76
+ */
77
+ request<T>(options: RequestOptions): Promise<T>;
78
+ /**
79
+ * Builds the full request URL with query parameters.
80
+ */
81
+ private buildUrl;
82
+ /**
83
+ * Temporarily disables TLS certificate verification for insecure mode.
84
+ * Returns the previous value so it can be restored.
85
+ */
86
+ private disableTlsVerification;
87
+ /**
88
+ * Restores the TLS verification setting to its previous value.
89
+ */
90
+ private restoreTlsVerification;
91
+ /**
92
+ * Parses an error response body to extract the RGW error code.
93
+ */
94
+ private parseErrorCode;
95
+ /**
96
+ * Wraps a non-RGW error into the appropriate RGW error type.
97
+ */
98
+ private wrapFetchError;
99
+ /**
100
+ * Executes a single signed HTTP request to the RGW Admin API.
101
+ */
102
+ private executeRequest;
103
+ }
104
+
105
+ /** Input for creating a new RGW user. */
106
+ interface CreateUserInput {
107
+ /** Unique user ID. Required. Must not contain colons (reserved for subuser notation). */
108
+ uid: string;
109
+ /** Display name for the user. Required. Must not be whitespace-only. */
110
+ displayName: string;
111
+ /** Email address. Basic format validation is applied. */
112
+ email?: string;
113
+ /** Key type to generate. Default: 's3'. */
114
+ keyType?: 's3' | 'swift';
115
+ /** Specify an access key instead of auto-generating. */
116
+ accessKey?: string;
117
+ /**
118
+ * Specify a secret key instead of auto-generating.
119
+ * @remarks This value is transmitted as a query parameter per the RGW Admin Ops API wire
120
+ * format. It is redacted from debug logs by the client.
121
+ */
122
+ secretKey?: string;
123
+ /**
124
+ * User capabilities string. Controls which admin operations the user may perform.
125
+ * Format: `"type=perm"` or `"type1=perm;type2=perm"`.
126
+ * Valid types: `users`, `buckets`, `metadata`, `usage`, `zone`, `info`, `bilog`,
127
+ * `mdlog`, `datalog`, `user-policy`, `oidc-provider`, `roles`, `ratelimit`.
128
+ * Valid perms: `*`, `read`, `write`, `read, write`.
129
+ * @example `"users=*;buckets=read"`
130
+ */
131
+ userCaps?: string;
132
+ /** Whether to auto-generate a key pair. Default: true. */
133
+ generateKey?: boolean;
134
+ /** Maximum number of buckets allowed. Default: 1000. Use -1 for unlimited. */
135
+ maxBuckets?: number;
136
+ /** Whether the user is suspended on creation. Default: false. */
137
+ suspended?: boolean;
138
+ /** Tenant name for multi-tenancy. */
139
+ tenant?: string;
140
+ /**
141
+ * Operation mask — limits which S3 operations the user can perform.
142
+ * Comma-separated list of operations: `read`, `write`, `delete`, `*`.
143
+ * @example `"read, write"`
144
+ */
145
+ opMask?: string;
146
+ }
147
+ /** Input for modifying an existing user. */
148
+ interface ModifyUserInput {
149
+ /** User ID to modify. Required. */
150
+ uid: string;
151
+ /** New display name. */
152
+ displayName?: string;
153
+ /** New email address. Basic format validation is applied. */
154
+ email?: string;
155
+ /** Maximum number of buckets. */
156
+ maxBuckets?: number;
157
+ /** Suspend or unsuspend the user. */
158
+ suspended?: boolean;
159
+ /** User capabilities string. See {@link CreateUserInput.userCaps} for format. */
160
+ userCaps?: string;
161
+ /** Operation mask. See {@link CreateUserInput.opMask} for format. */
162
+ opMask?: string;
163
+ }
164
+ /** Input for deleting a user. */
165
+ interface DeleteUserInput {
166
+ /** User ID to delete. Required. */
167
+ uid: string;
168
+ /** If true, permanently deletes all buckets and objects owned by the user. Default: false. DESTRUCTIVE. */
169
+ purgeData?: boolean;
170
+ }
171
+ /** An S3 key pair associated with a user. */
172
+ interface RGWKey {
173
+ user: string;
174
+ accessKey: string;
175
+ secretKey: string;
176
+ }
177
+ /** A Swift key associated with a user. */
178
+ interface RGWSwiftKey {
179
+ user: string;
180
+ secretKey: string;
181
+ }
182
+ /** A subuser reference. */
183
+ interface RGWSubuser {
184
+ id: string;
185
+ permissions: string;
186
+ }
187
+ /** A user capability entry. */
188
+ interface RGWCap {
189
+ type: string;
190
+ perm: string;
191
+ }
192
+ /** Quota configuration (used for both user and bucket quotas). */
193
+ interface RGWQuota {
194
+ enabled: boolean;
195
+ checkOnRaw: boolean;
196
+ /** Quota in bytes. -1 means unlimited. */
197
+ maxSize: number;
198
+ /** Quota in kilobytes. -1 means unlimited. */
199
+ maxSizeKb: number;
200
+ /** Maximum number of objects. -1 means unlimited. */
201
+ maxObjects: number;
202
+ }
203
+ /** Full RGW user object returned by the admin API. */
204
+ interface RGWUser {
205
+ userId: string;
206
+ displayName: string;
207
+ email: string;
208
+ /**
209
+ * Whether the user is suspended. `0` = active, `1` = suspended.
210
+ * Use numeric comparison: `user.suspended === 1` or treat as truthy/falsy.
211
+ */
212
+ suspended: number;
213
+ maxBuckets: number;
214
+ subusers: RGWSubuser[];
215
+ keys: RGWKey[];
216
+ swiftKeys: RGWSwiftKey[];
217
+ caps: RGWCap[];
218
+ opMask: string;
219
+ defaultPlacement: string;
220
+ defaultStorageClass: string;
221
+ placementTags: string[];
222
+ tenant: string;
223
+ bucketQuota: RGWQuota;
224
+ userQuota: RGWQuota;
225
+ /**
226
+ * User type. Common values: `"rgw"`, `"ldap"`, `"s3"`.
227
+ * May be absent on older Ceph versions.
228
+ */
229
+ type?: string;
230
+ /** MFA device IDs associated with this user. May be absent on older Ceph versions. */
231
+ mfaIds?: string[];
232
+ }
233
+ /** The raw usage statistics returned by `GET /user?stats=true`. */
234
+ interface RGWUserStatData {
235
+ /** Total bytes used (logical). */
236
+ size: number;
237
+ /** Total bytes actually consumed on disk (accounting for alignment). */
238
+ sizeActual: number;
239
+ /** Total bytes utilized (used + overhead). */
240
+ sizeUtilized: number;
241
+ /** Total kilobytes used (logical). */
242
+ sizeKb: number;
243
+ /** Total kilobytes actually on disk. */
244
+ sizeKbActual: number;
245
+ /** Total kilobytes utilized. */
246
+ sizeKbUtilized: number;
247
+ /** Total number of objects stored. */
248
+ numObjects: number;
249
+ }
250
+ /**
251
+ * Full user object with embedded storage statistics.
252
+ * Returned by `client.users.getStats()`.
253
+ * Contains all fields from {@link RGWUser} plus a `stats` field.
254
+ */
255
+ interface RGWUserWithStats extends RGWUser {
256
+ stats: RGWUserStatData;
257
+ }
258
+
259
+ /**
260
+ * User management module — create, get, modify, delete, list, suspend, enable,
261
+ * get stats, and look up users by access key.
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * const user = await client.users.create({ uid: 'alice', displayName: 'Alice' });
266
+ * const same = await client.users.getByAccessKey(user.keys[0].accessKey);
267
+ * ```
268
+ */
269
+ declare class UsersModule {
270
+ private readonly client;
271
+ constructor(client: BaseClient);
272
+ /**
273
+ * Create a new RGW user.
274
+ *
275
+ * @param input - User creation parameters. `uid` and `displayName` are required.
276
+ * @returns The newly created user object with keys, caps, and quotas.
277
+ * @throws {RGWValidationError} If `uid` contains colons, `displayName` is blank,
278
+ * `email` is malformed, or `userCaps` is an invalid capability string.
279
+ * @throws {RGWConflictError} If a user with the given `uid` already exists.
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * const user = await client.users.create({
284
+ * uid: 'alice',
285
+ * displayName: 'Alice Example',
286
+ * email: 'alice@example.com',
287
+ * maxBuckets: 100,
288
+ * userCaps: 'users=read;buckets=*',
289
+ * });
290
+ * console.log(user.keys[0].accessKey);
291
+ * ```
292
+ */
293
+ create(input: CreateUserInput): Promise<RGWUser>;
294
+ /**
295
+ * Get full user information including keys, caps, and quotas.
296
+ *
297
+ * For multi-tenant setups pass the `tenant` parameter instead of embedding
298
+ * it in the uid string. Both `get('alice', 'acme')` and `get('acme$alice')`
299
+ * resolve to the same user; the former is preferred for clarity.
300
+ *
301
+ * @param uid - The user ID (without tenant prefix).
302
+ * @param tenant - Optional tenant name. When provided, resolves to `tenant$uid`.
303
+ * @returns Full user object.
304
+ * @throws {RGWValidationError} If `uid` is empty.
305
+ * @throws {RGWNotFoundError} If the user does not exist.
306
+ *
307
+ * @example
308
+ * ```typescript
309
+ * // Standard lookup
310
+ * const user = await client.users.get('alice');
311
+ *
312
+ * // Multi-tenant lookup
313
+ * const tenantUser = await client.users.get('alice', 'acme');
314
+ * ```
315
+ */
316
+ get(uid: string, tenant?: string): Promise<RGWUser>;
317
+ /**
318
+ * Look up a user by their S3 access key.
319
+ *
320
+ * Useful for mapping an incoming S3 request's access key to the owning user
321
+ * without knowing the uid in advance.
322
+ *
323
+ * @param accessKey - The S3 access key to look up.
324
+ * @returns The user that owns this access key.
325
+ * @throws {RGWValidationError} If `accessKey` is empty.
326
+ * @throws {RGWNotFoundError} If no user owns this access key.
327
+ *
328
+ * @example
329
+ * ```typescript
330
+ * const user = await client.users.getByAccessKey('AKIAIOSFODNN7EXAMPLE');
331
+ * console.log('Key belongs to:', user.userId);
332
+ * ```
333
+ */
334
+ getByAccessKey(accessKey: string): Promise<RGWUser>;
335
+ /**
336
+ * Modify an existing user's properties.
337
+ *
338
+ * Only the provided fields are updated — omitted fields retain their current values.
339
+ *
340
+ * @param input - Properties to update. `uid` is required; all other fields are optional.
341
+ * @returns The updated user object.
342
+ * @throws {RGWValidationError} If `uid` is empty, `email` is malformed,
343
+ * or `userCaps` is an invalid capability string.
344
+ * @throws {RGWNotFoundError} If the user does not exist.
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * const updated = await client.users.modify({
349
+ * uid: 'alice',
350
+ * displayName: 'Alice Updated',
351
+ * maxBuckets: 200,
352
+ * opMask: 'read, write',
353
+ * });
354
+ * ```
355
+ */
356
+ modify(input: ModifyUserInput): Promise<RGWUser>;
357
+ /**
358
+ * Delete a user. Optionally purge all user data (buckets and objects).
359
+ *
360
+ * @param input - `uid` is required. Set `purgeData: true` to delete all objects.
361
+ * @throws {RGWValidationError} If `uid` is empty.
362
+ * @throws {RGWNotFoundError} If the user does not exist.
363
+ *
364
+ * @example
365
+ * ```typescript
366
+ * // Safe delete — fails if user owns buckets
367
+ * await client.users.delete({ uid: 'alice' });
368
+ *
369
+ * // ⚠️ Force delete with full data purge
370
+ * await client.users.delete({ uid: 'alice', purgeData: true });
371
+ * ```
372
+ */
373
+ delete(input: DeleteUserInput): Promise<void>;
374
+ /**
375
+ * List all user IDs in the cluster (or tenant).
376
+ *
377
+ * Returns the full list in a single call. The RGW `/metadata/user` endpoint
378
+ * supports `marker` and `max-entries` for server-side pagination, but has a
379
+ * default limit of 1000 entries. This method requests up to 100,000 entries
380
+ * to avoid silent truncation on large clusters.
381
+ *
382
+ * For clusters with more than 100k users, use the planned `paginate()` method
383
+ * (see v1.6 roadmap).
384
+ *
385
+ * @returns Array of user ID strings.
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * const uids = await client.users.list();
390
+ * console.log('Total users:', uids.length);
391
+ * ```
392
+ */
393
+ list(): Promise<string[]>;
394
+ /**
395
+ * Suspend a user account. The user's data is preserved but all API access is denied.
396
+ *
397
+ * @param uid - The user ID to suspend.
398
+ * @returns The updated user object with `suspended: 1`.
399
+ * @throws {RGWValidationError} If `uid` is empty.
400
+ * @throws {RGWNotFoundError} If the user does not exist.
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * const suspended = await client.users.suspend('alice');
405
+ * console.log(suspended.suspended); // 1
406
+ * ```
407
+ */
408
+ suspend(uid: string): Promise<RGWUser>;
409
+ /**
410
+ * Re-enable a suspended user account.
411
+ *
412
+ * @param uid - The user ID to enable.
413
+ * @returns The updated user object with `suspended: 0`.
414
+ * @throws {RGWValidationError} If `uid` is empty.
415
+ * @throws {RGWNotFoundError} If the user does not exist.
416
+ *
417
+ * @example
418
+ * ```typescript
419
+ * const enabled = await client.users.enable('alice');
420
+ * console.log(enabled.suspended); // 0
421
+ * ```
422
+ */
423
+ enable(uid: string): Promise<RGWUser>;
424
+ /**
425
+ * Get storage usage statistics for a user.
426
+ *
427
+ * Returns the full user object with an additional `stats` field containing:
428
+ * - `size` / `sizeKb` — logical bytes/KB used
429
+ * - `sizeActual` / `sizeKbActual` — bytes/KB on disk (accounting for alignment)
430
+ * - `sizeUtilized` / `sizeKbUtilized` — bytes/KB utilized (used + overhead)
431
+ * - `numObjects` — total number of objects stored
432
+ *
433
+ * Pass `sync: true` to force RGW to recalculate stats from the backing store
434
+ * before returning (slower but accurate).
435
+ *
436
+ * @param uid - The user ID.
437
+ * @param sync - If true, forces a stats sync before returning. Default: false.
438
+ * @returns User object with embedded {@link RGWUserStatData} `stats` field.
439
+ * @throws {RGWValidationError} If `uid` is empty.
440
+ * @throws {RGWNotFoundError} If the user does not exist.
441
+ *
442
+ * @example
443
+ * ```typescript
444
+ * // Fast read (may be slightly stale)
445
+ * const result = await client.users.getStats('alice');
446
+ *
447
+ * // Force sync — accurate but slower
448
+ * const synced = await client.users.getStats('alice', true);
449
+ *
450
+ * console.log('Objects:', result.stats.numObjects);
451
+ * console.log('Size (KB):', result.stats.sizeKb);
452
+ * console.log('Actual disk (KB):', result.stats.sizeKbActual);
453
+ * ```
454
+ */
455
+ getStats(uid: string, sync?: boolean): Promise<RGWUserWithStats>;
456
+ }
457
+
458
+ /** Input for creating a new S3 or Swift key for a user. */
459
+ interface CreateKeyInput {
460
+ /** User ID to create the key for. Required. */
461
+ uid: string;
462
+ /** Key type. Default: 's3'. */
463
+ keyType?: 's3' | 'swift';
464
+ /** Specify an access key instead of auto-generating. */
465
+ accessKey?: string;
466
+ /**
467
+ * Specify a secret key instead of auto-generating.
468
+ * @remarks This value is transmitted as a query parameter per the RGW Admin Ops API wire
469
+ * format. It is redacted from debug logs by the client.
470
+ */
471
+ secretKey?: string;
472
+ /** Whether to auto-generate the key. Default: true. */
473
+ generateKey?: boolean;
474
+ }
475
+ /** Input for deleting an S3 or Swift key. */
476
+ interface DeleteKeyInput {
477
+ /** The access key to delete. Required. */
478
+ accessKey: string;
479
+ /** User ID. Required for Swift keys. */
480
+ uid?: string;
481
+ /** Key type. Default: 's3'. */
482
+ keyType?: 's3' | 'swift';
483
+ }
484
+ /** Input for creating a subuser. */
485
+ interface CreateSubuserInput {
486
+ /** Parent user UID. Required. */
487
+ uid: string;
488
+ /** Subuser ID in `uid:name` format (e.g. `"alice:swift"`). Required. */
489
+ subuser: string;
490
+ /**
491
+ * Secret key for the subuser. Auto-generated if omitted.
492
+ * @remarks This value is transmitted as a query parameter per the RGW Admin Ops API wire
493
+ * format. It is redacted from debug logs by the client.
494
+ */
495
+ secretKey?: string;
496
+ /** Key type for the subuser. */
497
+ keyType?: 'swift' | 's3';
498
+ /** Access level for the subuser. */
499
+ access?: 'read' | 'write' | 'readwrite' | 'full';
500
+ /** Whether to auto-generate a secret. Default: true. */
501
+ generateSecret?: boolean;
502
+ }
503
+ /** Input for modifying a subuser. */
504
+ interface ModifySubuserInput {
505
+ /** Parent user UID. Required. */
506
+ uid: string;
507
+ /** Subuser ID in `uid:name` format (e.g. `"alice:swift"`). Required. */
508
+ subuser: string;
509
+ /**
510
+ * Secret key for the subuser.
511
+ * @remarks This value is transmitted as a query parameter per the RGW Admin Ops API wire
512
+ * format. It is redacted from debug logs by the client.
513
+ */
514
+ secretKey?: string;
515
+ /** Key type for the subuser. */
516
+ keyType?: 'swift' | 's3';
517
+ /** Updated access level. */
518
+ access?: 'read' | 'write' | 'readwrite' | 'full';
519
+ /** Whether to auto-generate a secret. */
520
+ generateSecret?: boolean;
521
+ }
522
+ /** Input for deleting a subuser. */
523
+ interface DeleteSubuserInput {
524
+ /** Parent user UID. Required. */
525
+ uid: string;
526
+ /** Subuser ID in `uid:name` format (e.g. `"alice:swift"`). Required. */
527
+ subuser: string;
528
+ /** Whether to also purge the subuser's keys. Default: true. */
529
+ purgeKeys?: boolean;
530
+ }
531
+
532
+ /**
533
+ * Key management module — generate and revoke S3/Swift access keys.
534
+ *
535
+ * @example
536
+ * ```typescript
537
+ * // Generate a new key pair for a user
538
+ * const keys = await client.keys.generate({ uid: 'alice' });
539
+ * console.log(keys[0].accessKey, keys[0].secretKey);
540
+ *
541
+ * // Revoke a specific key
542
+ * await client.keys.revoke({ accessKey: 'OLDKEY123' });
543
+ * ```
544
+ */
545
+ declare class KeysModule {
546
+ private readonly client;
547
+ constructor(client: BaseClient);
548
+ /**
549
+ * Generate a new S3 or Swift key for a user.
550
+ *
551
+ * Returns the user's **entire** key list after the operation, not just the
552
+ * newly created key. To identify the new key, compare with the key list
553
+ * before generation or look for the last entry.
554
+ *
555
+ * @param input - Key generation parameters. `uid` is required.
556
+ * @returns Array of **all** keys belonging to the user after generation.
557
+ * @throws {RGWValidationError} If `uid` is missing or invalid.
558
+ * @throws {RGWNotFoundError} If the user does not exist.
559
+ *
560
+ * @example
561
+ * ```typescript
562
+ * // Auto-generate a new S3 key
563
+ * const allKeys = await client.keys.generate({ uid: 'alice' });
564
+ * const newKey = allKeys[allKeys.length - 1]; // newest key is last
565
+ * console.log('New key:', newKey.accessKey);
566
+ *
567
+ * // Supply specific credentials (disable auto-generation)
568
+ * const allKeys = await client.keys.generate({
569
+ * uid: 'alice',
570
+ * accessKey: 'MY_ACCESS_KEY',
571
+ * secretKey: 'MY_SECRET_KEY',
572
+ * generateKey: false,
573
+ * });
574
+ * ```
575
+ */
576
+ generate(input: CreateKeyInput): Promise<RGWKey[]>;
577
+ /**
578
+ * Revoke an S3 or Swift key.
579
+ *
580
+ * @param input - `accessKey` is required. `uid` is required for Swift keys.
581
+ * @returns Resolves when the key has been revoked.
582
+ * @throws {RGWValidationError} If `accessKey` is missing.
583
+ * @throws {RGWNotFoundError} If the key does not exist.
584
+ *
585
+ * @example
586
+ * ```typescript
587
+ * // Revoke an S3 key by access key ID
588
+ * await client.keys.revoke({ accessKey: 'OLDKEY123' });
589
+ *
590
+ * // Revoke a Swift key (uid required)
591
+ * await client.keys.revoke({
592
+ * accessKey: 'SWIFTKEY',
593
+ * uid: 'alice',
594
+ * keyType: 'swift',
595
+ * });
596
+ * ```
597
+ */
598
+ revoke(input: DeleteKeyInput): Promise<void>;
599
+ }
600
+
601
+ /**
602
+ * Subuser management module — create, modify, and remove subusers with Swift keys.
603
+ *
604
+ * @example
605
+ * ```typescript
606
+ * // Create a subuser with Swift access
607
+ * const subusers = await client.subusers.create({
608
+ * uid: 'alice',
609
+ * subuser: 'alice:swift',
610
+ * access: 'readwrite',
611
+ * keyType: 'swift',
612
+ * });
613
+ * ```
614
+ */
615
+ declare class SubusersModule {
616
+ private readonly client;
617
+ constructor(client: BaseClient);
618
+ /**
619
+ * Create a new subuser for a user.
620
+ *
621
+ * Returns the user's **entire** subuser list after the operation, not just the
622
+ * newly created subuser. To identify the new entry, compare with the list
623
+ * before creation or look for the matching `id`.
624
+ *
625
+ * @param input - Subuser creation parameters. `uid` and `subuser` are required.
626
+ * `subuser` must be in `uid:name` format (e.g. `"alice:swift"`).
627
+ * @returns Array of **all** subusers belonging to the user after creation.
628
+ * @throws {RGWValidationError} If `uid` or `subuser` is missing, invalid, or not in `uid:name` format.
629
+ * @throws {RGWNotFoundError} If the parent user does not exist.
630
+ *
631
+ * @example
632
+ * ```typescript
633
+ * const subusers = await client.subusers.create({
634
+ * uid: 'alice',
635
+ * subuser: 'alice:swift',
636
+ * access: 'readwrite',
637
+ * keyType: 'swift',
638
+ * generateSecret: true,
639
+ * });
640
+ * console.log(subusers[0].id, subusers[0].permissions);
641
+ * ```
642
+ */
643
+ create(input: CreateSubuserInput): Promise<RGWSubuser[]>;
644
+ /**
645
+ * Modify an existing subuser's properties.
646
+ *
647
+ * @param input - Properties to update. `uid` and `subuser` are required.
648
+ * @returns Array of subusers belonging to the user after modification.
649
+ * @throws {RGWValidationError} If `uid` or `subuser` is missing or invalid.
650
+ * @throws {RGWNotFoundError} If the parent user or subuser does not exist.
651
+ *
652
+ * @example
653
+ * ```typescript
654
+ * const subusers = await client.subusers.modify({
655
+ * uid: 'alice',
656
+ * subuser: 'alice:swift',
657
+ * access: 'full',
658
+ * });
659
+ * ```
660
+ */
661
+ modify(input: ModifySubuserInput): Promise<RGWSubuser[]>;
662
+ /**
663
+ * Remove a subuser from a user. Optionally purge the subuser's keys.
664
+ *
665
+ * @param input - `uid` and `subuser` are required. `purgeKeys` defaults to true.
666
+ * @returns Resolves when the subuser has been removed.
667
+ * @throws {RGWValidationError} If `uid` or `subuser` is missing or invalid.
668
+ * @throws {RGWNotFoundError} If the parent user or subuser does not exist.
669
+ *
670
+ * @example
671
+ * ```typescript
672
+ * // Remove subuser and purge keys
673
+ * await client.subusers.remove({
674
+ * uid: 'alice',
675
+ * subuser: 'alice:swift',
676
+ * });
677
+ *
678
+ * // Remove subuser but keep keys
679
+ * await client.subusers.remove({
680
+ * uid: 'alice',
681
+ * subuser: 'alice:swift',
682
+ * purgeKeys: false,
683
+ * });
684
+ * ```
685
+ */
686
+ remove(input: DeleteSubuserInput): Promise<void>;
687
+ }
688
+
689
+ /** Usage statistics for a bucket storage class. */
690
+ interface RGWBucketUsage {
691
+ size: number;
692
+ sizeActual: number;
693
+ sizeUtilized: number;
694
+ sizeKb: number;
695
+ sizeKbActual: number;
696
+ numObjects: number;
697
+ }
698
+ /** Full RGW bucket object returned by the admin API. */
699
+ interface RGWBucket {
700
+ bucket: string;
701
+ tenant: string;
702
+ explicitTenant: boolean;
703
+ id: string;
704
+ marker: string;
705
+ indexType: string;
706
+ owner: string;
707
+ ver: string;
708
+ masterVer: string;
709
+ mtime: string;
710
+ creationTime: string;
711
+ maxMarker: string;
712
+ usage: {
713
+ rgwMain: RGWBucketUsage;
714
+ rgwMultimeta?: RGWBucketUsage;
715
+ [storageClass: string]: RGWBucketUsage | undefined;
716
+ };
717
+ bucketQuota: RGWQuota;
718
+ }
719
+ /** Input for deleting a bucket. */
720
+ interface DeleteBucketInput {
721
+ /** Bucket name. Required. */
722
+ bucket: string;
723
+ /** If true, permanently deletes all objects in the bucket. Default: false. DESTRUCTIVE. */
724
+ purgeObjects?: boolean;
725
+ }
726
+ /** Input for linking a bucket to a user. */
727
+ interface LinkBucketInput {
728
+ /** Bucket name. Required. */
729
+ bucket: string;
730
+ /** Bucket ID (from getInfo). Required. */
731
+ bucketId: string;
732
+ /** User ID to link the bucket to. Required. */
733
+ uid: string;
734
+ }
735
+ /** Input for unlinking a bucket from a user. */
736
+ interface UnlinkBucketInput {
737
+ /** Bucket name. Required. */
738
+ bucket: string;
739
+ /** User ID to unlink the bucket from. Required. */
740
+ uid: string;
741
+ }
742
+ /** Input for checking/repairing a bucket index. */
743
+ interface CheckBucketIndexInput {
744
+ /** Bucket name. Required. */
745
+ bucket: string;
746
+ /** Whether to check object data consistency. Default: false. */
747
+ checkObjects?: boolean;
748
+ /** Whether to fix any detected issues. Default: false (dry run). */
749
+ fix?: boolean;
750
+ }
751
+ /** Result of a bucket index check. */
752
+ interface CheckBucketIndexResult {
753
+ invalidMultipartEntries: string[];
754
+ checkResult: {
755
+ existingHeader: Record<string, unknown>;
756
+ calculatedHeader: Record<string, unknown>;
757
+ };
758
+ }
759
+
760
+ /**
761
+ * Bucket management module — list, inspect, delete, transfer ownership, and verify/repair bucket indexes.
762
+ *
763
+ * @example
764
+ * ```typescript
765
+ * const allBuckets = await client.buckets.list();
766
+ * const userBuckets = await client.buckets.listByUser('alice');
767
+ * const info = await client.buckets.getInfo('my-bucket');
768
+ * console.log(info.owner, info.usage.rgwMain.numObjects);
769
+ * ```
770
+ */
771
+ declare class BucketsModule {
772
+ private readonly client;
773
+ constructor(client: BaseClient);
774
+ /**
775
+ * List all buckets in the cluster.
776
+ *
777
+ * The RGW `/bucket` endpoint has a default limit of 1000 entries.
778
+ * This method requests up to 100,000 entries to avoid silent truncation
779
+ * on large clusters.
780
+ *
781
+ * For clusters with more than 100k buckets, use the planned `paginate()`
782
+ * method (see v1.6 roadmap).
783
+ *
784
+ * @returns Array of bucket name strings.
785
+ *
786
+ * @example
787
+ * ```typescript
788
+ * const all = await client.buckets.list();
789
+ * console.log(`Cluster has ${all.length} buckets`);
790
+ * ```
791
+ */
792
+ list(): Promise<string[]>;
793
+ /**
794
+ * List buckets owned by a specific user.
795
+ *
796
+ * @param uid - User ID to filter buckets by. Required.
797
+ * @returns Array of bucket name strings owned by the user.
798
+ * @throws {RGWValidationError} If `uid` is missing or invalid.
799
+ *
800
+ * @example
801
+ * ```typescript
802
+ * const userBuckets = await client.buckets.listByUser('alice');
803
+ * console.log(`alice has ${userBuckets.length} buckets`);
804
+ * ```
805
+ */
806
+ listByUser(uid: string): Promise<string[]>;
807
+ /**
808
+ * Get detailed metadata about a bucket.
809
+ *
810
+ * @param bucket - The bucket name to inspect.
811
+ * @returns Full bucket object with owner, usage, quota, and placement info.
812
+ * @throws {RGWValidationError} If `bucket` is empty.
813
+ * @throws {RGWNotFoundError} If the bucket does not exist.
814
+ *
815
+ * @example
816
+ * ```typescript
817
+ * const info = await client.buckets.getInfo('my-bucket');
818
+ * console.log(`Owner: ${info.owner}`);
819
+ * console.log(`Objects: ${info.usage.rgwMain.numObjects}`);
820
+ * console.log(`Size: ${(info.usage.rgwMain.sizeKb / 1024).toFixed(2)} MB`);
821
+ * ```
822
+ */
823
+ getInfo(bucket: string): Promise<RGWBucket>;
824
+ /**
825
+ * Delete a bucket. Optionally purge all objects inside it.
826
+ *
827
+ * @param input - `bucket` is required. Set `purgeObjects: true` to delete all objects.
828
+ * @returns Resolves when the bucket has been deleted.
829
+ * @throws {RGWValidationError} If `bucket` is empty.
830
+ * @throws {RGWNotFoundError} If the bucket does not exist.
831
+ *
832
+ * @example
833
+ * ```typescript
834
+ * // Safe delete (fails if bucket has objects)
835
+ * await client.buckets.delete({ bucket: 'my-bucket' });
836
+ *
837
+ * // Force delete with object purge
838
+ * await client.buckets.delete({ bucket: 'my-bucket', purgeObjects: true });
839
+ * ```
840
+ */
841
+ delete(input: DeleteBucketInput): Promise<void>;
842
+ /**
843
+ * Transfer ownership of a bucket to a different user.
844
+ *
845
+ * @param input - `bucket`, `bucketId`, and `uid` are all required.
846
+ * @returns Resolves when ownership has been transferred.
847
+ * @throws {RGWValidationError} If any required field is missing.
848
+ * @throws {RGWNotFoundError} If the bucket or user does not exist.
849
+ *
850
+ * @example
851
+ * ```typescript
852
+ * const info = await client.buckets.getInfo('my-bucket');
853
+ * await client.buckets.transferOwnership({
854
+ * bucket: 'my-bucket',
855
+ * bucketId: info.id,
856
+ * uid: 'bob',
857
+ * });
858
+ * ```
859
+ */
860
+ transferOwnership(input: LinkBucketInput): Promise<void>;
861
+ /**
862
+ * Remove ownership of a bucket from a user without deleting the bucket.
863
+ *
864
+ * **Warning:** This leaves the bucket in an orphaned state with no owner.
865
+ * The bucket and its objects remain intact but cannot be managed via the
866
+ * S3 API until ownership is reassigned with {@link transferOwnership}.
867
+ *
868
+ * @param input - `bucket` and `uid` are required.
869
+ * @returns Resolves when ownership has been removed.
870
+ * @throws {RGWValidationError} If any required field is missing.
871
+ * @throws {RGWNotFoundError} If the bucket or user does not exist.
872
+ *
873
+ * @example
874
+ * ```typescript
875
+ * await client.buckets.removeOwnership({
876
+ * bucket: 'my-bucket',
877
+ * uid: 'alice',
878
+ * });
879
+ * ```
880
+ */
881
+ removeOwnership(input: UnlinkBucketInput): Promise<void>;
882
+ /**
883
+ * Verify and optionally repair a bucket's index.
884
+ *
885
+ * With `fix: false` (default), this is a safe read-only operation that reports
886
+ * any inconsistencies. Set `fix: true` to actually repair detected issues.
887
+ *
888
+ * @param input - `bucket` is required. `checkObjects` and `fix` are optional.
889
+ * @returns Index check result with invalid entries and header comparison.
890
+ * @throws {RGWValidationError} If `bucket` is empty.
891
+ * @throws {RGWNotFoundError} If the bucket does not exist.
892
+ *
893
+ * @example
894
+ * ```typescript
895
+ * // Dry run — check only
896
+ * const result = await client.buckets.verifyIndex({
897
+ * bucket: 'my-bucket',
898
+ * checkObjects: true,
899
+ * fix: false,
900
+ * });
901
+ * console.log('Invalid entries:', result.invalidMultipartEntries);
902
+ *
903
+ * // Fix detected issues
904
+ * await client.buckets.verifyIndex({
905
+ * bucket: 'my-bucket',
906
+ * fix: true,
907
+ * });
908
+ * ```
909
+ */
910
+ verifyIndex(input: CheckBucketIndexInput): Promise<CheckBucketIndexResult>;
911
+ }
912
+
913
+ /** Input for setting a user-level quota. */
914
+ interface SetUserQuotaInput {
915
+ /** User ID. Required. */
916
+ uid: string;
917
+ /** Maximum storage size in bytes, or a human-readable string like "10G", "500M". -1 for unlimited. */
918
+ maxSize?: number | string;
919
+ /** Maximum number of objects. -1 for unlimited. */
920
+ maxObjects?: number;
921
+ /** Whether the quota is enabled. Default: true when setting a quota. */
922
+ enabled?: boolean;
923
+ }
924
+ /** Input for setting a bucket-level quota. */
925
+ interface SetBucketQuotaInput {
926
+ /** User ID. Required. */
927
+ uid: string;
928
+ /** Maximum storage size in bytes, or a human-readable string like "10G", "500M". -1 for unlimited. */
929
+ maxSize?: number | string;
930
+ /** Maximum number of objects. -1 for unlimited. */
931
+ maxObjects?: number;
932
+ /** Whether the quota is enabled. Default: true when setting a quota. */
933
+ enabled?: boolean;
934
+ }
935
+ /** Rate limit configuration returned by the RGW Admin API. */
936
+ interface RGWRateLimit {
937
+ enabled: boolean;
938
+ /** Maximum read operations per minute per RGW instance. 0 = unlimited. */
939
+ maxReadOps: number;
940
+ /** Maximum write operations per minute per RGW instance. 0 = unlimited. */
941
+ maxWriteOps: number;
942
+ /** Maximum read bytes per minute per RGW instance. 0 = unlimited. */
943
+ maxReadBytes: number;
944
+ /** Maximum write bytes per minute per RGW instance. 0 = unlimited. */
945
+ maxWriteBytes: number;
946
+ }
947
+ /** Input for setting a user-level rate limit. */
948
+ interface SetUserRateLimitInput {
949
+ /** User ID. Required. */
950
+ uid: string;
951
+ /** Max read ops per minute per RGW instance. 0 = unlimited. */
952
+ maxReadOps?: number;
953
+ /** Max write ops per minute per RGW instance. 0 = unlimited. */
954
+ maxWriteOps?: number;
955
+ /** Max read bytes per minute per RGW instance. 0 = unlimited. */
956
+ maxReadBytes?: number;
957
+ /** Max write bytes per minute per RGW instance. 0 = unlimited. */
958
+ maxWriteBytes?: number;
959
+ /** Whether the rate limit is enabled. Default: true. */
960
+ enabled?: boolean;
961
+ }
962
+ /** Input for setting a bucket-level rate limit. */
963
+ interface SetBucketRateLimitInput {
964
+ /** Bucket name. Required. */
965
+ bucket: string;
966
+ /** Max read ops per minute per RGW instance. 0 = unlimited. */
967
+ maxReadOps?: number;
968
+ /** Max write ops per minute per RGW instance. 0 = unlimited. */
969
+ maxWriteOps?: number;
970
+ /** Max read bytes per minute per RGW instance. 0 = unlimited. */
971
+ maxReadBytes?: number;
972
+ /** Max write bytes per minute per RGW instance. 0 = unlimited. */
973
+ maxWriteBytes?: number;
974
+ /** Whether the rate limit is enabled. Default: true. */
975
+ enabled?: boolean;
976
+ }
977
+ /** Input for setting a global rate limit. */
978
+ interface SetGlobalRateLimitInput {
979
+ /** Scope: 'user', 'bucket', or 'anonymous'. Required. */
980
+ scope: 'user' | 'bucket' | 'anonymous';
981
+ /** Max read ops per minute per RGW instance. 0 = unlimited. */
982
+ maxReadOps?: number;
983
+ /** Max write ops per minute per RGW instance. 0 = unlimited. */
984
+ maxWriteOps?: number;
985
+ /** Max read bytes per minute per RGW instance. 0 = unlimited. */
986
+ maxReadBytes?: number;
987
+ /** Max write bytes per minute per RGW instance. 0 = unlimited. */
988
+ maxWriteBytes?: number;
989
+ /** Whether the rate limit is enabled. Default: true. */
990
+ enabled?: boolean;
991
+ }
992
+ /** Global rate limit info returned by the RGW Admin API. */
993
+ interface RGWGlobalRateLimit {
994
+ /** Rate limit for all users (per-user scope). */
995
+ user: RGWRateLimit;
996
+ /** Rate limit for all buckets (per-bucket scope). */
997
+ bucket: RGWRateLimit;
998
+ /** Rate limit for anonymous (unauthenticated) access. */
999
+ anonymous: RGWRateLimit;
1000
+ }
1001
+
1002
+ /**
1003
+ * Quota management module — get, set, enable, and disable user-level and bucket-level quotas.
1004
+ *
1005
+ * @example
1006
+ * ```typescript
1007
+ * // Set a 10GB user quota
1008
+ * await client.quota.setUserQuota({ uid: 'alice', maxSize: '10G', maxObjects: 50000 });
1009
+ *
1010
+ * // Check current quota
1011
+ * const quota = await client.quota.getUserQuota('alice');
1012
+ * console.log(quota.enabled, quota.maxSize);
1013
+ * ```
1014
+ */
1015
+ declare class QuotaModule {
1016
+ private readonly client;
1017
+ constructor(client: BaseClient);
1018
+ /**
1019
+ * Get the user-level quota for a user.
1020
+ *
1021
+ * @param uid - The user ID.
1022
+ * @returns The user's quota configuration.
1023
+ * @throws {RGWValidationError} If `uid` is empty.
1024
+ * @throws {RGWNotFoundError} If the user does not exist.
1025
+ *
1026
+ * @example
1027
+ * ```typescript
1028
+ * const quota = await client.quota.getUserQuota('alice');
1029
+ * console.log('Enabled:', quota.enabled);
1030
+ * console.log('Max size:', quota.maxSize, 'bytes');
1031
+ * console.log('Max objects:', quota.maxObjects);
1032
+ * ```
1033
+ */
1034
+ getUserQuota(uid: string): Promise<RGWQuota>;
1035
+ /**
1036
+ * Set the user-level quota for a user.
1037
+ *
1038
+ * The `maxSize` field accepts either a number (bytes) or a human-readable string
1039
+ * like `"10G"`, `"500M"`, `"1T"`.
1040
+ *
1041
+ * @param input - Quota settings. `uid` is required.
1042
+ * @throws {RGWValidationError} If `uid` is empty, `maxSize` format is invalid, or `maxSize`/`maxObjects` is a negative number other than -1.
1043
+ * @throws {RGWNotFoundError} If the user does not exist.
1044
+ *
1045
+ * @example
1046
+ * ```typescript
1047
+ * await client.quota.setUserQuota({
1048
+ * uid: 'alice',
1049
+ * maxSize: '10G',
1050
+ * maxObjects: 50000,
1051
+ * enabled: true,
1052
+ * });
1053
+ * ```
1054
+ */
1055
+ setUserQuota(input: SetUserQuotaInput): Promise<void>;
1056
+ /**
1057
+ * Enable the user-level quota for a user without changing quota values.
1058
+ *
1059
+ * @param uid - The user ID.
1060
+ * @throws {RGWValidationError} If `uid` is empty.
1061
+ * @throws {RGWNotFoundError} If the user does not exist.
1062
+ *
1063
+ * @example
1064
+ * ```typescript
1065
+ * await client.quota.enableUserQuota('alice');
1066
+ * ```
1067
+ */
1068
+ enableUserQuota(uid: string): Promise<void>;
1069
+ /**
1070
+ * Disable the user-level quota for a user without changing quota values.
1071
+ *
1072
+ * @param uid - The user ID.
1073
+ * @throws {RGWValidationError} If `uid` is empty.
1074
+ * @throws {RGWNotFoundError} If the user does not exist.
1075
+ *
1076
+ * @example
1077
+ * ```typescript
1078
+ * await client.quota.disableUserQuota('alice');
1079
+ * ```
1080
+ */
1081
+ disableUserQuota(uid: string): Promise<void>;
1082
+ /**
1083
+ * Get the bucket-level quota for a user.
1084
+ *
1085
+ * This returns the per-bucket quota applied to all buckets owned by the user,
1086
+ * not a quota for a specific bucket. RGW bucket quotas are configured per-user.
1087
+ *
1088
+ * @param uid - The user ID (bucket owner), not a bucket name.
1089
+ * @throws {RGWValidationError} If `uid` is empty.
1090
+ * @throws {RGWNotFoundError} If the user does not exist.
1091
+ *
1092
+ * @example
1093
+ * ```typescript
1094
+ * const quota = await client.quota.getBucketQuota('alice');
1095
+ * console.log('Bucket quota enabled:', quota.enabled);
1096
+ * ```
1097
+ */
1098
+ getBucketQuota(uid: string): Promise<RGWQuota>;
1099
+ /**
1100
+ * Set the bucket-level quota for a user's buckets.
1101
+ *
1102
+ * The `maxSize` field accepts either a number (bytes) or a human-readable string
1103
+ * like `"1G"`, `"500M"`.
1104
+ *
1105
+ * @param input - Quota settings. `uid` is required.
1106
+ * @throws {RGWValidationError} If `uid` is empty, `maxSize` format is invalid, or `maxSize`/`maxObjects` is a negative number other than -1.
1107
+ * @throws {RGWNotFoundError} If the user does not exist.
1108
+ *
1109
+ * @example
1110
+ * ```typescript
1111
+ * await client.quota.setBucketQuota({
1112
+ * uid: 'alice',
1113
+ * maxSize: '1G',
1114
+ * maxObjects: 10000,
1115
+ * enabled: true,
1116
+ * });
1117
+ * ```
1118
+ */
1119
+ setBucketQuota(input: SetBucketQuotaInput): Promise<void>;
1120
+ /**
1121
+ * Enable the bucket-level quota for a user without changing quota values.
1122
+ *
1123
+ * @param uid - The user ID.
1124
+ * @throws {RGWValidationError} If `uid` is empty.
1125
+ * @throws {RGWNotFoundError} If the user does not exist.
1126
+ *
1127
+ * @example
1128
+ * ```typescript
1129
+ * await client.quota.enableBucketQuota('alice');
1130
+ * ```
1131
+ */
1132
+ enableBucketQuota(uid: string): Promise<void>;
1133
+ /**
1134
+ * Disable the bucket-level quota for a user without changing quota values.
1135
+ *
1136
+ * @param uid - The user ID.
1137
+ * @throws {RGWValidationError} If `uid` is empty.
1138
+ * @throws {RGWNotFoundError} If the user does not exist.
1139
+ *
1140
+ * @example
1141
+ * ```typescript
1142
+ * await client.quota.disableBucketQuota('alice');
1143
+ * ```
1144
+ */
1145
+ disableBucketQuota(uid: string): Promise<void>;
1146
+ }
1147
+
1148
+ /**
1149
+ * Rate limit management module — get, set, and disable rate limits for users, buckets, and globally.
1150
+ *
1151
+ * Rate limits are enforced **per RGW instance**. If you have 3 RGW daemons and want a
1152
+ * cluster-wide limit of 300 ops/min, set `maxReadOps: 100` on each instance.
1153
+ *
1154
+ * Requires Ceph **Pacific (v16)** or later.
1155
+ *
1156
+ * @example
1157
+ * ```typescript
1158
+ * // Throttle alice to 100 read ops/min per RGW
1159
+ * await client.rateLimit.setUserLimit({
1160
+ * uid: 'alice',
1161
+ * maxReadOps: 100,
1162
+ * maxWriteOps: 50,
1163
+ * });
1164
+ *
1165
+ * // Get current rate limit
1166
+ * const limit = await client.rateLimit.getUserLimit('alice');
1167
+ * console.log(limit.enabled, limit.maxReadOps);
1168
+ * ```
1169
+ */
1170
+ declare class RateLimitModule {
1171
+ private readonly client;
1172
+ constructor(client: BaseClient);
1173
+ /**
1174
+ * Get the rate limit configuration for a user.
1175
+ *
1176
+ * @param uid - The user ID.
1177
+ * @returns The user's rate limit configuration.
1178
+ * @throws {RGWValidationError} If `uid` is empty.
1179
+ * @throws {RGWNotFoundError} If the user does not exist.
1180
+ *
1181
+ * @example
1182
+ * ```typescript
1183
+ * const limit = await client.rateLimit.getUserLimit('alice');
1184
+ * console.log('Read ops/min:', limit.maxReadOps);
1185
+ * console.log('Write ops/min:', limit.maxWriteOps);
1186
+ * ```
1187
+ */
1188
+ getUserLimit(uid: string): Promise<RGWRateLimit>;
1189
+ /**
1190
+ * Set the rate limit for a user.
1191
+ *
1192
+ * Values are per RGW instance. Divide by the number of RGW daemons for cluster-wide limits.
1193
+ *
1194
+ * @param input - Rate limit settings. `uid` is required. `enabled` defaults to `true`.
1195
+ * @throws {RGWValidationError} If `uid` is empty or any rate limit value is negative.
1196
+ * @throws {RGWNotFoundError} If the user does not exist.
1197
+ *
1198
+ * @example
1199
+ * ```typescript
1200
+ * await client.rateLimit.setUserLimit({
1201
+ * uid: 'alice',
1202
+ * maxReadOps: 100,
1203
+ * maxWriteOps: 50,
1204
+ * maxWriteBytes: 52428800, // 50MB/min
1205
+ * enabled: true,
1206
+ * });
1207
+ * ```
1208
+ */
1209
+ setUserLimit(input: SetUserRateLimitInput): Promise<void>;
1210
+ /**
1211
+ * Disable the rate limit for a user without changing the configured values.
1212
+ *
1213
+ * @param uid - The user ID.
1214
+ * @throws {RGWValidationError} If `uid` is empty.
1215
+ * @throws {RGWNotFoundError} If the user does not exist.
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * await client.rateLimit.disableUserLimit('alice');
1220
+ * ```
1221
+ */
1222
+ disableUserLimit(uid: string): Promise<void>;
1223
+ /**
1224
+ * Get the rate limit configuration for a bucket.
1225
+ *
1226
+ * @param bucket - The bucket name.
1227
+ * @returns The bucket's rate limit configuration.
1228
+ * @throws {RGWValidationError} If `bucket` is empty.
1229
+ * @throws {RGWNotFoundError} If the bucket does not exist.
1230
+ *
1231
+ * @example
1232
+ * ```typescript
1233
+ * const limit = await client.rateLimit.getBucketLimit('my-bucket');
1234
+ * console.log('Read ops/min:', limit.maxReadOps);
1235
+ * ```
1236
+ */
1237
+ getBucketLimit(bucket: string): Promise<RGWRateLimit>;
1238
+ /**
1239
+ * Set the rate limit for a bucket.
1240
+ *
1241
+ * Values are per RGW instance. Divide by the number of RGW daemons for cluster-wide limits.
1242
+ *
1243
+ * @param input - Rate limit settings. `bucket` is required. `enabled` defaults to `true`.
1244
+ * @throws {RGWValidationError} If `bucket` is empty or any rate limit value is negative.
1245
+ * @throws {RGWNotFoundError} If the bucket does not exist.
1246
+ *
1247
+ * @example
1248
+ * ```typescript
1249
+ * await client.rateLimit.setBucketLimit({
1250
+ * bucket: 'my-bucket',
1251
+ * maxReadOps: 200,
1252
+ * maxWriteOps: 100,
1253
+ * enabled: true,
1254
+ * });
1255
+ * ```
1256
+ */
1257
+ setBucketLimit(input: SetBucketRateLimitInput): Promise<void>;
1258
+ /**
1259
+ * Disable the rate limit for a bucket without changing the configured values.
1260
+ *
1261
+ * @param bucket - The bucket name.
1262
+ * @throws {RGWValidationError} If `bucket` is empty.
1263
+ * @throws {RGWNotFoundError} If the bucket does not exist.
1264
+ *
1265
+ * @example
1266
+ * ```typescript
1267
+ * await client.rateLimit.disableBucketLimit('my-bucket');
1268
+ * ```
1269
+ */
1270
+ disableBucketLimit(bucket: string): Promise<void>;
1271
+ /**
1272
+ * Get the global rate limit configuration for all scopes (user, bucket, anonymous).
1273
+ *
1274
+ * @returns Global rate limits for user, bucket, and anonymous scopes.
1275
+ *
1276
+ * @example
1277
+ * ```typescript
1278
+ * const global = await client.rateLimit.getGlobal();
1279
+ * console.log('Anonymous read limit:', global.anonymous.maxReadOps);
1280
+ * ```
1281
+ */
1282
+ getGlobal(): Promise<RGWGlobalRateLimit>;
1283
+ /**
1284
+ * Set a global rate limit for a specific scope.
1285
+ *
1286
+ * Use `scope: 'anonymous'` to protect public-read buckets from abuse.
1287
+ *
1288
+ * @param input - Rate limit settings. `scope` is required. `enabled` defaults to `true`.
1289
+ * @throws {RGWValidationError} If `scope` is invalid or any rate limit value is negative.
1290
+ *
1291
+ * @example
1292
+ * ```typescript
1293
+ * // Limit anonymous access globally
1294
+ * await client.rateLimit.setGlobal({
1295
+ * scope: 'anonymous',
1296
+ * maxReadOps: 50,
1297
+ * maxWriteOps: 0,
1298
+ * enabled: true,
1299
+ * });
1300
+ * ```
1301
+ */
1302
+ setGlobal(input: SetGlobalRateLimitInput): Promise<void>;
1303
+ }
1304
+
1305
+ interface GetUsageInput {
1306
+ /** Filter by user ID. Omit to retrieve cluster-wide usage for all users. */
1307
+ uid?: string;
1308
+ /** Start of the date range. Accepts ISO date string ("2024-01-01") or Date object. */
1309
+ start?: string | Date;
1310
+ /** End of the date range. Accepts ISO date string ("2024-01-31") or Date object. */
1311
+ end?: string | Date;
1312
+ /** Include per-bucket usage entries in the response. Default: true. */
1313
+ showEntries?: boolean;
1314
+ /** Include per-user summary totals in the response. Default: true. */
1315
+ showSummary?: boolean;
1316
+ }
1317
+ interface TrimUsageInput {
1318
+ /** Trim usage logs only for this user. Omit to trim across all users. */
1319
+ uid?: string;
1320
+ /** Start of the date range to trim. */
1321
+ start?: string | Date;
1322
+ /** End of the date range to trim. */
1323
+ end?: string | Date;
1324
+ /**
1325
+ * Required when `uid` is not provided to prevent accidental cluster-wide log deletion.
1326
+ * Setting this to `true` explicitly acknowledges that all matching logs will be removed.
1327
+ */
1328
+ removeAll?: boolean;
1329
+ }
1330
+ interface RGWUsageCategory {
1331
+ /** Operation category, e.g. "get_obj", "put_obj", "delete_obj", "list_buckets". */
1332
+ category: string;
1333
+ /** Total bytes sent (egress) for this category. */
1334
+ bytesSent: number;
1335
+ /** Total bytes received (ingress) for this category. */
1336
+ bytesReceived: number;
1337
+ /** Total number of operations attempted. */
1338
+ ops: number;
1339
+ /** Total number of operations that succeeded. */
1340
+ successfulOps: number;
1341
+ }
1342
+ interface RGWUsageBucket {
1343
+ bucket: string;
1344
+ time: string;
1345
+ epoch: number;
1346
+ owner: string;
1347
+ categories: RGWUsageCategory[];
1348
+ }
1349
+ interface RGWUsageEntry {
1350
+ /** The user ID this entry belongs to. */
1351
+ user: string;
1352
+ /** Per-bucket breakdown of usage. */
1353
+ buckets: RGWUsageBucket[];
1354
+ }
1355
+ interface RGWUsageSummary {
1356
+ /** The user ID this summary belongs to. */
1357
+ user: string;
1358
+ /** Per-category totals for this user. */
1359
+ categories: RGWUsageCategory[];
1360
+ /** Aggregate totals across all categories for this user. */
1361
+ total: {
1362
+ bytesSent: number;
1363
+ bytesReceived: number;
1364
+ ops: number;
1365
+ successfulOps: number;
1366
+ };
1367
+ }
1368
+ interface RGWUsageReport {
1369
+ /** Detailed per-bucket usage entries (present when showEntries is true). */
1370
+ entries: RGWUsageEntry[];
1371
+ /** Per-user aggregated summaries (present when showSummary is true). */
1372
+ summary: RGWUsageSummary[];
1373
+ }
1374
+
1375
+ /**
1376
+ * Usage & analytics module — query and trim RGW usage logs.
1377
+ *
1378
+ * > **Note:** Usage logging must be enabled in your Ceph config:
1379
+ * > `rgw enable usage log = true`
1380
+ *
1381
+ * @example
1382
+ * ```typescript
1383
+ * // Get usage for a specific user in January 2025
1384
+ * const report = await client.usage.get({
1385
+ * uid: 'alice',
1386
+ * start: '2025-01-01',
1387
+ * end: '2025-01-31',
1388
+ * });
1389
+ *
1390
+ * // Trim all usage logs before a date (cluster-wide)
1391
+ * await client.usage.trim({ end: '2024-12-31', removeAll: true });
1392
+ * ```
1393
+ */
1394
+ declare class UsageModule {
1395
+ private readonly client;
1396
+ constructor(client: BaseClient);
1397
+ /**
1398
+ * Retrieve a usage report for a user or the entire cluster.
1399
+ *
1400
+ * Omit `uid` to get cluster-wide usage across all users.
1401
+ * Omit `start`/`end` to get all available usage data.
1402
+ *
1403
+ * > **Note:** Usage logging must be enabled in `ceph.conf`:
1404
+ * > `rgw enable usage log = true`
1405
+ *
1406
+ * @param input - Optional filters: `uid`, `start`, `end`, `showEntries`, `showSummary`.
1407
+ * @returns A usage report with `entries` (per-bucket detail) and `summary` (per-user totals).
1408
+ * @throws {RGWValidationError} If `uid` is provided but empty/whitespace.
1409
+ * @throws {RGWValidationError} If a date string is not in a recognised format.
1410
+ *
1411
+ * @example
1412
+ * ```typescript
1413
+ * // Cluster-wide usage, all time
1414
+ * const all = await client.usage.get();
1415
+ *
1416
+ * // Single user, date range
1417
+ * const report = await client.usage.get({
1418
+ * uid: 'alice',
1419
+ * start: '2025-01-01',
1420
+ * end: '2025-01-31',
1421
+ * });
1422
+ *
1423
+ * for (const s of report.summary) {
1424
+ * console.log(s.user, 'sent', s.total.bytesSent, 'bytes');
1425
+ * }
1426
+ * ```
1427
+ */
1428
+ get(input?: GetUsageInput): Promise<RGWUsageReport>;
1429
+ /**
1430
+ * Delete (trim) usage log entries matching the given filters.
1431
+ *
1432
+ * **Destructive operation** — deleted log entries cannot be recovered.
1433
+ *
1434
+ * When no `uid` is provided the trim applies cluster-wide. In that case
1435
+ * `removeAll: true` is required to prevent accidental full-cluster log wipes.
1436
+ *
1437
+ * @param input - Trim filters. Omit entirely to trim nothing (use `removeAll: true` explicitly).
1438
+ * @throws {RGWValidationError} If `uid` is provided but empty/whitespace.
1439
+ * @throws {RGWValidationError} If `uid` is omitted but `removeAll` is not `true`.
1440
+ * @throws {RGWValidationError} If a date string is not in a recognised format.
1441
+ *
1442
+ * @example
1443
+ * ```typescript
1444
+ * // Trim a specific user's logs up to end of 2024
1445
+ * await client.usage.trim({ uid: 'alice', end: '2024-12-31' });
1446
+ *
1447
+ * // ⚠️ Trim all logs before 2024 across the entire cluster
1448
+ * await client.usage.trim({ end: '2023-12-31', removeAll: true });
1449
+ * ```
1450
+ */
1451
+ trim(input?: TrimUsageInput): Promise<void>;
1452
+ }
1453
+
1454
+ interface RGWStorageBackend {
1455
+ /** Backend name (e.g. "rados"). */
1456
+ name: string;
1457
+ /** The Ceph cluster FSID (unique identifier for the cluster). */
1458
+ clusterId: string;
1459
+ }
1460
+ interface RGWClusterInfo {
1461
+ info: {
1462
+ /** Storage backends available in this cluster. */
1463
+ storageBackends: RGWStorageBackend[];
1464
+ };
1465
+ }
1466
+
1467
+ /**
1468
+ * Cluster info module — retrieve basic cluster/endpoint information.
1469
+ *
1470
+ * @example
1471
+ * ```typescript
1472
+ * const info = await client.info.get();
1473
+ * console.log('Cluster FSID:', info.info.storageBackends[0].clusterId);
1474
+ * ```
1475
+ */
1476
+ declare class InfoModule {
1477
+ private readonly client;
1478
+ constructor(client: BaseClient);
1479
+ /**
1480
+ * Get basic cluster information including the Ceph cluster FSID.
1481
+ *
1482
+ * Useful for confirming connectivity and identifying which cluster the
1483
+ * client is connected to when managing multiple environments.
1484
+ *
1485
+ * @returns Cluster info containing the cluster ID (FSID).
1486
+ * @throws {RGWAuthError} If the credentials are invalid or lack permission.
1487
+ *
1488
+ * @example
1489
+ * ```typescript
1490
+ * const info = await client.info.get();
1491
+ * console.log('Cluster FSID:', info.info.storageBackends[0].clusterId);
1492
+ * ```
1493
+ */
1494
+ get(): Promise<RGWClusterInfo>;
1495
+ }
1496
+
1497
+ /**
1498
+ * Base error class for all RGW Admin API errors.
1499
+ */
1500
+ declare class RGWError extends Error {
1501
+ readonly statusCode?: number | undefined;
1502
+ readonly code?: string | undefined;
1503
+ readonly uid?: string | undefined;
1504
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined, uid?: string | undefined);
1505
+ }
1506
+ /**
1507
+ * Thrown when a requested resource (user, bucket, key) does not exist.
1508
+ */
1509
+ declare class RGWNotFoundError extends RGWError {
1510
+ constructor(resource: string, id: string);
1511
+ }
1512
+ /**
1513
+ * Thrown when input validation fails before making an HTTP request.
1514
+ */
1515
+ declare class RGWValidationError extends RGWError {
1516
+ constructor(message: string);
1517
+ }
1518
+ /**
1519
+ * Thrown on 403 Access Denied responses.
1520
+ */
1521
+ declare class RGWAuthError extends RGWError {
1522
+ constructor(message: string);
1523
+ }
1524
+ /**
1525
+ * Thrown when a resource already exists (409 Conflict).
1526
+ */
1527
+ declare class RGWConflictError extends RGWError {
1528
+ constructor(resource: string, id: string);
1529
+ }
1530
+
1531
+ /**
1532
+ * AWS Signature V4 signer for RGW Admin API requests.
1533
+ * Implemented without external dependencies using node:crypto.
1534
+ */
1535
+ interface SignedHeaders {
1536
+ [header: string]: string;
1537
+ }
1538
+ interface SignRequest {
1539
+ method: string;
1540
+ url: URL;
1541
+ headers: Record<string, string>;
1542
+ body?: string;
1543
+ accessKey: string;
1544
+ secretKey: string;
1545
+ region: string;
1546
+ }
1547
+ /**
1548
+ * Signs an HTTP request using AWS Signature Version 4.
1549
+ *
1550
+ * @param request - The request details to sign
1551
+ * @param date - Optional date override (used for testing)
1552
+ * @returns Headers that must be added to the request
1553
+ * @internal
1554
+ */
1555
+ declare function signRequest(request: SignRequest, date?: Date): SignedHeaders;
1556
+
1557
+ /**
1558
+ * RadosGW Admin Client — the single entry point for all RGW Admin API operations.
1559
+ *
1560
+ * @example
1561
+ * ```typescript
1562
+ * import { RadosGWAdminClient } from 'radosgw-admin';
1563
+ *
1564
+ * const client = new RadosGWAdminClient({
1565
+ * host: 'http://192.168.1.100',
1566
+ * port: 8080,
1567
+ * accessKey: 'ADMIN_ACCESS_KEY',
1568
+ * secretKey: 'ADMIN_SECRET_KEY',
1569
+ * });
1570
+ *
1571
+ * const user = await client.users.create({
1572
+ * uid: 'alice',
1573
+ * displayName: 'Alice',
1574
+ * });
1575
+ * ```
1576
+ */
1577
+ declare class RadosGWAdminClient {
1578
+ /** @internal */
1579
+ readonly _client: BaseClient;
1580
+ /** User management operations. */
1581
+ readonly users: UsersModule;
1582
+ /** S3/Swift key management operations. */
1583
+ readonly keys: KeysModule;
1584
+ /** Subuser management operations. */
1585
+ readonly subusers: SubusersModule;
1586
+ /** Bucket management operations. */
1587
+ readonly buckets: BucketsModule;
1588
+ /** Quota management operations (user-level and bucket-level). */
1589
+ readonly quota: QuotaModule;
1590
+ /** Rate limit management operations (user, bucket, and global). */
1591
+ readonly rateLimit: RateLimitModule;
1592
+ /** Usage & analytics operations — query and trim RGW usage logs. */
1593
+ readonly usage: UsageModule;
1594
+ /** Cluster info operations. */
1595
+ readonly info: InfoModule;
1596
+ constructor(config: ClientConfig);
1597
+ }
1598
+
1599
+ export { BaseClient, type CheckBucketIndexInput, type CheckBucketIndexResult, type ClientConfig, type CreateKeyInput, type CreateSubuserInput, type CreateUserInput, type DeleteBucketInput, type DeleteKeyInput, type DeleteSubuserInput, type DeleteUserInput, type GetUsageInput, type HttpMethod, type LinkBucketInput, type ModifySubuserInput, type ModifyUserInput, RGWAuthError, type RGWBucket, type RGWBucketUsage, type RGWCap, type RGWClusterInfo, RGWConflictError, RGWError, type RGWGlobalRateLimit, type RGWKey, RGWNotFoundError, type RGWQuota, type RGWRateLimit, type RGWStorageBackend, type RGWSubuser, type RGWSwiftKey, type RGWUsageBucket, type RGWUsageCategory, type RGWUsageEntry, type RGWUsageReport, type RGWUsageSummary, type RGWUser, type RGWUserStatData, type RGWUserWithStats, RGWValidationError, RadosGWAdminClient, type RequestOptions, type SetBucketQuotaInput, type SetBucketRateLimitInput, type SetGlobalRateLimitInput, type SetUserQuotaInput, type SetUserRateLimitInput, type TrimUsageInput, type UnlinkBucketInput, signRequest };