Skip to content

Commit

Permalink
Merge branch 'main' into feature/firebase-realtime-database
Browse files Browse the repository at this point in the history
# Conflicts:
#	firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java
  • Loading branch information
jfbenckhuijsen committed Jan 17, 2025
2 parents 54a60d5 + 08eaf76 commit 0929a96
Show file tree
Hide file tree
Showing 21 changed files with 341 additions and 42 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@
"contributions": [
"code"
]
},
{
"login": "xperjon",
"name": "Jon-Erik Liw",
"avatar_url": "https://avatars.githubusercontent.com/u/965777?v=4",
"profile": "https://github.com/xperjon",
"contributions": [
"doc"
]
}
],
"contributorsPerLine": 7,
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/quarkus-snapshot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ jobs:
if: github.actor == 'quarkusbot' || github.actor == 'quarkiversebot' || github.actor == 'loicmathieu'

steps:
- name: Install yq
run: sudo add-apt-repository ppa:rmescandon/yq && sudo apt update && sudo apt install yq -y

- name: Set up Java
uses: actions/setup-java@v1
with:
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Quarkiverse - Quarkus Google Cloud Services
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-23-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
[![version](https://img.shields.io/maven-central/v/io.quarkiverse.googlecloudservices/quarkus-google-cloud-services-bom)](https://repo1.maven.org/maven2/io/quarkiverse/googlecloudservices/)
[![Build](https://github.com/quarkiverse/quarkus-google-cloud-services/workflows/Build/badge.svg)](https://github.com/quarkiverse/quarkus-google-cloud-services/actions?query=workflow%3ABuild)
Expand Down Expand Up @@ -71,6 +71,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wabrit"><img src="https://avatars.githubusercontent.com/u/4264910?v=4?s=100" width="100px;" alt="wabrit"/><br /><sub><b>wabrit</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-google-cloud-services/commits?author=wabrit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xperjon"><img src="https://avatars.githubusercontent.com/u/965777?v=4?s=100" width="100px;" alt="Jon-Erik Liw"/><br /><sub><b>Jon-Erik Liw</b></sub></a><br /><a href="https://github.com/quarkiverse/quarkus-google-cloud-services/commits?author=xperjon" title="Documentation">📖</a></td>
</tr>
</tbody>
</table>
Expand Down
2 changes: 1 addition & 1 deletion bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<google-cloud-sdk.version>26.50.0</google-cloud-sdk.version>
<firebase-admin-sdk.version>9.4.2</firebase-admin-sdk.version>
<firebase-admin-sdk.version>9.4.3</firebase-admin-sdk.version>

<!-- Dependency convergence issues -->
<opencensus.version>0.31.1</opencensus.version><!-- mess in google-pubsub and grpc deps; should be rather stable as OpenCensus has been sunsetted already - see https://github.com/GoogleCloudPlatform/cloud-opensource-java/issues/862 -->
Expand Down
4 changes: 2 additions & 2 deletions docs/modules/ROOT/pages/firebase-admin.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public class FirebaseAuthResourceTest {
This extension also supports Firebase Authentication, allowing you to secure your endpoints using Firebase's authentication mechanisms.
This section describes how to use Firebase Authentication in your Quarkus application.

Remember that you need to enable the Firebase Authentication service in your Firebase project. `quarkus.google.cloud.firebase.auth.enable` must be set to `true` in your application configuration.
Remember that you need to enable the Firebase Authentication service in your Firebase project. `quarkus.google.cloud.firebase.auth.enabled` must be set to `true` in your application configuration.

=== Configuration

Expand Down Expand Up @@ -122,4 +122,4 @@ public class FirebaseAppResource {

== Configuration Reference

include::./includes/quarkus-google-cloud-firebase-admin.adoc[]
include::./includes/quarkus-google-cloud-firebase-admin.adoc[]
32 changes: 31 additions & 1 deletion docs/modules/ROOT/pages/firebase-devservices.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,43 @@ If emulators are configured via the configuration options, a `firebase.json` fil
* Each of the emulators must be exposed on `0.0.0.0` as host as described https://firebase.google.com/docs/emulator-suite/use_hosting#emulators-no-local-host[here]. If this is not done, the Emulators will not be reachable from the Docker host.
* Emulators need to be configured to use the default ports. Customizing the ports on which they run is currently not supported (this might change in a future version).

== Details on specific Devservices

The following sections provide documentation in interaction with specific emulators.

=== Hosting emulator

If you use the hosting emulator, where Quarkus is the backend, you will need to include a CORS configuration, as REST
requests will originate from another Origin (host). See the https://quarkus.io/guides/security-cors[Quarkus CORS]
documentation for more info.

A simple setup would be
[source,properties]
----
"%dev".quarkus.http.cors=true
"%dev".quarkus.http.cors.origins: /.*/
----

Note that a redirect from the hosting emulator to the Quarkus instance is currently not supported by the emulator.

=== Auth emulator

You can use the features provided by Mircoprofile JWT (e.g. injecting a `@Claim` value) by including the smallrye-jwt
extension and disabling smallrye-jwt using the following property. This will prevent SmallRye JWT from handling the JWT
validation (leaving that to the Firebase Auth module and the Auth emulator), but using the provided JWT to allow injecting
of these beans.

[source,properties]
----
quarkus.smallrye-jwt.enabled=false
----

== Interaction with other extensions

The following extensions support Dev Services which conflicts with the Dev Services exposed by the Firebase Emulators.

* Firestore
* PubSub
* TODO: Verify Storage

When including this module, these Dev Services will automatically be disabled, as the Firebase emulator should feature wise be on-par or more extensive than the individual emulators.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,23 @@ endif::add-copy-button-to-env-var[]
a|`import-only`, `export-only`, `import-export`
|

a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments[`quarkus.google.cloud.devservices.firebase.emulator.cli.experiments`]##

[.description]
--
Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable command line option).


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++`
endif::add-copy-button-to-env-var[]
--
|list of string
|

a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug[`quarkus.google.cloud.devservices.firebase.emulator.cli.debug`]##

[.description]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,23 @@ endif::add-copy-button-to-env-var[]
a|`import-only`, `export-only`, `import-export`
|

a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-experiments[`quarkus.google.cloud.devservices.firebase.emulator.cli.experiments`]##

[.description]
--
Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable command line option).


ifdef::add-copy-button-to-env-var[]
Environment variable: env_var_with_copy_button:+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++[]
endif::add-copy-button-to-env-var[]
ifndef::add-copy-button-to-env-var[]
Environment variable: `+++QUARKUS_GOOGLE_CLOUD_DEVSERVICES_FIREBASE_EMULATOR_CLI_EXPERIMENTS+++`
endif::add-copy-button-to-env-var[]
--
|list of string
|

a|icon:lock[title=Fixed at build time] [[quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug]] [.property-path]##link:#quarkus-google-cloud-firebase-devservices_quarkus-google-cloud-devservices-firebase-emulator-cli-debug[`quarkus.google.cloud.devservices.firebase.emulator.cli.debug`]##

[.description]
Expand Down
22 changes: 22 additions & 0 deletions docs/modules/ROOT/pages/pubsub.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,28 @@ public class PubSubResource {
}
----

== AdminClient beans

If you need to perform admin actions on PubSub, you can inject the `com.google.cloud.pubsub.v1.SubscriptionAdminClient` and
`com.google.cloud.pubsub.v1.TopicAdminClient` as CDI beans as shown in the example below. This is usefull if the basic
facilities offered by `io.quarkiverse.googlecloudservices.pubsub.QuarkusPubSub` are not sufficient:

[source, java]
----
@Inject
SubscriptionAdminClient subscriptionAdminClient;
@Inject
TopicAdminClient topicAdminClient;
public someMethod() {
var pushConfig = ...; // Create com.google.pubsub.v1.PushConfig
subscriptionAdminClient.createSubscription("subscription-name", "topic-name", pushConfig, 10 /* ACK deadline */);
var topics = topicAdminClient.listTopics("my-google-project");
}
----

== Dev Service

=== Configuring the Dev Service
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkiverse.googlecloudservices.firebase.deployment;

import java.util.Optional;
import java.util.Set;

import io.quarkiverse.googlecloudservices.firebase.deployment.testcontainers.FirebaseEmulatorContainer;
import io.quarkus.runtime.annotations.ConfigRoot;
Expand Down Expand Up @@ -199,6 +200,12 @@ interface Cli {
*/
Optional<FirebaseEmulatorContainer.ImportExport> importExport();

/**
* Indicates the set of experimental features from firebase to enable (using the firebase experiment:enable
* command line option).
*/
Optional<Set<String>> experiments();

/**
* Enable firebase emulators debugging.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ public DevServicesResultBuildItem start(DockerStatusBuildItem dockerStatusBuildI

// Try starting the container if conditions are met
try {
devService = startContainerIfAvailable(dockerStatusBuildItem, projectConfig, firebaseBuildTimeConfig,
devService = startContainerIfAvailable(
dockerStatusBuildItem,
closeBuildItem,
projectConfig,
firebaseBuildTimeConfig,
globalDevServicesConfig.timeout);
} catch (Throwable t) {
LOGGER.warn("Unable to start Firebase dev service", t);
Expand All @@ -87,9 +91,11 @@ public DevServicesResultBuildItem start(DockerStatusBuildItem dockerStatusBuildI
* @param dockerStatusBuildItem, Docker status
* @param config, Configuration for the Firebase service
* @param timeout, Optional timeout for starting the service
* @param closeBuildItem
* @return Running service item, or null if the service couldn't be started
*/
private DevServicesResultBuildItem.RunningDevService startContainerIfAvailable(DockerStatusBuildItem dockerStatusBuildItem,
CuratedApplicationShutdownBuildItem closeBuildItem,
FirebaseDevServiceProjectConfig projectConfig,
FirebaseDevServiceConfig config,
Optional<Duration> timeout) {
Expand All @@ -111,7 +117,7 @@ private DevServicesResultBuildItem.RunningDevService startContainerIfAvailable(D
return null;
}

return startContainer(dockerStatusBuildItem, projectConfig, config, timeout);
return startContainer(closeBuildItem, projectConfig, config, timeout);
}

private boolean isEnabled(FirebaseDevServiceConfig config) {
Expand All @@ -125,12 +131,12 @@ private boolean isEnabled(FirebaseDevServiceConfig config) {
/**
* Starts the Pub/Sub emulator container with provided configuration.
*
* @param dockerStatusBuildItem, Docker status
* @param closeBuildItem The close build item to handle shutdown of the container
* @param config, Configuration for the Firebase service
* @param timeout, Optional timeout for starting the service
* @return Running service item, or null if the service couldn't be started
*/
private DevServicesResultBuildItem.RunningDevService startContainer(DockerStatusBuildItem dockerStatusBuildItem,
private DevServicesResultBuildItem.RunningDevService startContainer(CuratedApplicationShutdownBuildItem closeBuildItem,
FirebaseDevServiceProjectConfig projectConfig,
FirebaseDevServiceConfig config,
Optional<Duration> timeout) {
Expand All @@ -155,6 +161,8 @@ private DevServicesResultBuildItem.RunningDevService startContainer(DockerStatus
.forEach((e, h) -> LOGGER.info("Google Cloud emulator config property " + e + " set to " + h));
}

closeBuildItem.addCloseTask(emulatorContainer::close, true);

// Return running service item with container details
return new DevServicesResultBuildItem.RunningDevService(FirebaseBuildSteps.FEATURE,
emulatorContainer.getContainerId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ private void handleCliConfig(FirebaseDevServiceConfig.Firebase.Emulator.Cli cli,
cli.javaToolOptions().ifPresent(cliConfig::withJavaToolOptions);
cli.emulatorData().map(FirebaseEmulatorConfigBuilder::asPath).ifPresent(cliConfig::withEmulatorData);
cli.importExport().ifPresent(cliConfig::withImportExport);
cli.experiments().ifPresent(cliConfig::withExperiments);
cli.debug().ifPresent(cliConfig::withDebug);

cliConfig.done();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;

import io.quarkiverse.googlecloudservices.firebase.deployment.testcontainers.json.Emulators;
Expand All @@ -21,6 +23,8 @@
*/
class CustomFirebaseConfigReader {

private static final Logger LOGGER = LoggerFactory.getLogger(CustomFirebaseConfigReader.class);

private final ObjectMapper objectMapper = new ObjectMapper();

/**
Expand Down Expand Up @@ -110,6 +114,8 @@ private Map<FirebaseEmulatorContainer.Emulator, FirebaseEmulatorContainer.Expose
map = Map.copyOf(map);
}

LOGGER.debug("Found the following emulators configured in firebase.json {}", map.keySet());

return map;
}

Expand Down Expand Up @@ -137,6 +143,9 @@ private FirebaseEmulatorContainer.FirestoreConfig readFirestore(Object firestore
.ofNullable(firestoreMap.get("indexes"))
.map(f -> this.resolvePath(f, customFirebaseJson));

LOGGER.debug("Firestore configured with rules file {}", rulesFile);
LOGGER.debug("Firestore configured with indexes file {}", indexesFile);

return new FirebaseEmulatorContainer.FirestoreConfig(
rulesFile,
indexesFile);
Expand All @@ -152,8 +161,11 @@ private FirebaseEmulatorContainer.HostingConfig readHosting(Object hosting, Path

var publicDir = Optional
.ofNullable(hostingMap.get("public"))
.or(() -> Optional.ofNullable(hostingMap.get("source")))
.map(f -> this.resolvePath(f, customFirebaseJson));

LOGGER.debug("Hosting configured with public directory {}", publicDir);

return new FirebaseEmulatorContainer.HostingConfig(
publicDir);
} else {
Expand All @@ -170,6 +182,8 @@ private FirebaseEmulatorContainer.StorageConfig readStorage(Object storage, Path
.ofNullable(storageMap.get("rules"))
.map(f -> this.resolvePath(f, customFirebaseJson));

LOGGER.debug("Storage configured with rules file {}", rulesFile);

return new FirebaseEmulatorContainer.StorageConfig(
rulesFile);
} else {
Expand All @@ -192,6 +206,9 @@ private FirebaseEmulatorContainer.FunctionsConfig readFunctions(Object functions
.map(String[].class::cast)
.orElse(new String[0]);

LOGGER.debug("Functions will be read from source directory {}", functionsPath);
LOGGER.debug("Functions configured with ignore file {}", (Object) ignores);

return new FirebaseEmulatorContainer.FunctionsConfig(
functionsPath,
ignores);
Expand Down
Loading

0 comments on commit 0929a96

Please sign in to comment.