Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ with `FORGE_*` env vars using **double-underscore** nesting, e.g.
| --- | --- |
| `auth.bootstrap_admin` | First-run admin username (a UPN, default `admin@example.com`) / password. No or a blank password means no bootstrap admin. |
| `server.allow_insecure_defaults` | Default `false`: startup fails while the bootstrap-admin password is `changeme` or the S3 keys are `minioadmin`. `true` only in dev configs (`forge.toml`, `.env.example`, `docker-compose.app.yml`). |
| `server.alias_base_urls` | Further base URLs, such as the old Nexus host pointed at Forge (`["https://nexus.example.com"]`): a request for an alias host is handed the client protocols' URLs on that alias instead of `public_base_url`. See [docs/deployment.md](./docs/deployment.md#further-host-names-aliases). |
| `[redis]` | Optional shared L2 cache + cross-instance invalidation. Omit for in-process cache only. `connect_timeout_ms` / `response_timeout_ms` (default 2000) bound every Redis call. |
| `[blob_cache]` | Optional local disk cache for blobs (`path`, `max_bytes` = `"auto"` or bytes, `min_free_bytes`): hot downloads skip S3 and cached packages keep resolving while S3 is down. See [docs/deployment.md](./docs/deployment.md#local-blob-cache). |
| `[telemetry]` | OpenTelemetry export over OTLP/HTTP: `metrics`, `traces`, `logs` (each off by default), sent where the `OTEL_*` variables say (`OTEL_EXPORTER_OTLP_ENDPOINT`, default `http://localhost:4318`). See [docs/deployment.md](./docs/deployment.md#telemetry). |
Expand Down
44 changes: 42 additions & 2 deletions crates/e2e/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ fn config_toml(
trusted_proxies: &[String],
cache_ttl_seconds: u64,
public_base_url: &str,
alias_base_urls: &[String],
oidc_block: &str,
auth_block: &str,
blob_cache: Option<&BlobCacheSetup>,
Expand Down Expand Up @@ -250,12 +251,17 @@ fn config_toml(
let quoted: Vec<String> = trusted_proxies.iter().map(|t| format!("{t:?}")).collect();
format!("trusted_proxy_cidrs = [{}]\n", quoted.join(", "))
};
let aliases = {
let quoted: Vec<String> = alias_base_urls.iter().map(|a| format!("{a:?}")).collect();
format!("alias_base_urls = [{}]", quoted.join(", "))
};
std::env::set_var(ROOT_KEY_VAR, ROOT_KEY);
format!(
r#"
[server]
bind = "127.0.0.1:0"
public_base_url = "{public_base_url}"
{aliases}

[database]
url = "{db_url}"
Expand Down Expand Up @@ -328,6 +334,11 @@ pub struct StackBuilder {
blob_cache: Option<BlobCacheSetup>,
/// `None` ⇒ the static test keys.
s3_credentials: Option<String>,
/// The host of `server.public_base_url`; `None` ⇒ the listener's
/// address (`127.0.0.1`).
public_host: Option<String>,
/// Hosts of `server.alias_base_urls` (`http://<host>:<port>`).
alias_hosts: Vec<String>,
}

impl Default for StackBuilder {
Expand All @@ -347,6 +358,8 @@ impl Default for StackBuilder {
s3_endpoint: None,
blob_cache: None,
s3_credentials: None,
public_host: None,
alias_hosts: Vec::new(),
}
}
}
Expand Down Expand Up @@ -426,6 +439,23 @@ impl StackBuilder {
self
}

/// Name the server `http://<host>:<port>` in `server.public_base_url`
/// instead of its listener's address. [`TestServer::base_url`] stays the
/// listener's address, so the harness reaches the server whether `host`
/// resolves or not (`forge.invalid` never does: a client handed a URL on
/// it cannot follow it).
pub fn public_host(mut self, host: impl Into<String>) -> Self {
self.public_host = Some(host.into());
self
}

/// Add `http://<host>:<port>` to `server.alias_base_urls` (#312), the
/// port the server listens on.
pub fn alias_host(mut self, host: impl Into<String>) -> Self {
self.alias_hosts.push(host.into());
self
}

/// Enable the local blob cache at `path`, `max_bytes` bytes large
/// (`None`: `"auto"`). The server then starts even while S3 is down.
pub fn blob_cache(
Expand Down Expand Up @@ -478,6 +508,15 @@ impl StackBuilder {
.expect("bind ephemeral");
let addr = listener.local_addr().expect("local addr");
let base_url = format!("http://{addr}");
let public_base_url = match &self.public_host {
Some(host) => format!("http://{host}:{}", addr.port()),
None => base_url.clone(),
};
let alias_base_urls: Vec<String> = self
.alias_hosts
.iter()
.map(|host| format!("http://{host}:{}", addr.port()))
.collect();

let admin_ref = self
.bootstrap_admin
Expand All @@ -488,7 +527,7 @@ impl StackBuilder {
let oidc_block = self
.oidc_block_fn
.as_ref()
.map(|f| f(&base_url))
.map(|f| f(&public_base_url))
.unwrap_or_default();
let toml = config_toml(
&db_url,
Expand All @@ -497,7 +536,8 @@ impl StackBuilder {
redis.as_deref(),
&self.trusted_proxies,
self.cache_ttl_seconds,
&base_url,
&public_base_url,
&alias_base_urls,
&oidc_block,
self.auth_block.as_deref().unwrap_or_default(),
self.blob_cache.as_ref(),
Expand Down
Loading
Loading