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.
- package/LICENSE +182 -0
- package/README.md +411 -0
- package/dist/index.cjs +1903 -0
- package/dist/index.d.cts +1599 -0
- package/dist/index.d.ts +1599 -0
- package/dist/index.js +1869 -0
- package/package.json +105 -0
package/dist/index.d.cts
ADDED
|
@@ -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 };
|