Skip to content

fix(config): use api.{realm} CRUD host and add O11y API URL override (SAO-18181) - #304

Open
etserend wants to merge 2 commits into
mainfrom
fix/sao-18181-o11y-api-host
Open

etserend wants to merge 2 commits into
mainfrom
fix/sao-18181-o11y-api-host

Conversation

@etserend

@etserend etserend commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The SDK hardcoded app.{realm}.observability.splunkcloud.com for O11y CRUD requests with no way to override the endpoint. This change moves the default CRUD host and adds an optional override. Jira: SAO-18181.

  • O11y CRUD now targets https://api.{realm}.observability.splunkcloud.com (was app.).
  • New optional SPLUNK_AO_O11Y_API_URL overrides the CRUD API origin only. It must be an https:// origin with no path, credentials, query or fragment. It counts as O11y configuration, so it conflicts with the standalone variables. Errors never echo the value.
  • Unchanged: OTLP ingest endpoint and console URL (app.{realm}).
  • Docs updated: README, CHANGELOG, AGENTS.md, ARCHITECTURE.md.

Testing

  • Targeted tests (tests/test_deployment.py, tests/test_o11y_config.py): 128 passed (adds tests/test_config.py), including new override, validation and auth-guard tests.
  • Full suite: no new failures compared with main. The pre-existing failures also occur on main without this change (OTLP exporter import, OpenAI, serialization).
  • mypy clean; ruff lint and format pass on the changed Python files.
  • Authenticated CRUD (Projects().list()) through the test pipeline lab0 -> rc0 -> us1 (us1 is production). Each realm succeeds on the new default host and through an explicit override:
Realm Raw GET app. / api. SDK default api.{realm}.observability.splunkcloud.com SDK override https://api.{realm}.signalfx.com
lab0 200 / 200 16 projects 16 projects
rc0 200 / 200 4 projects 4 projects
us1 200 / 200 9 projects 9 projects
  • Invalid overrides (path, credentials, bad port, malformed IPv6) are rejected with a clear error.

Open items before merge

  • Confirm the SPLUNK_AO_O11Y_API_URL name (public surface).
  • Decide the release vehicle. No version bump here.

Not covered: an override for the OTLP ingest endpoint, and custom CA/TLS configuration.

@etserend etserend changed the title fix(config): use api.{realm} host and add API URL override for O11y CRUD (SAO-18181) fix(config): use api.{realm} CRUD host and add O11y API URL override (SAO-18181) Nov 3, 2026
…(SAO-18181)

O11y CRUD requests now target https://api.{realm}.observability.splunkcloud.com
instead of https://app.{realm}.observability.splunkcloud.com. Add optional
SPLUNK_AO_O11Y_API_URL to override the CRUD API origin: https only, origin only
(no path, credentials, query or fragment), with the origin rebuilt from host and
port. The override counts as O11y configuration and is reported by the auth
guard when the realm is missing. The OTLP ingest endpoint and the console URL
are unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
@etserend
etserend force-pushed the fix/sao-18181-o11y-api-host branch from a72e9b4 to 8223cdc Compare November 3, 2026 01:15
@etserend
etserend marked this pull request as ready for review November 3, 2026 01:18
@etserend
etserend requested a review from pradystar November 3, 2026 16:55

@opikalova opikalova left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This review was generated by the Astra agent (claude-opus-5-5). It may contain mistakes.

Verdict: needs_discussion — The code is sound. The default CRUD host changes for every realm, but the PR verifies only three realms, and the public variable name is still an open item.

General Comments

  • 🟡 minor (question): This change moves the default CRUD host from app.{realm} to api.{realm} for every O11y user. The testing table in the description lists only lab0, rc0 and us1.

If api.{realm} does not route /ao/api/ in another realm where AO is available, CRUD breaks there after upgrade. Examples are us0, eu0, jp0 and au0. The new override is the only way to recover.

Please confirm one of these:

  • AO is only available in the verified realms.
  • api.{realm} serves /ao/api/ in all realms where AO runs.

The description also leaves "Confirm the SPLUNK_AO_O11Y_API_URL name" unchecked. This is a public surface, so settle it before merge.

  • 🟡 minor (testing): SPLUNK_AO_O11Y_API_URL now counts as an O11y detection variable (src/splunk_ao/deployment.py:12). The root fixture clears it (tests/conftest.py:177). The ADK test does not.

splunk-ao-adk/tests/test_observer.py:25 clears only the three old O11y variables. It then sets SPLUNK_AO_API_KEY and SPLUNK_AO_CONSOLE_URL.

If a developer or CI shell exports SPLUNK_AO_O11Y_API_URL, resolve_deployment() raises AmbiguousConfigurationError and the test fails. Add the new variable to that loop. A search for SPLUNK_AO_O11Y_API_TOKEN" in tests, splunk-ao-a2a and splunk-ao-adk found no other env-clearing loop that needs it.

Follow-ups

Suggested follow-up work that could be tracked as Jira tickets:

  • splunk-ao-adk/README.md:65-66: The ADK and A2A READMEs (splunk-ao-a2a/README.md:86-87) list the O11y variables but not SPLUNK_AO_O11Y_API_URL. Add a row or link to the root README so integration users can find the override.

Comment on lines +88 to +89
if self.api_url:
self.api_url = _normalize_api_origin(self.api_url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 minor (design): An invalid override is validated eagerly in __post_init__. Every O11yConfig.from_env() call therefore raises on it, including the telemetry-only paths:

  • src/splunk_ao/otel.py:137 (SplunkAOOTLPExporter)
  • src/splunk_ao/logger/logger.py:419 (logger sink)
  • src/splunk_ao/config.py:230 (_bridge_env_vars, run by SplunkAOConfig.get() at otel.py:133)

Scenario: a telemetry-only user sets SPLUNK_AO_O11Y_API_URL=https://api.lab0.signalfx.com/ao/api/ by mistake. OTLP exporter and logger construction then raise ConfigurationError. This contradicts CHANGELOG.md:18 ("OTLP ingest is not affected") and the "never OTLP ingest" note in AGENTS.md:121.

Options:

  1. Keep fail-fast. Then reword the docs to say an invalid value fails all SDK configuration. Add a test that SplunkAOConfig.get() raises the clean ConfigurationError and not a wrapped pydantic error.
  2. Validate lazily in api_root, so only CRUD paths fail.

Option 1 is simpler and catches typos early. It needs the doc fix and the test.

🤖 Generated by the Astra agent

Comment on lines +64 to +65
if any(ch.isspace() for ch in parts.netloc):
raise ConfigurationError("SPLUNK_AO_O11Y_API_URL has an invalid host.")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 minor (bug): The host check rejects only whitespace. urlsplit accepts and keeps other invalid host characters. I checked these values with stdlib urlsplit:

  • https://h.com;x gives hostname h.com;x.
  • https://h.com\evil gives hostname h.com\evil.
  • https://h%2e.com gives hostname h%2e.com.
  • https://h:0 gives port 0. The SDK accepts it as https://h:0.

urlsplit also silently strips embedded \n and \t, so https://api.exa\nmple.com becomes api.example.com.

These values pass validation and then fail later at request time with an unclear transport error. That defeats the purpose of the clear error here.

Fix: check parts.hostname against an allowlist pattern (LDH labels, or an IPv6 literal). Reject port 0. If the user enters a Unicode IDN, encode it with idna first, or reject it with a message.

🤖 Generated by the Astra agent

SPLUNK_AO_O11Y_API_URL now counts as an O11y detection variable. The ADK
autouse config fixture cleared no O11y variables, so exporting it (or
SPLUNK_AO_REALM) broke every ADK test during setup. Clear all four O11y
variables in the fixture, mirroring the root tests/conftest.py, and add the
new variable to the observer test's own clearing loop.

Co-Authored-By: Claude <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants