From a5746f0ac608b291abc21f4903edafc535a78b20 Mon Sep 17 00:00:00 2001 From: Jeroen Benckhuijsen Date: Fri, 3 Jan 2025 16:39:33 +0100 Subject: [PATCH 1/2] Added debug logging to ease detecting and fixing issues --- .../CustomFirebaseConfigReader.java | 16 ++++++++++++++ .../FirebaseEmulatorContainer.java | 21 ++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java index a7050bd9..740cd2fe 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/CustomFirebaseConfigReader.java @@ -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; @@ -21,6 +23,8 @@ */ class CustomFirebaseConfigReader { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomFirebaseConfigReader.class); + private final ObjectMapper objectMapper = new ObjectMapper(); /** @@ -110,6 +114,8 @@ private Map 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); @@ -154,6 +163,8 @@ private FirebaseEmulatorContainer.HostingConfig readHosting(Object hosting, Path .ofNullable(hostingMap.get("public")) .map(f -> this.resolvePath(f, customFirebaseJson)); + LOGGER.debug("Hosting configured with public directory {}", publicDir); + return new FirebaseEmulatorContainer.HostingConfig( publicDir); } else { @@ -170,6 +181,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 { @@ -192,6 +205,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); diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java index 31c96003..6e47d4ca 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java @@ -921,6 +921,8 @@ public FirebaseEmulatorContainer(EmulatorConfig emulatorConfig) { .map(Path::toString) .orElse(new File(FirebaseJsonBuilder.FIREBASE_HOSTING_SUBPATH).getAbsolutePath()); + LOGGER.debug("Mounting {} to the container hosting path", hostingPath); + // Mount volume for static hosting content this.withFileSystemBind(hostingPath, containerHostingPath(emulatorConfig), BindMode.READ_ONLY); } @@ -933,6 +935,8 @@ public FirebaseEmulatorContainer(EmulatorConfig emulatorConfig) { .map(Path::toString) .orElse(new File(FirebaseJsonBuilder.FIREBASE_FUNCTIONS_SUBPATH).getAbsolutePath()); + LOGGER.debug("Mounting {} to the container functions sources path", functionsPath); + // Mount volume for functions this.withFileSystemBind(functionsPath, containerFunctionsPath(emulatorConfig), BindMode.READ_ONLY); } @@ -1036,10 +1040,14 @@ private void validateConfiguration() { } if (emulatorConfig.customFirebaseJson.isPresent()) { - var hostingDirIsAbsolute = emulatorConfig.firebaseConfig.hostingConfig.hostingContentDir + var hostingDir = emulatorConfig.firebaseConfig.hostingConfig.hostingContentDir; + + var hostingDirIsAbsolute = hostingDir .map(Path::isAbsolute) .orElse(false); + LOGGER.debug("Checking if path {} is absolute --> {}", hostingDir, hostingDirIsAbsolute); + if (hostingDirIsAbsolute) { throw new IllegalStateException( "When using a custom firebase.json, the hosting path must be relative to the firebase.json file"); @@ -1047,11 +1055,14 @@ private void validateConfiguration() { var firebasePath = emulatorConfig.customFirebaseJson.get().toAbsolutePath().getParent(); - var hostingDirIsChildOfFirebaseJsonParent = emulatorConfig.firebaseConfig.hostingConfig.hostingContentDir + var hostingDirIsChildOfFirebaseJsonParent = hostingDir .map(Path::toAbsolutePath) .map(h -> h.startsWith(firebasePath)) .orElse(true); + LOGGER.debug("Checking if the hosting path {} is relative to the firebase.json file --> {}", hostingDir, + hostingDirIsChildOfFirebaseJsonParent); + if (!hostingDirIsChildOfFirebaseJsonParent) { throw new IllegalStateException( "When using a custom firebase.json, the hosting path must be in the same subtree as the firebase.json file"); @@ -1059,10 +1070,14 @@ private void validateConfiguration() { } if (emulatorConfig.firebaseConfig.functionsConfig.functionsPath.isPresent()) { - var functionsDirIsAbsolute = emulatorConfig.firebaseConfig.functionsConfig.functionsPath + var functionsDir = emulatorConfig.firebaseConfig.functionsConfig.functionsPath; + var functionsDirIsAbsolute = functionsDir .map(Path::isAbsolute) .orElse(false); + LOGGER.debug("Checking if the functions sources dir {} is absolute --> {}", functionsDir, + functionsDirIsAbsolute); + if (functionsDirIsAbsolute) { throw new IllegalStateException("Functions path cannot be absolute"); } From 820bdbe3deeeed721bdb3ac9a87bb3fdbeead41e Mon Sep 17 00:00:00 2001 From: Jeroen Benckhuijsen Date: Fri, 3 Jan 2025 17:02:32 +0100 Subject: [PATCH 2/2] Fix reading the firebase.json file from an absolute path, this conflicts with the Firebase hosting detection. --- .../FirebaseEmulatorContainer.java | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java index 6e47d4ca..b7506104 100644 --- a/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java +++ b/firebase-devservices/deployment/src/main/java/io/quarkiverse/googlecloudservices/firebase/deployment/testcontainers/FirebaseEmulatorContainer.java @@ -413,7 +413,7 @@ public FirebaseConfigBuilder withFirebaseConfig() { public EmulatorConfig buildConfig() { if (firebaseConfig == null) { // Try to autoload the firebase.json configuration - var defaultFirebaseJson = new File("firebase.json").getAbsoluteFile().toPath(); + var defaultFirebaseJson = new File("firebase.json").toPath(); LOGGER.info("Trying to automatically read firebase config from {}", defaultFirebaseJson); @@ -943,33 +943,54 @@ public FirebaseEmulatorContainer(EmulatorConfig emulatorConfig) { } static String containerHostingPath(EmulatorConfig emulatorConfig) { - var hostingPath = emulatorConfig.firebaseConfig().hostingConfig().hostingContentDir(); - if (emulatorConfig.customFirebaseJson().isPresent()) { - var firebaseJsonDir = emulatorConfig.customFirebaseJson().get().getParent(); - hostingPath = hostingPath.map(path -> path.subpath(firebaseJsonDir.getNameCount(), path.getNameCount())); - } + var hostingPath = relativizeToFirebaseJson( + emulatorConfig.firebaseConfig().hostingConfig().hostingContentDir(), + emulatorConfig); + String containerHostingPath; if (hostingPath.isPresent()) { var path = hostingPath.get(); if (path.isAbsolute()) { - return FIREBASE_HOSTING_PATH; + containerHostingPath = FIREBASE_HOSTING_PATH; } else { - return FIREBASE_ROOT + "/" + hostingPath.get(); + containerHostingPath = FIREBASE_ROOT + "/" + hostingPath.get(); } } else { - return FIREBASE_HOSTING_PATH; + containerHostingPath = FIREBASE_HOSTING_PATH; } + + LOGGER.debug("Container hosting path is {}", containerHostingPath); + + return containerHostingPath; } static String containerFunctionsPath(EmulatorConfig emulatorConfig) { - var functionsPath = emulatorConfig.firebaseConfig().functionsConfig().functionsPath(); - if (emulatorConfig.customFirebaseJson().isPresent()) { - var firebaseJsonDir = emulatorConfig.customFirebaseJson().get().getParent(); - functionsPath = functionsPath.map(path -> path.subpath(firebaseJsonDir.getNameCount(), path.getNameCount())); - } - return FIREBASE_ROOT + "/" + functionsPath + var functionsPath = relativizeToFirebaseJson( + emulatorConfig.firebaseConfig().functionsConfig().functionsPath(), + emulatorConfig); + + var containerFunctionsPath = FIREBASE_ROOT + "/" + functionsPath .map(Path::toString) .orElse(FirebaseJsonBuilder.FIREBASE_FUNCTIONS_SUBPATH); + + LOGGER.debug("Container functions path is {}", containerFunctionsPath); + + return containerFunctionsPath; + } + + private static Optional relativizeToFirebaseJson(Optional filePath, EmulatorConfig emulatorConfig) { + if (emulatorConfig.customFirebaseJson().isPresent()) { + var firebaseJsonFile = emulatorConfig.customFirebaseJson().get(); + var nameCount = firebaseJsonFile.getParent() == null ? 0 : firebaseJsonFile.getParent().getNameCount(); + + var result = filePath.map(path -> path.subpath(nameCount, path.getNameCount())); + + LOGGER.debug("Resolved path to be {} relative to the firebase.json file", result); + + return result; + } else { + return filePath; + } } private static class FirebaseDockerBuilder {