@floci/testcontainers 0.1.0 → 0.2.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 +21 -0
- package/README.md +273 -36
- package/dist/FlociContainer.d.ts +67 -3
- package/dist/FlociContainer.d.ts.map +1 -1
- package/dist/FlociContainer.js +191 -14
- package/dist/FlociContainer.js.map +1 -1
- package/dist/config/DuckDbConfig.d.ts +9 -0
- package/dist/config/DuckDbConfig.d.ts.map +1 -0
- package/dist/config/DuckDbConfig.js +18 -0
- package/dist/config/DuckDbConfig.js.map +1 -0
- package/dist/config/StorageConfig.d.ts +14 -0
- package/dist/config/StorageConfig.d.ts.map +1 -0
- package/dist/config/StorageConfig.js +23 -0
- package/dist/config/StorageConfig.js.map +1 -0
- package/dist/config/TlsConfig.d.ts +11 -0
- package/dist/config/TlsConfig.d.ts.map +1 -0
- package/dist/config/TlsConfig.js +26 -0
- package/dist/config/TlsConfig.js.map +1 -0
- package/dist/config/index.d.ts +4 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +19 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/services.d.ts +85 -3
- package/dist/config/services.d.ts.map +1 -1
- package/dist/config/services.js +204 -16
- package/dist/config/services.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/package.json +27 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Floci and its contributors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,17 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/floci-io/.github/main/floci.svg#gh-light-mode-only" alt="Floci" width="500" />
|
|
3
|
+
<img src="https://github.com/user-attachments/assets/edfff8b3-926c-471e-9549-77fb90a21b49#gh-dark-mode-only" alt="Floci" width="500" />
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<strong>Any Cloud. Locally.</strong><br />
|
|
8
|
+
Light, fluffy, and always free: Testcontainers for Node.js<br />
|
|
9
|
+
No account. No auth token. No feature gates.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/@floci/testcontainers"><img src="https://img.shields.io/npm/v/%40floci%2Ftestcontainers?label=npm&color=blue" alt="npm version"></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@floci/testcontainers"><img src="https://img.shields.io/node/v/%40floci%2Ftestcontainers" alt="Node versions"></a>
|
|
15
|
+
<a href="https://github.com/floci-io/testcontainers-floci-node/actions/workflows/ci.yml"><img src="https://github.com/floci-io/testcontainers-floci-node/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
16
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-green" alt="License: MIT"></a>
|
|
17
|
+
<a href="https://github.com/floci-io/testcontainers-floci-node/stargazers"><img src="https://img.shields.io/github/stars/floci-io/testcontainers-floci-node?style=flat" alt="GitHub Stars"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="#quick-start">Quick Start</a> ·
|
|
22
|
+
<a href="#service-configuration">Configuration</a> ·
|
|
23
|
+
<a href="#the-floci-emulators">Emulators</a> ·
|
|
24
|
+
<a href="https://floci.io/floci/testcontainers/nodejs/">Docs</a>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What is this?
|
|
30
|
+
|
|
31
|
+
A Node.js / TypeScript [Testcontainers](https://testcontainers.com/) module for [Floci](https://github.com/floci-io),
|
|
32
|
+
the free, open-source local cloud emulators. `FlociContainer` starts a Floci (AWS) container for your integration
|
|
33
|
+
tests and gives you an endpoint and credentials to point the AWS SDK v3 at, plus a typed, per-service configuration
|
|
34
|
+
API over the emulator's environment variables. No cloud account, no auth token, MIT license.
|
|
35
|
+
|
|
36
|
+
See the [Floci documentation](https://floci.io/floci/services/) for the full list of supported AWS services.
|
|
37
|
+
|
|
38
|
+
### The Floci emulators
|
|
39
|
+
|
|
40
|
+
testcontainers-floci-node is the Node.js member of the [Floci](https://github.com/floci-io) Testcontainers family.
|
|
41
|
+
Floci is named after [floccus](https://en.wikipedia.org/wiki/Cirrocumulus_floccus), the cloud formation that looks
|
|
42
|
+
like popcorn.
|
|
43
|
+
|
|
44
|
+
| Emulator | Cloud | Port | Supported |
|
|
45
|
+
|----------------------------------------------------|-------|:----:|:------------------------------------------------------------------------------:|
|
|
46
|
+
| [floci](https://github.com/floci-io/floci) | AWS | 4566 | ✅ [`@floci/testcontainers`](https://www.npmjs.com/package/@floci/testcontainers) |
|
|
47
|
+
| [floci-az](https://github.com/floci-io/floci-az) | Azure | 4577 | Planned |
|
|
48
|
+
| [floci-gcp](https://github.com/floci-io/floci-gcp) | GCP | 4588 | Planned |
|
|
49
|
+
| [floci-oci](https://github.com/floci-io/floci-oci) | OCI | 4599 | Planned |
|
|
15
50
|
|
|
16
51
|
## Installation
|
|
17
52
|
|
|
@@ -61,7 +96,15 @@ describe('S3', () => {
|
|
|
61
96
|
});
|
|
62
97
|
```
|
|
63
98
|
|
|
64
|
-
|
|
99
|
+
### Jest note
|
|
100
|
+
|
|
101
|
+
Integration tests that use AWS SDK v3 may need Node VM modules enabled when running under Jest:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
NODE_OPTIONS=--experimental-vm-modules npm test
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Sharing a container across tests
|
|
65
108
|
|
|
66
109
|
```ts
|
|
67
110
|
import { FlociContainer, StartedFlociContainer } from '@floci/testcontainers';
|
|
@@ -77,11 +120,46 @@ afterAll(async () => {
|
|
|
77
120
|
});
|
|
78
121
|
```
|
|
79
122
|
|
|
123
|
+
### AWS SDK v3 Example (S3)
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { FlociContainer } from "@floci/testcontainers";
|
|
127
|
+
import { S3Client, CreateBucketCommand, ListBucketsCommand } from "@aws-sdk/client-s3";
|
|
128
|
+
|
|
129
|
+
const floci = await new FlociContainer().start();
|
|
130
|
+
|
|
131
|
+
const client = new S3Client({
|
|
132
|
+
region: "us-east-1",
|
|
133
|
+
endpoint: floci.getEndpoint(),
|
|
134
|
+
credentials: {
|
|
135
|
+
accessKeyId: "test",
|
|
136
|
+
secretAccessKey: "test",
|
|
137
|
+
},
|
|
138
|
+
forcePathStyle: true,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
await client.send(
|
|
142
|
+
new CreateBucketCommand({
|
|
143
|
+
Bucket: "example-bucket",
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const buckets = await client.send(new ListBucketsCommand({}));
|
|
148
|
+
|
|
149
|
+
console.log(buckets.Buckets);
|
|
150
|
+
|
|
151
|
+
await floci.stop();
|
|
152
|
+
```
|
|
153
|
+
|
|
80
154
|
## Service configuration
|
|
81
155
|
|
|
82
|
-
Each
|
|
156
|
+
Each AWS service emulated by Floci can be configured individually using typed config classes passed to a
|
|
157
|
+
`with*Config(...)` method on `FlociContainer`. See the [Floci documentation](https://floci.io/floci/services/) for the
|
|
158
|
+
full list of supported services.
|
|
159
|
+
|
|
160
|
+
### Per-service examples
|
|
83
161
|
|
|
84
|
-
|
|
162
|
+
#### S3
|
|
85
163
|
|
|
86
164
|
```ts
|
|
87
165
|
import { FlociContainer, S3Config } from '@floci/testcontainers';
|
|
@@ -91,7 +169,7 @@ const floci = await new FlociContainer()
|
|
|
91
169
|
.start();
|
|
92
170
|
```
|
|
93
171
|
|
|
94
|
-
|
|
172
|
+
#### SQS
|
|
95
173
|
|
|
96
174
|
```ts
|
|
97
175
|
import { SqsConfig } from '@floci/testcontainers';
|
|
@@ -101,7 +179,7 @@ const floci = await new FlociContainer()
|
|
|
101
179
|
.start();
|
|
102
180
|
```
|
|
103
181
|
|
|
104
|
-
|
|
182
|
+
#### DynamoDB
|
|
105
183
|
|
|
106
184
|
```ts
|
|
107
185
|
import { DynamoDbConfig } from '@floci/testcontainers';
|
|
@@ -111,7 +189,7 @@ const floci = await new FlociContainer()
|
|
|
111
189
|
.start();
|
|
112
190
|
```
|
|
113
191
|
|
|
114
|
-
|
|
192
|
+
#### Lambda
|
|
115
193
|
|
|
116
194
|
```ts
|
|
117
195
|
import { LambdaConfig } from '@floci/testcontainers';
|
|
@@ -127,7 +205,7 @@ const floci = await new FlociContainer()
|
|
|
127
205
|
.start();
|
|
128
206
|
```
|
|
129
207
|
|
|
130
|
-
|
|
208
|
+
#### RDS (PostgreSQL / MySQL / MariaDB)
|
|
131
209
|
|
|
132
210
|
```ts
|
|
133
211
|
import { RdsConfig } from '@floci/testcontainers';
|
|
@@ -137,7 +215,7 @@ const floci = await new FlociContainer()
|
|
|
137
215
|
.start();
|
|
138
216
|
```
|
|
139
217
|
|
|
140
|
-
|
|
218
|
+
#### ElastiCache (Redis / Valkey)
|
|
141
219
|
|
|
142
220
|
```ts
|
|
143
221
|
import { ElastiCacheConfig } from '@floci/testcontainers';
|
|
@@ -147,7 +225,7 @@ const floci = await new FlociContainer()
|
|
|
147
225
|
.start();
|
|
148
226
|
```
|
|
149
227
|
|
|
150
|
-
|
|
228
|
+
#### OpenSearch
|
|
151
229
|
|
|
152
230
|
```ts
|
|
153
231
|
import { OpenSearchConfig } from '@floci/testcontainers';
|
|
@@ -157,7 +235,7 @@ const floci = await new FlociContainer()
|
|
|
157
235
|
.start();
|
|
158
236
|
```
|
|
159
237
|
|
|
160
|
-
|
|
238
|
+
#### MSK (Kafka via Redpanda)
|
|
161
239
|
|
|
162
240
|
```ts
|
|
163
241
|
import { MskConfig } from '@floci/testcontainers';
|
|
@@ -167,6 +245,75 @@ const floci = await new FlociContainer()
|
|
|
167
245
|
.start();
|
|
168
246
|
```
|
|
169
247
|
|
|
248
|
+
### TLS Configuration
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { FlociContainer, TlsConfig } from '@floci/testcontainers';
|
|
252
|
+
|
|
253
|
+
const floci = await new FlociContainer()
|
|
254
|
+
.withTlsConfig(new TlsConfig(true, true))
|
|
255
|
+
.start();
|
|
256
|
+
|
|
257
|
+
const endpoint = floci.getSecureEndpoint(); // https://host:port
|
|
258
|
+
await floci.stop();
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Storage Configuration
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import { FlociContainer, StorageConfig } from '@floci/testcontainers';
|
|
265
|
+
|
|
266
|
+
const floci = await new FlociContainer()
|
|
267
|
+
.withStorageConfig(new StorageConfig('/tmp/floci-data', true))
|
|
268
|
+
.start();
|
|
269
|
+
|
|
270
|
+
await floci.stop();
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Docker Socket
|
|
274
|
+
|
|
275
|
+
By default, the host Docker socket is mounted read-write at `/var/run/docker.sock` for container-backed services. Tests using only in-process services can omit this mount:
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
const floci = await new FlociContainer().withoutDockerSocket().start();
|
|
279
|
+
await floci.stop();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
For a rootless Docker daemon, pass its host socket path. It is still mounted at `/var/run/docker.sock` inside Floci:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const floci = await new FlociContainer()
|
|
286
|
+
.withDockerSocket(`${process.env.XDG_RUNTIME_DIR}/docker.sock`)
|
|
287
|
+
.start();
|
|
288
|
+
await floci.stop();
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`withDockerSocket()` also restores the default mount after `withoutDockerSocket()`.
|
|
292
|
+
|
|
293
|
+
### DuckDB Configuration
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
import { FlociContainer, DuckDbConfig } from '@floci/testcontainers';
|
|
297
|
+
|
|
298
|
+
const floci = await new FlociContainer()
|
|
299
|
+
.withDuckDbConfig(new DuckDbConfig('floci/floci-duck:latest'))
|
|
300
|
+
.start();
|
|
301
|
+
|
|
302
|
+
await floci.stop();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Log Level
|
|
306
|
+
|
|
307
|
+
```ts
|
|
308
|
+
import { FlociContainer } from '@floci/testcontainers';
|
|
309
|
+
|
|
310
|
+
const floci = await new FlociContainer()
|
|
311
|
+
.withLogLevel('DEBUG')
|
|
312
|
+
.start();
|
|
313
|
+
|
|
314
|
+
await floci.stop();
|
|
315
|
+
```
|
|
316
|
+
|
|
170
317
|
### All available config classes
|
|
171
318
|
|
|
172
319
|
| Config class | AWS service |
|
|
@@ -177,13 +324,19 @@ const floci = await new FlociContainer()
|
|
|
177
324
|
| `AppConfigConfig` | AppConfig |
|
|
178
325
|
| `AppConfigDataConfig` | AppConfig Data |
|
|
179
326
|
| `AthenaConfig` | Athena |
|
|
327
|
+
| `BackupConfig` | AWS Backup |
|
|
328
|
+
| `BcmDataExportsConfig` | BCM Data Exports |
|
|
180
329
|
| `BedrockRuntimeConfig` | Bedrock Runtime |
|
|
181
330
|
| `CloudFormationConfig` | CloudFormation |
|
|
331
|
+
| `CloudFrontConfig` | CloudFront |
|
|
182
332
|
| `CloudWatchLogsConfig` | CloudWatch Logs |
|
|
183
333
|
| `CloudWatchMetricsConfig` | CloudWatch Metrics |
|
|
184
334
|
| `CodeBuildConfig` | CodeBuild |
|
|
185
335
|
| `CodeDeployConfig` | CodeDeploy |
|
|
186
336
|
| `CognitoConfig` | Cognito |
|
|
337
|
+
| `ConfigServiceConfig` | AWS Config |
|
|
338
|
+
| `CostExplorerConfig` | Cost Explorer |
|
|
339
|
+
| `CurConfig` | Cost and Usage Reports |
|
|
187
340
|
| `DynamoDbConfig` | DynamoDB |
|
|
188
341
|
| `Ec2Config` | EC2 |
|
|
189
342
|
| `EcrConfig` | ECR |
|
|
@@ -199,10 +352,13 @@ const floci = await new FlociContainer()
|
|
|
199
352
|
| `KmsConfig` | KMS |
|
|
200
353
|
| `LambdaConfig` | Lambda |
|
|
201
354
|
| `MskConfig` | MSK (Kafka) |
|
|
355
|
+
| `NeptuneConfig` | Neptune |
|
|
202
356
|
| `OpenSearchConfig` | OpenSearch |
|
|
203
357
|
| `PipesConfig` | EventBridge Pipes |
|
|
358
|
+
| `PricingConfig` | AWS Pricing |
|
|
204
359
|
| `RdsConfig` | RDS |
|
|
205
360
|
| `ResourceGroupsTaggingConfig` | Resource Groups Tagging |
|
|
361
|
+
| `Route53Config` | Route 53 |
|
|
206
362
|
| `S3Config` | S3 |
|
|
207
363
|
| `SchedulerConfig` | EventBridge Scheduler |
|
|
208
364
|
| `SecretsManagerConfig` | Secrets Manager |
|
|
@@ -212,11 +368,15 @@ const floci = await new FlociContainer()
|
|
|
212
368
|
| `SqsConfig` | SQS |
|
|
213
369
|
| `SsmConfig` | SSM Parameter Store |
|
|
214
370
|
| `StepFunctionsConfig` | Step Functions |
|
|
371
|
+
| `TextractConfig` | Textract |
|
|
372
|
+
| `TransferFamilyConfig` | Transfer Family |
|
|
215
373
|
|
|
216
374
|
## Container options
|
|
217
375
|
|
|
376
|
+
By default, only the Floci gateway port (4566) is published to the host. Extra service ports are published only when their service configuration is explicitly supplied, or when `withExposedPort(port)` is called. Replacing a service configuration updates its published port range; disabling the service removes that range. This avoids publishing hundreds of unused proxy ports for tests that only use the gateway.
|
|
377
|
+
|
|
218
378
|
```ts
|
|
219
|
-
const floci = await new FlociContainer('floci/floci:
|
|
379
|
+
const floci = await new FlociContainer('floci/floci:x.y.z') // pin a specific tag
|
|
220
380
|
.withRegion('eu-west-1')
|
|
221
381
|
.withAccountId('111122223333')
|
|
222
382
|
.withAvailabilityZone('eu-west-1a')
|
|
@@ -235,12 +395,59 @@ const floci = await new FlociContainer('floci/floci:latest') // pin a specific
|
|
|
235
395
|
| `getAccountId()` | AWS account ID |
|
|
236
396
|
| `getMappedPort(port)` | Host port mapped from the given container port |
|
|
237
397
|
|
|
238
|
-
|
|
398
|
+
### Troubleshooting
|
|
239
399
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
400
|
+
#### Docker not running
|
|
401
|
+
|
|
402
|
+
**Symptom:** `Cannot connect to the Docker daemon` or container fails to start.
|
|
403
|
+
|
|
404
|
+
**Cause:** The Docker daemon is not running or the current user lacks permissions.
|
|
405
|
+
|
|
406
|
+
**Resolution:**
|
|
407
|
+
1. Start Docker Desktop or the Docker daemon (`sudo systemctl start docker`)
|
|
408
|
+
2. Verify with `docker info`
|
|
409
|
+
3. Ensure your user is in the `docker` group (`sudo usermod -aG docker $USER`)
|
|
410
|
+
|
|
411
|
+
#### Port conflicts
|
|
412
|
+
|
|
413
|
+
**Symptom:** `Bind for 0.0.0.0:<port> failed: port is already allocated`
|
|
414
|
+
|
|
415
|
+
**Cause:** Another process or container is using the same port.
|
|
416
|
+
|
|
417
|
+
**Resolution:**
|
|
418
|
+
1. Identify the conflicting process: `lsof -i :<port>` or `docker ps`
|
|
419
|
+
2. Stop the conflicting process or container
|
|
420
|
+
3. Alternatively, let Testcontainers use random port mapping (the default behavior)
|
|
421
|
+
|
|
422
|
+
#### Timeout errors
|
|
423
|
+
|
|
424
|
+
**Symptom:** `Timeout waiting for container to be ready` or test timeout exceeded.
|
|
425
|
+
|
|
426
|
+
**Cause:** The Floci container takes longer to start than the configured timeout.
|
|
427
|
+
|
|
428
|
+
**Resolution:**
|
|
429
|
+
1. Increase the Jest test timeout: `jest.setTimeout(120_000)`
|
|
430
|
+
2. Ensure Docker has sufficient resources (CPU/memory)
|
|
431
|
+
3. Check container logs for startup errors: `docker logs <container-id>`
|
|
432
|
+
4. Use `withLogLevel('DEBUG')` to get more verbose container output
|
|
433
|
+
|
|
434
|
+
## Docker image tags
|
|
435
|
+
|
|
436
|
+
By default `FlociContainer` runs the floating `latest` tag of the emulator image (`floci/floci:latest`), so you always
|
|
437
|
+
test against the current emulator. Pass an image name to the constructor to pin a release or follow `main`:
|
|
438
|
+
|
|
439
|
+
```ts
|
|
440
|
+
new FlociContainer('floci/floci:x.y.z'); // a specific release
|
|
441
|
+
new FlociContainer('floci/floci:nightly'); // built from main every night
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
| Tag | Description |
|
|
445
|
+
|-----------------------|-------------------------------------|
|
|
446
|
+
| `floci/floci:latest` | Latest release, native image (default, recommended) |
|
|
447
|
+
| `floci/floci:x.y.z` | Pinned release (native) |
|
|
448
|
+
| `floci/floci:nightly` | Built from `main` every night |
|
|
449
|
+
|
|
450
|
+
Every emulator publishes `latest`, `x.y.z` and `nightly` tags.
|
|
244
451
|
|
|
245
452
|
## Requirements
|
|
246
453
|
|
|
@@ -248,13 +455,43 @@ const floci = await new FlociContainer('floci/floci:latest') // pin a specific
|
|
|
248
455
|
- Docker (running locally or in CI)
|
|
249
456
|
- `testcontainers >= 10.0.0`
|
|
250
457
|
|
|
251
|
-
##
|
|
458
|
+
## Building and testing
|
|
252
459
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
-
|
|
256
|
-
|
|
460
|
+
```bash
|
|
461
|
+
npm ci # install dependencies
|
|
462
|
+
npm run typecheck # type-check (the lint gate CI enforces)
|
|
463
|
+
npm test # all tests, unit and integration
|
|
464
|
+
npm run test:unit # unit tests only, no Docker required
|
|
465
|
+
npm run test:integration # integration tests, Docker must be running
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the project layout, the branching model, and how to add a service.
|
|
469
|
+
|
|
470
|
+
## Other languages
|
|
471
|
+
|
|
472
|
+
| Language | Repository |
|
|
473
|
+
|---|---|
|
|
474
|
+
| Java | [testcontainers-floci](https://github.com/floci-io/testcontainers-floci) |
|
|
475
|
+
| Node.js / TypeScript | **testcontainers-floci-node** (this repo) |
|
|
476
|
+
| Python | [testcontainers-floci-python](https://github.com/floci-io/testcontainers-floci-python) |
|
|
477
|
+
| Go | [testcontainers-floci-go](https://github.com/floci-io/testcontainers-floci-go) |
|
|
478
|
+
| .NET | [testcontainers-floci-dotnet](https://github.com/floci-io/testcontainers-floci-dotnet) |
|
|
479
|
+
|
|
480
|
+
## Community
|
|
481
|
+
|
|
482
|
+
- 💬 [Slack](https://join.slack.com/t/floci/shared_invite/zt-3tjn02s3q-A00kEjJ1cZxsg_imTfy6Cw): quick questions and community chat
|
|
483
|
+
- 🗣️ [GitHub Discussions](https://github.com/orgs/floci-io/discussions): ideas, design tradeoffs, and proposals
|
|
484
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) · [SECURITY.md](SECURITY.md) · [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) · [MAINTAINERS.md](MAINTAINERS.md)
|
|
257
485
|
|
|
258
486
|
## License
|
|
259
487
|
|
|
260
|
-
MIT
|
|
488
|
+
MIT. See [LICENSE](LICENSE).
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
<div align="center">
|
|
493
|
+
|
|
494
|
+
Floci™ is a trademark of Hector Ventura. Code is MIT-licensed; see
|
|
495
|
+
[TRADEMARK.md](https://github.com/floci-io/.github/blob/main/TRADEMARK.md) for name and logo use.
|
|
496
|
+
|
|
497
|
+
</div>
|
package/dist/FlociContainer.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { StartedTestContainer } from 'testcontainers';
|
|
2
|
-
import type { StartedNetwork } from 'testcontainers';
|
|
3
|
-
import { AcmConfig, ApiGatewayConfig, ApiGatewayV2Config, AppConfigConfig, AppConfigDataConfig, AthenaConfig, BedrockRuntimeConfig, CloudFormationConfig, CloudWatchLogsConfig, CloudWatchMetricsConfig, CodeBuildConfig, CodeDeployConfig, CognitoConfig, DynamoDbConfig, Ec2Config, EcrConfig, EcsConfig, EksConfig, ElastiCacheConfig, ElbV2Config, EventBridgeConfig, FirehoseConfig, GlueConfig, IamConfig, KinesisConfig, KmsConfig, LambdaConfig, MskConfig, OpenSearchConfig, PipesConfig, RdsConfig, ResourceGroupsTaggingConfig, S3Config, SchedulerConfig, SecretsManagerConfig, SesConfig, SesV2Config, SnsConfig, SqsConfig, SsmConfig, StepFunctionsConfig } from './config/services';
|
|
2
|
+
import type { StartedNetwork, ExecResult } from 'testcontainers';
|
|
3
|
+
import { AcmConfig, ApiGatewayConfig, ApiGatewayV2Config, AppConfigConfig, AppConfigDataConfig, AthenaConfig, BackupConfig, BcmDataExportsConfig, BedrockRuntimeConfig, CloudFormationConfig, CloudFrontConfig, CloudWatchLogsConfig, CloudWatchMetricsConfig, CodeBuildConfig, CodeDeployConfig, CognitoConfig, ConfigServiceConfig, CostExplorerConfig, CurConfig, DynamoDbConfig, Ec2Config, EcrConfig, EcsConfig, EksConfig, ElastiCacheConfig, ElbV2Config, EventBridgeConfig, FirehoseConfig, GlueConfig, IamConfig, KinesisConfig, KmsConfig, LambdaConfig, MskConfig, NeptuneConfig, OpenSearchConfig, PipesConfig, PricingConfig, RdsConfig, ResourceGroupsTaggingConfig, Route53Config, S3Config, SchedulerConfig, SecretsManagerConfig, SesConfig, SesV2Config, SnsConfig, SqsConfig, SsmConfig, StepFunctionsConfig, TextractConfig, TransferFamilyConfig } from './config/services';
|
|
4
|
+
import { TlsConfig } from './config/TlsConfig';
|
|
5
|
+
import { StorageConfig } from './config/StorageConfig';
|
|
6
|
+
import { DuckDbConfig } from './config/DuckDbConfig';
|
|
7
|
+
/**
|
|
8
|
+
* Valid log levels for the Floci container.
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
4
11
|
/**
|
|
5
12
|
* Testcontainers module for Floci — a free, open-source local AWS emulator.
|
|
6
13
|
*
|
|
@@ -23,11 +30,15 @@ export declare class FlociContainer {
|
|
|
23
30
|
static readonly DEFAULT_ACCOUNT_ID = "000000000000";
|
|
24
31
|
static readonly DEFAULT_ACCESS_KEY = "test";
|
|
25
32
|
static readonly DEFAULT_SECRET_KEY = "test";
|
|
26
|
-
static readonly STARTUP_TIMEOUT_MS =
|
|
33
|
+
static readonly STARTUP_TIMEOUT_MS = 120000;
|
|
27
34
|
private readonly image;
|
|
28
35
|
private readonly envVars;
|
|
29
36
|
private readonly exposedPorts;
|
|
37
|
+
private readonly manualExposedPorts;
|
|
38
|
+
private readonly configuredPortServices;
|
|
30
39
|
private dedicatedNetworkName?;
|
|
40
|
+
private logLevel;
|
|
41
|
+
private dockerSocketPath?;
|
|
31
42
|
private acmConfig;
|
|
32
43
|
private apiGatewayConfig;
|
|
33
44
|
private apiGatewayV2Config;
|
|
@@ -69,13 +80,31 @@ export declare class FlociContainer {
|
|
|
69
80
|
private sqsConfig;
|
|
70
81
|
private ssmConfig;
|
|
71
82
|
private stepFunctionsConfig;
|
|
83
|
+
private cloudFrontConfig;
|
|
84
|
+
private configServiceConfig;
|
|
85
|
+
private backupConfig;
|
|
86
|
+
private transferFamilyConfig;
|
|
87
|
+
private route53Config;
|
|
88
|
+
private textractConfig;
|
|
89
|
+
private pricingConfig;
|
|
90
|
+
private neptuneConfig;
|
|
91
|
+
private costExplorerConfig;
|
|
92
|
+
private curConfig;
|
|
93
|
+
private bcmDataExportsConfig;
|
|
94
|
+
private tlsConfig;
|
|
95
|
+
private storageConfig?;
|
|
96
|
+
private duckDbConfig;
|
|
72
97
|
constructor(image?: string);
|
|
73
98
|
withEnv(key: string, value: string): this;
|
|
74
99
|
withExposedPort(port: number): this;
|
|
100
|
+
withDockerSocket(path?: string): this;
|
|
101
|
+
withoutDockerSocket(): this;
|
|
75
102
|
withRegion(region: string): this;
|
|
76
103
|
withAccountId(accountId: string): this;
|
|
77
104
|
withAvailabilityZone(zone: string): this;
|
|
78
105
|
withDedicatedNetwork(): this;
|
|
106
|
+
withLogLevel(level: LogLevel): this;
|
|
107
|
+
getLogLevel(): LogLevel;
|
|
79
108
|
withAcmConfig(config: AcmConfig): this;
|
|
80
109
|
getAcmConfig(): AcmConfig;
|
|
81
110
|
withApiGatewayConfig(config: ApiGatewayConfig): this;
|
|
@@ -158,10 +187,39 @@ export declare class FlociContainer {
|
|
|
158
187
|
getSsmConfig(): SsmConfig;
|
|
159
188
|
withStepFunctionsConfig(config: StepFunctionsConfig): this;
|
|
160
189
|
getStepFunctionsConfig(): StepFunctionsConfig;
|
|
190
|
+
withCloudFrontConfig(config: CloudFrontConfig): this;
|
|
191
|
+
getCloudFrontConfig(): CloudFrontConfig;
|
|
192
|
+
withConfigServiceConfig(config: ConfigServiceConfig): this;
|
|
193
|
+
getConfigServiceConfig(): ConfigServiceConfig;
|
|
194
|
+
withBackupConfig(config: BackupConfig): this;
|
|
195
|
+
getBackupConfig(): BackupConfig;
|
|
196
|
+
withTransferFamilyConfig(config: TransferFamilyConfig): this;
|
|
197
|
+
getTransferFamilyConfig(): TransferFamilyConfig;
|
|
198
|
+
withRoute53Config(config: Route53Config): this;
|
|
199
|
+
getRoute53Config(): Route53Config;
|
|
200
|
+
withTextractConfig(config: TextractConfig): this;
|
|
201
|
+
getTextractConfig(): TextractConfig;
|
|
202
|
+
withPricingConfig(config: PricingConfig): this;
|
|
203
|
+
getPricingConfig(): PricingConfig;
|
|
204
|
+
withNeptuneConfig(config: NeptuneConfig): this;
|
|
205
|
+
getNeptuneConfig(): NeptuneConfig;
|
|
206
|
+
withCostExplorerConfig(config: CostExplorerConfig): this;
|
|
207
|
+
getCostExplorerConfig(): CostExplorerConfig;
|
|
208
|
+
withCurConfig(config: CurConfig): this;
|
|
209
|
+
getCurConfig(): CurConfig;
|
|
210
|
+
withBcmDataExportsConfig(config: BcmDataExportsConfig): this;
|
|
211
|
+
getBcmDataExportsConfig(): BcmDataExportsConfig;
|
|
212
|
+
withTlsConfig(config: TlsConfig): this;
|
|
213
|
+
getTlsConfig(): TlsConfig;
|
|
214
|
+
withStorageConfig(config: StorageConfig): this;
|
|
215
|
+
getStorageConfig(): StorageConfig | undefined;
|
|
216
|
+
withDuckDbConfig(config: DuckDbConfig): this;
|
|
217
|
+
getDuckDbConfig(): DuckDbConfig;
|
|
161
218
|
getDedicatedNetworkName(): string | undefined;
|
|
162
219
|
start(): Promise<StartedFlociContainer>;
|
|
163
220
|
private applyAllConfigs;
|
|
164
221
|
private refreshExposedPorts;
|
|
222
|
+
private updatePortConfig;
|
|
165
223
|
}
|
|
166
224
|
export declare class StartedFlociContainer {
|
|
167
225
|
private readonly container;
|
|
@@ -170,14 +228,19 @@ export declare class StartedFlociContainer {
|
|
|
170
228
|
private readonly accountId;
|
|
171
229
|
private readonly _dedicatedNetworkName?;
|
|
172
230
|
private readonly network?;
|
|
231
|
+
private readonly tlsEnabled;
|
|
232
|
+
private readonly hostPersistentPath?;
|
|
173
233
|
constructor(container: StartedTestContainer, opts: {
|
|
174
234
|
region: string;
|
|
175
235
|
availabilityZone: string;
|
|
176
236
|
accountId: string;
|
|
177
237
|
dedicatedNetworkName?: string;
|
|
178
238
|
network?: StartedNetwork;
|
|
239
|
+
tlsEnabled: boolean;
|
|
240
|
+
hostPersistentPath?: string;
|
|
179
241
|
});
|
|
180
242
|
getEndpoint(): string;
|
|
243
|
+
getSecureEndpoint(): string;
|
|
181
244
|
getRegion(): string;
|
|
182
245
|
getAccessKey(): string;
|
|
183
246
|
getSecretKey(): string;
|
|
@@ -185,6 +248,7 @@ export declare class StartedFlociContainer {
|
|
|
185
248
|
getAvailabilityZone(): string;
|
|
186
249
|
getDedicatedNetworkName(): string | undefined;
|
|
187
250
|
getMappedPort(port: number): number;
|
|
251
|
+
exec(command: string[]): Promise<ExecResult>;
|
|
188
252
|
stop(): Promise<void>;
|
|
189
253
|
}
|
|
190
254
|
//# sourceMappingURL=FlociContainer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlociContainer.d.ts","sourceRoot":"","sources":["../src/FlociContainer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FlociContainer.d.ts","sourceRoot":"","sources":["../src/FlociContainer.ts"],"names":[],"mappings":"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"}
|