canonical / canonical/charm-integration-testing

discourse-k8s charm should have external_hostname property explicitly set for the deployment not to fail.

Open
#324 1 comment 1 reaction 2 assignees Claimed by @dmvdm View on GitHub
bug bundle-generation charm-deployment
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.