diff --git a/modules/keycloak/testcontainers/keycloak/__init__.py b/modules/keycloak/testcontainers/keycloak/__init__.py index ca5702298..27b6b20d1 100644 --- a/modules/keycloak/testcontainers/keycloak/__init__.py +++ b/modules/keycloak/testcontainers/keycloak/__init__.py @@ -23,6 +23,8 @@ class KeycloakContainer(DockerContainer): + has_realm_imports = False + """ Keycloak container. @@ -43,12 +45,14 @@ def __init__( username: Optional[str] = None, password: Optional[str] = None, port: int = 8080, + cmd: Optional[str] = _DEFAULT_DEV_COMMAND, ) -> None: super().__init__(image=image) self.username = username or os.environ.get("KEYCLOAK_ADMIN", "test") self.password = password or os.environ.get("KEYCLOAK_ADMIN_PASSWORD", "test") self.port = port self.with_exposed_ports(self.port) + self.cmd = cmd def _configure(self) -> None: self.with_env("KEYCLOAK_ADMIN", self.username) @@ -56,9 +60,11 @@ def _configure(self) -> None: # Enable health checks # see: https://www.keycloak.org/server/health#_relevant_options self.with_env("KC_HEALTH_ENABLED", "true") - # Starting Keycloak in development mode + # Start Keycloak in development mode # see: https://www.keycloak.org/server/configuration#_starting_keycloak_in_development_mode - self.with_command(_DEFAULT_DEV_COMMAND) + if self.has_realm_imports: + self.cmd += " --import-realm" + self.with_command(self.cmd) def get_url(self) -> str: host = self.get_container_host_ip() @@ -67,10 +73,10 @@ def get_url(self) -> str: @wait_container_is_ready(requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) def _readiness_probe(self) -> None: - # Keycloak provides an REST API endpoints for health checks: https://www.keycloak.org/server/health + # Keycloak provides REST API endpoints for health checks: https://www.keycloak.org/server/health response = requests.get(f"{self.get_url()}/health/ready", timeout=1) response.raise_for_status() - if self._command == _DEFAULT_DEV_COMMAND: + if _DEFAULT_DEV_COMMAND in self._command: wait_for_logs(self, "Added user .* to realm .*") def start(self) -> "KeycloakContainer": @@ -79,6 +85,22 @@ def start(self) -> "KeycloakContainer": self._readiness_probe() return self + def with_realm_import_file(self, realm_import_file: str) -> "KeycloakContainer": + file = os.path.abspath(realm_import_file) + if not os.path.exists(file): + raise FileNotFoundError(f"Realm file {file} does not exist") + self.with_volume_mapping(file, "/opt/keycloak/data/import/realm.json") + self.has_realm_imports = True + return self + + def with_realm_import_folder(self, realm_import_folder: str) -> "KeycloakContainer": + folder = os.path.abspath(realm_import_folder) + if not os.path.exists(folder): + raise FileNotFoundError(f"Realm folder {folder} does not exist") + self.with_volume_mapping(folder, "/opt/keycloak/data/import/") + self.has_realm_imports = True + return self + def get_client(self, **kwargs) -> KeycloakAdmin: default_kwargs = { "server_url": self.get_url(),