Skip to content

Commit 29b1bba

Browse files
committed
feat: added firebase module
1 parent a43edc8 commit 29b1bba

File tree

18 files changed

+682
-3
lines changed

18 files changed

+682
-3
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
matrix:
9595
go-version: [1.22.x, 1.x]
9696
platform: [ubuntu-latest]
97-
module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, meilisearch, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb]
97+
module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, firebase, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, meilisearch, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb]
9898
uses: ./.github/workflows/ci-test-go.yml
9999
with:
100100
go-version: ${{ matrix.go-version }}

.vscode/.testcontainers-go.code-workspace

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
"name": "module / etcd",
7070
"path": "../modules/etcd"
7171
},
72+
{
73+
"name": "module / firebase",
74+
"path": "../modules/firebase"
75+
},
7276
{
7377
"name": "module / gcloud",
7478
"path": "../modules/gcloud"
@@ -214,4 +218,4 @@
214218
"path": "../modulegen"
215219
}
216220
]
217-
}
221+
}

docs/modules/firebase.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Firebase
2+
3+
Not available until the next release of testcontainers-go <a href="https://github.com/testcontainers/testcontainers-go"><span class="tc-version">:material-tag: main</span></a>
4+
5+
## Introduction
6+
7+
The Testcontainers module for Firebase.
8+
9+
## Adding this module to your project dependencies
10+
11+
Please run the following command to add the Firebase module to your Go dependencies:
12+
13+
```
14+
go get github.com/testcontainers/testcontainers-go/modules/firebase
15+
```
16+
17+
## Usage example
18+
19+
<!--codeinclude-->
20+
[Creating a Firebase container](../../modules/firebase/examples_test.go) inside_block:runFirebaseContainer
21+
<!--/codeinclude-->
22+
23+
## Module reference
24+
25+
The Firebase module exposes one entrypoint function to create the Firebase container, and this function receives two parameters:
26+
27+
```golang
28+
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*FirebaseContainer, error)
29+
```
30+
31+
- `context.Context`, the Go context.
32+
- `testcontainers.ContainerCustomizer`, a variadic argument for passing options.
33+
34+
### Container Options
35+
36+
When starting the Firebase container, you can pass options in a variadic way to configure it.
37+
38+
#### Image
39+
40+
If you need to set a different Firebase Docker image, you can use `testcontainers.WithImage` with a valid Docker image
41+
for Firebase. E.g. `testcontainers.WithImage("ghcr.io/thoughtgears/docker-firebase-emulator:13.6.0")`.
42+
43+
{% include "../features/common_functional_options.md" %}
44+
45+
### Container Methods
46+
47+
The Firebase container exposes the following methods:

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ nav:
8181
- modules/dynamodb.md
8282
- modules/elasticsearch.md
8383
- modules/etcd.md
84+
- modules/firebase.md
8485
- modules/gcloud.md
8586
- modules/grafana-lgtm.md
8687
- modules/inbucket.md

modules/firebase/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include ../../commons-test.mk
2+
3+
.PHONY: test
4+
test:
5+
$(MAKE) test-firebase

modules/firebase/anchor_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package firebase_test
2+
3+
import (
4+
"path/filepath"
5+
"runtime"
6+
)
7+
8+
// BasePath returns the catalog of the module this function resides in
9+
func BasePath() string {
10+
_, b, _, _ := runtime.Caller(0)
11+
base := filepath.Dir(b)
12+
return base
13+
}

modules/firebase/examples_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package firebase_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"path/filepath"
8+
9+
"github.com/testcontainers/testcontainers-go/modules/firebase"
10+
)
11+
12+
func ExampleRunContainer() {
13+
// runFirebaseContainer {
14+
ctx := context.Background()
15+
16+
firebaseContainer, err := firebase.RunContainer(
17+
ctx,
18+
firebase.WithRoot(filepath.Join(BasePath(), "firebase")),
19+
)
20+
if err != nil {
21+
log.Fatalf("failed to start container: %s", err)
22+
}
23+
24+
// Clean up the container
25+
defer func() {
26+
if err := firebaseContainer.Terminate(ctx); err != nil {
27+
log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic
28+
}
29+
}()
30+
// }
31+
32+
state, err := firebaseContainer.State(ctx)
33+
if err != nil {
34+
log.Fatalf("failed to get container state: %s", err) // nolint:gocritic
35+
}
36+
37+
fmt.Println(state.Running)
38+
39+
// Output:
40+
// true
41+
}

modules/firebase/firebase.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package firebase
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"time"
8+
9+
"github.com/docker/docker/api/types/mount"
10+
11+
"github.com/testcontainers/testcontainers-go"
12+
"github.com/testcontainers/testcontainers-go/wait"
13+
)
14+
15+
// FirebaseContainer represents the Firebase container type used in the module
16+
type FirebaseContainer struct {
17+
testcontainers.Container
18+
}
19+
20+
const defaultImageName = "ghcr.io/u-health/docker-firebase-emulator:13.6.0"
21+
22+
// WithRoot sets the directory which is copied to the destination container as firebase root
23+
func WithRoot(rootPath string) testcontainers.CustomizeRequestOption {
24+
return func(req *testcontainers.GenericContainerRequest) error {
25+
if !strings.HasSuffix(rootPath, "/firebase") {
26+
return fmt.Errorf("root path must end with '/firebase': %s", rootPath)
27+
}
28+
req.Files = append(req.Files, testcontainers.ContainerFile{
29+
HostFilePath: rootPath,
30+
ContainerFilePath: "/srv/firebase",
31+
})
32+
33+
return nil
34+
}
35+
}
36+
37+
// WithData names the data directory in firebase root
38+
func WithData(dataPath string) testcontainers.CustomizeRequestOption {
39+
return func(req *testcontainers.GenericContainerRequest) error {
40+
req.Env["DATA_DIRECTORY"] = dataPath
41+
return nil
42+
}
43+
}
44+
45+
func cache(volumeName string, volumeOptions *mount.VolumeOptions) testcontainers.CustomizeRequestOption {
46+
return func(req *testcontainers.GenericContainerRequest) error {
47+
m := testcontainers.ContainerMount{
48+
Source: testcontainers.DockerVolumeMountSource{
49+
Name: volumeName,
50+
VolumeOptions: volumeOptions,
51+
},
52+
Target: "/root/.cache/firebase",
53+
}
54+
req.Mounts = append(req.Mounts, m)
55+
return nil
56+
}
57+
}
58+
59+
// WithCache enables firebase binary cache based on session (meaningful only when multiple tests are used)
60+
func WithCache() testcontainers.CustomizeRequestOption {
61+
volumeName := fmt.Sprintf("firestore-cache-%s", testcontainers.SessionID())
62+
volumeOptions := &mount.VolumeOptions{
63+
Labels: testcontainers.GenericLabels(),
64+
}
65+
66+
return cache(volumeName, volumeOptions)
67+
}
68+
69+
// RunContainer creates an instance of the Firebase container type
70+
func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*FirebaseContainer, error) {
71+
req := testcontainers.ContainerRequest{
72+
Image: defaultImageName,
73+
ExposedPorts: []string{
74+
UiPort,
75+
HubPort,
76+
LoggingPort,
77+
FunctionsPort,
78+
FirestorePort,
79+
PubsubPort,
80+
DatabasePort,
81+
AuthPort,
82+
StoragePort,
83+
HostingPort,
84+
},
85+
86+
Env: map[string]string{},
87+
WaitingFor: wait.ForAll(
88+
wait.ForHTTP("/").WithPort(UiPort).WithStartupTimeout(3 * time.Minute),
89+
),
90+
}
91+
92+
genericContainerReq := testcontainers.GenericContainerRequest{
93+
ContainerRequest: req,
94+
Started: true,
95+
}
96+
97+
for _, opt := range opts {
98+
if err := opt.Customize(&genericContainerReq); err != nil {
99+
return nil, fmt.Errorf("customize: %w", err)
100+
}
101+
}
102+
103+
container, err := testcontainers.GenericContainer(ctx, genericContainerReq)
104+
if err != nil {
105+
return nil, err
106+
}
107+
108+
return &FirebaseContainer{Container: container}, nil
109+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "test"
4+
}
5+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"emulators": {
3+
"ui": {
4+
"enabled": true,
5+
"port": 4000,
6+
"host": "0.0.0.0"
7+
},
8+
"hub": {
9+
"port": 4400,
10+
"host": "0.0.0.0"
11+
},
12+
"logging": {
13+
"port": 4600,
14+
"host": "0.0.0.0"
15+
},
16+
"firestore": {
17+
"port": 8080,
18+
"host": "0.0.0.0"
19+
},
20+
"auth": {
21+
"port": 9099,
22+
"host": "0.0.0.0"
23+
},
24+
"storage": {
25+
"port": 9199,
26+
"host": "0.0.0.0"
27+
},
28+
"singleProjectMode": true
29+
},
30+
"firestore": {
31+
"rules": "firestore.rules",
32+
"indexes": "firestore.indexes.json"
33+
},
34+
"storage": {
35+
"rules": "storage.rules"
36+
}
37+
}

0 commit comments

Comments
 (0)