canonical / canonical/charm-integration-testing
discourse-k8s charm should have external_hostname property explicitly set for the deployment not to fail.
- Dominant language
- Python
- Stars
- 6
- Forks
- 1
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 96
Description
## Summary
When `external_hostname` config is not set and an oauth relation is established, the charm constructs an invalid OAuth redirect URL using the Juju application name instead of a routable external hostname, causing OAuth configuration to fail with "Invalid URL" error.
## Test Observer Details
- **Test Execution**: https://test-observer.canonical.com/#/charms/310692?testExecutionId=310335&testResultId=8767362
- **Charm**: discourse-k8s revision 234, latest/edge channel
- **Environment**: juju:3/stable ubuntu:20.04 kubernetes
- **Test Date**: 2026-01-18
## Error Details
```
unit-target-0: 2026-01-18 10:22:50 ERROR unit.target/0.juju-log oauth:23:
Invalid OAuth client config: Invalid URL https://target/auth/oidc/callback
```
The charm constructs the redirect URL as `https://target/auth/oidc/callback` where "target" is the Juju application name. This fails URL validation in the OAuth library because "target" is not a valid FQDN (lacks a TLD like `.com` or `.local`).
## Root Cause
**File**: [src/charm.py#L280](https://github.com/canonical/discourse-k8s-operator/blob/1420720001955b7abb0c67ff65eb0a956ef083fd/src/charm.py#L280-L289)
```python
def _get_external_hostname(self) -> str:
"""Extract and return hostname from site_url or default to [application name].
Returns:
The site hostname defined as part of the site_url configuration or a default value.
"""
return (
typing.cast(str, self.config["external_hostname"])
if self.config["external_hostname"]
else self.app.name # ← BUG: Defaults to application name
)
```
This method is called by `OAuthObserver._generate_client_config()` in [src/oauth_observer.py#L81](https://github.com/canonical/discourse-k8s-operator/blob/1420720001955b7abb0c67ff65eb0a956ef083fd/src/oauth_observer.py#L81) to construct the OAuth redirect URI:
```python
self.client_config = ClientConfig(
redirect_uri=f"https://{self._external_hostname_callback()}/auth/oidc/callback",
# ...
)
```
The OAuth library validates URLs using a regex pattern that requires domain names to have at least one dot (e.g., `example.com`, `discourse.local`). Single-word hostnames like "target" are rejected.
**Validation Code**: [lib/charms/hydra/v0/oauth.py](https://github.com/canonical/discourse-k8s-operator/blob/1420720001955b7abb0c67ff65eb0a956ef083fd/lib/charms/hydra/v0/oauth.py#L91-L98)
## Requirement
discourse-k8s charm has the external_hostname property setup in charm-test-configs.
Contributor guide
Assessment
This issue has not been assessed yet.