Spell every o11y caller /v1/o11y

The server moved off /api/vN; the integration suite, handler tests,
install.sh's health wait and the docs still called the old tree.

Claude-Session: https://claude.ai/code/session_01TUxvfuta1Z44KVNYuAz71F
This commit is contained in:
2026-09-24 15:05:09 -07:00
parent 904e56d436
commit 46c6241c52
85 changed files with 454 additions and 463 deletions
+1 -1
View File
@@ -87,7 +87,7 @@ The dashboards list page (`/dashboard`) lists all dashboards in the workspace. F
- All Dashboards section header rendered.
- Search input, sort button, and at least one dashboard thumbnail visible.
**Cleanup:** delete the seeded dashboard via `DELETE /api/v1/dashboards/<id>`.
**Cleanup:** delete the seeded dashboard via `DELETE /v1/o11y/dashboards/<id>`.
#### TC-02 ...
</example-spec>
+4 -4
View File
@@ -2,15 +2,15 @@
#
# o11y-site — the o11y browser SPA served by hanzoai/static (house-native static
# plugin, scratch + Go binary), NOT nginx. The main server image (Dockerfile) is
# HEADLESS (O11Y_WEB_ENABLED=false, serves only /api/*); this image serves the
# dashboard SPA at the edge, and the ingress routes o11y.hanzo.ai here while
# /api/* goes to the backend (universe infra/k8s/o11y/ingress.yaml).
# HEADLESS (O11Y_WEB_ENABLED=false, serves only /v1/o11y/*); this image serves
# the dashboard SPA at the edge, and the ingress routes o11y.hanzo.ai here while
# /v1/o11y/* goes to the backend.
#
# CONTENT: built FROM SOURCE (frontend/) now that the @o11yhq -> @hanzo/ui
# migration is complete, tsgo --noEmit is clean, and `pnpm build` is green. The
# production build resolves the [[.BaseHref]]/[[.Settings]] Go-template placeholders
# at build time (vite.config.ts) so index.html is placeholder-free; assets are
# relative (base './') under <base href="/">, and the SPA calls same-origin /api/*
# relative (base './') under <base href="/">, and the SPA calls same-origin /v1/o11y/*
# — so a static --spa serve is faithful with no backend templating.
# 1) Build the SPA from source.
+13 -10
View File
@@ -51,19 +51,22 @@ public `/v1/o11y/...` paths. Cloud's `describe.go` reads that registry from a re
mount and weaves the result into the one published document. Change a struct and
the document follows; there is nothing to keep in sync.
There was a second emitter and it is **deleted**: `cmd/openapi.go` ran a swaggest
reflector over the runtime's gorilla/mux tree and wrote a committed 629 KB
`docs/api/openapi.yml` — 120 paths, 174 ops, spelled `/api/v1` ×59, `/api/v2` ×57,
`/api/v3`, `/api/v4`, `/api/v5` ×2, and **zero** `/v1/o11y`. It described the
fork's internal tree behind the delegation wildcard's `/v1/o11y/* -> /api/*`
rewrite, so it documented a surface no customer can address, in a shape that
breaks two house rules on its face. No CI regenerated or verified it, so it could
only drift. Gone with it: `pkg/o11y/openapi.go` (the reflector — unreachable once
the command went) and `registerGenerateOpenAPI` from `cmd/generate.go`.
There is no second emitter. A reflector over the runtime's router tree once wrote
a committed `docs/api/openapi.yml` describing an internal versioned tree no customer
could address; it is deleted with `pkg/o11y/openapi.go` and
`registerGenerateOpenAPI`. Do not add one back.
**If a route is not in the typed registry it is in no document.** That is the only
place to fix it; do not add a second writer.
## No `/api/`
Every route is `/v1/o11y/…`; the host already says api. `apiprefix_test.go`
fails on a registered route outside `/v1/` and on any `/api/v<N>` spelling in
the tree, so an upstream re-sync cannot bring the old namespace back. The one
`/api/` segment served is the Sentry SDK's envelope suffix under
`/v1/o11y/api/<project>/`, which a stock SDK appends to its DSN.
## The console (`pkg/web`) is router-agnostic
`web.Web` is `http.Handler` and nothing else. It used to also carry
@@ -361,7 +364,7 @@ user authorized for their own org. Cross-org is denied by org scoping
**The setup gate is gone.** `NewAPIHandler` (`pkg/query-service/app/http_handler.go`)
now sets `SetupCompleted = true` unconditionally — no org/user counting, no root
gate. So `/api/v1/register` is inert ("self-registration is disabled") and the SPA
gate. There is no register route, and the SPA
never shows an onboarding wizard. Native login/session/invite endpoints remain
compiled but are dead: no native users are ever created, so nothing can log in
through them. `apikeyidentn` (service-account API keys, `O11Y-API-KEY`) stays for
+2 -3
View File
@@ -6,9 +6,8 @@ package o11y
// WHY THE ANSWER LIVES HERE. It is a fact about these routes, so it belongs
// beside them. It used to live in the embedding host instead — hanzoai/cloud's
// apps/o11y kept its own list of "the o11y paths that need no principal" — and
// that list named /v1/o11y/api/v1/health, /api/v2/healthz, /api/v2/readyz and
// /api/v2/livez: the INTERNAL namespace this module used to rewrite onto before
// PATH UNTOUCHED (mount.go) removed the rewrite. The paths it named stopped
// that list named the probes under an INTERNAL versioned namespace this module
// used to rewrite onto before PATH UNTOUCHED (mount.go) removed the rewrite. The paths it named stopped
// existing and the paths that exist were never named, so the host's exemption
// matched nothing at all and every public op — /version, /health, the three
// probes, sign-in, the shared-dashboard reads — was refused 403 at the unified
+1 -1
View File
@@ -248,7 +248,7 @@ wait_for_containers_start() {
# The while loop is important because for-loops don't work for dynamic values
while [[ $timeout -gt 0 ]]; do
status_code="$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8080/api/v1/health?live=1" || true)"
status_code="$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8080/v1/o11y/health?live=1" || true)"
if [[ status_code -eq 200 ]]; then
break
else
+2 -2
View File
@@ -78,7 +78,7 @@ This command:
2. Verify it's working:
```bash
curl http://localhost:8080/api/v1/health
curl http://localhost:8080/v1/o11y/health
```
You should see: `{"status":"ok"}`
@@ -116,7 +116,7 @@ To verify everything is working correctly:
1. **Check Datastore**: `curl http://localhost:8123/ping` (should return "Ok.")
2. **Check OTel Collector**: `curl http://localhost:13133` (should return health status)
3. **Check Backend**: `curl http://localhost:8080/api/v1/health` (should return `{"status":"ok"}`)
3. **Check Backend**: `curl http://localhost:8080/v1/o11y/health` (should return `{"status":"ok"}`)
4. **Check Frontend**: Open `http://localhost:3301` in your browser
## How to send test data?
+4 -4
View File
@@ -24,7 +24,7 @@ Each route wraps a module handler method with the following:
For example, in `pkg/apiserver/o11yapiserver`:
```go
if err := router.Handle("/api/v1/invite", handler.New(
if err := router.Handle("/v1/o11y/invite", handler.New(
provider.authZ.AdminAccess(provider.userHandler.CreateInvite),
handler.OpenAPIDef{
ID: "CreateInvite",
@@ -114,7 +114,7 @@ func (h *handler) CreateThing(rw http.ResponseWriter, req *http.Request) {
In `pkg/apiserver/o11yapiserver`, add a route in the appropriate `add*Routes` function (`addUserRoutes`, `addSessionRoutes`, `addOrgRoutes`, etc.). The pattern is:
```go
if err := router.Handle("/api/v1/things", handler.New(
if err := router.Handle("/v1/o11y/things", handler.New(
provider.authZ.AdminAccess(provider.thingHandler.CreateThing),
handler.OpenAPIDef{
ID: "CreateThing",
@@ -193,10 +193,10 @@ type OpenAPIExample struct {
}
```
For reference, see `pkg/apiserver/o11yapiserver/querier.go` which defines examples inline for the `/api/v5/query_range` endpoint:
For reference, see `pkg/apiserver/o11yapiserver/querier.go` which defines examples inline for the `/v1/o11y/query_range` endpoint:
```go
if err := router.Handle("/api/v5/query_range", handler.New(provider.authZ.ViewAccess(provider.querierHandler.QueryRange), handler.OpenAPIDef{
if err := router.Handle("/v1/o11y/query_range", handler.New(provider.authZ.ViewAccess(provider.querierHandler.QueryRange), handler.OpenAPIDef{
ID: "QueryRangeV5",
Tags: []string{"querier"},
Summary: "Query range",
+1 -1
View File
@@ -120,7 +120,7 @@ Each spec follows these principles:
const token = await page.evaluate(
() => (globalThis as any).localStorage.getItem('AUTH_TOKEN') || '',
);
await page.request.post('/api/v1/dashboards', {
await page.request.post('/v1/o11y/dashboards', {
data: { title: 'my-name', uploadedGrafana: false },
headers: { Authorization: `Bearer ${token}` },
});
+2 -2
View File
@@ -133,7 +133,7 @@ logger = setup_logger(__name__)
def test_version(o11y: types.O11y) -> None:
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/version"),
o11y.self.host_configs["8080"].get("/v1/o11y/version"),
timeout=2,
)
logger.info(response)
@@ -163,7 +163,7 @@ logger = setup_logger(__name__)
def test_user_registration(o11y: types.O11y) -> None:
"""Test user registration functionality."""
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/register"),
o11y.self.host_configs["8080"].get("/v1/o11y/register"),
json={
"name": "testuser",
"orgId": "",
+2 -2
View File
@@ -8,8 +8,8 @@
* HAND EDIT: every `url` is built from `AI_API_PATH` instead of a hard-coded
* prefix, so the assistant path is spelled in exactly one place. `orval.config.ts`
* has no target for this spec, so nothing here regenerates today — if that ever
* changes, re-apply the substitution rather than letting `/api/v1/assistant`
* literals back in.
* changes, re-apply the substitution rather than letting hard-coded assistant
* path literals back in.
*/
import { useMutation, useQuery } from 'react-query';
import type {
@@ -119,7 +119,7 @@ describe('convertFiltersToExpression', () => {
id: '3',
key: { key: 'path', type: 'string' },
op: '=',
value: '/api/v1/users',
value: '/v1/users',
},
],
op: 'AND',
@@ -128,7 +128,7 @@ describe('convertFiltersToExpression', () => {
const result = convertFiltersToExpression(filters);
expect(result).toStrictEqual({
expression:
"message = 'user\\'s data' AND description = '' AND path = '/api/v1/users'",
"message = 'user\\'s data' AND description = '' AND path = '/v1/users'",
});
});
@@ -451,7 +451,7 @@ describe('convertFiltersToExpression', () => {
id: '5',
key: { key: 'path', type: 'string' },
op: '=',
value: '/api/v1/users/123?filter=true',
value: '/v1/users/123?filter=true',
},
],
op: 'AND',
@@ -460,7 +460,7 @@ describe('convertFiltersToExpression', () => {
const result = convertFiltersToExpression(filters);
expect(result).toStrictEqual({
expression:
"is_active = true AND is_deleted = false AND email = '[email protected]' AND description = 'Contains \"quotes\" and \\'apostrophes\\'' AND path = '/api/v1/users/123?filter=true'",
"is_active = true AND is_deleted = false AND email = '[email protected]' AND description = 'Contains \"quotes\" and \\'apostrophes\\'' AND path = '/v1/users/123?filter=true'",
});
});
@@ -1454,7 +1454,7 @@ describe('formatValueForExpression', () => {
});
it('should handle strings with special characters', () => {
expect(formatValueForExpression('/api/v1/users')).toBe("'/api/v1/users'");
expect(formatValueForExpression('/v1/users')).toBe("'/v1/users'");
expect(formatValueForExpression('[email protected]')).toBe(
"'[email protected]'",
);
+3 -3
View File
@@ -23,7 +23,7 @@ describe('MyComponent', () => {
const user = userEvent.setup({ pointerEventsCheck: 0 });
server.use(
rest.get('*/api/v1/example', (_req, res, ctx) => res(ctx.status(200), ctx.json({ value: 42 })))
rest.get('*/v1/o11y/example', (_req, res, ctx) => res(ctx.status(200), ctx.json({ value: 42 })))
);
render(<MyComponent />, undefined, { initialRoute: '/foo' });
@@ -52,10 +52,10 @@ Repo-specific reasons:
MSW overrides per test:
```ts
server.use(
rest.get(`${ENVIRONMENT.baseURL}/api/v1/orgs/me/filters/logs`, (_req, res, ctx) =>
rest.get(`${ENVIRONMENT.baseURL}/v1/o11y/orgs/me/filters/logs`, (_req, res, ctx) =>
res(ctx.status(200), ctx.json(quickFiltersListResponse)),
),
rest.put(`${ENVIRONMENT.baseURL}/api/v1/orgs/me/filters`, async (req, res, ctx) => {
rest.put(`${ENVIRONMENT.baseURL}/v1/o11y/orgs/me/filters`, async (req, res, ctx) => {
// capture payload if needed
return res(ctx.status(200), ctx.json({}));
}),
+1 -1
View File
@@ -60,7 +60,7 @@ images:
VARIANT: community
# The browser SPA (frontend/), served by hanzoai/static at the edge while
# /api/* goes to the server above. Takes no build-args and no secrets.
# /v1/o11y/* goes to the server above. Takes no build-args and no secrets.
#
# It builds on every push now, where docker-site.yaml filtered on
# `paths: [Dockerfile.site, frontend/**]`. That filter is not expressible in
+2 -2
View File
@@ -16,7 +16,7 @@ func TestNewWithEnvProvider(t *testing.T) {
t.Setenv("O11Y_APISERVER_TIMEOUT_DEFAULT", "70s")
t.Setenv("O11Y_APISERVER_TIMEOUT_MAX", "700s")
t.Setenv("O11Y_APISERVER_TIMEOUT_EXCLUDED__ROUTES", "/excluded1,/excluded2")
t.Setenv("O11Y_APISERVER_LOGGING_EXCLUDED__ROUTES", "/api/v1/health1")
t.Setenv("O11Y_APISERVER_LOGGING_EXCLUDED__ROUTES", "/v1/o11y/health1")
conf, err := config.New(
context.Background(),
@@ -48,7 +48,7 @@ func TestNewWithEnvProvider(t *testing.T) {
},
Logging: Logging{
ExcludedRoutes: []string{
"/api/v1/health1",
"/v1/o11y/health1",
},
},
}
@@ -161,8 +161,7 @@ func (provider *provider) addMetricsExplorerRoutes(router routing.Router) {
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
}))
// GetMetricDashboards (formerly /api/v2/metrics/dashboards) is superseded by
// GetMetricDashboardsV2 below (formerly /api/v3) — highest version wins.
// GetMetricDashboardsV2 is the one handler for /v1/o11y/metrics/dashboards.
router.Get("/v1/o11y/metrics/dashboards", handler.New(
provider.authzMiddleware.ViewAccess(provider.metricsExplorerHandler.GetMetricDashboardsV2),
handler.OpenAPIDef{
@@ -433,7 +433,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
"signal": "traces",
"stepInterval": 60,
"aggregations": []any{map[string]any{"expression": "p99(duration_nano)"}},
"filter": map[string]any{"expression": "service.name = 'search-api' AND name = 'GET /api/v1/search'"},
"filter": map[string]any{"expression": "service.name = 'search-api' AND name = 'GET /v1/search'"},
"groupBy": []any{
map[string]any{"name": "service.name", "fieldContext": "resource", "fieldDataType": "string"},
map[string]any{"name": "http.route", "fieldContext": "attribute", "fieldDataType": "string"},
+2 -2
View File
@@ -101,14 +101,14 @@ func TestPrepareFiltersV5(t *testing.T) {
name: "special_characters_in_values",
labels: map[string]string{
"message": "Error: Connection failed",
"path": "/api/v1/users",
"path": "/v1/users",
},
whereClause: "",
groupByItems: []qbtypes.GroupByKey{
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "message"}},
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "path"}},
},
expected: "message='Error: Connection failed' AND path='/api/v1/users'",
expected: "message='Error: Connection failed' AND path='/v1/users'",
description: "Should quote values with special characters",
},
{
@@ -60,18 +60,18 @@ func TestOrgUUIDFromProject_EmptyRejected(t *testing.T) {
}
func TestSentryKeyFromRequest_Header(t *testing.T) {
r := httptest.NewRequest("POST", "/api/acme/envelope/", nil)
r := httptest.NewRequest("POST", "/v1/o11y/api/acme/envelope/", nil)
r.Header.Set("X-Sentry-Auth", "Sentry sentry_version=7, sentry_key=pubkey123, sentry_client=sentry.python/1.40")
assert.Equal(t, "pubkey123", sentryKeyFromRequest(r))
}
func TestSentryKeyFromRequest_QueryFallback(t *testing.T) {
r := httptest.NewRequest("POST", "/api/acme/envelope/?sentry_key=qkey456", nil)
r := httptest.NewRequest("POST", "/v1/o11y/api/acme/envelope/?sentry_key=qkey456", nil)
assert.Equal(t, "qkey456", sentryKeyFromRequest(r))
}
func TestSentryKeyFromRequest_HeaderWins(t *testing.T) {
r := httptest.NewRequest("POST", "/api/acme/envelope/?sentry_key=qkey", nil)
r := httptest.NewRequest("POST", "/v1/o11y/api/acme/envelope/?sentry_key=qkey", nil)
r.Header.Set("X-Sentry-Auth", "Sentry sentry_key=hkey")
assert.Equal(t, "hkey", sentryKeyFromRequest(r))
}
+3 -3
View File
@@ -29,7 +29,7 @@ func claimsCtx() context.Context {
func TestViewRequest_TenantScopeFromHeader(t *testing.T) {
// A client tries to inject the tenant via ?orgSlug=evil; the header is the real
// tenant. ViewQuery.OrgSlug has no `query` tag, so the param is ignored.
r := httptest.NewRequest(http.MethodGet, "/api/observations?orgSlug=evil&traceId=t1", nil)
r := httptest.NewRequest(http.MethodGet, "/v1/o11y/llm/observations?orgSlug=evil&traceId=t1", nil)
r.Header.Set("X-Org-Id", "acme")
_, q, err := viewRequest(claimsCtx(), r)
@@ -47,14 +47,14 @@ func TestViewRequest_TenantScopeFromHeader(t *testing.T) {
// TestViewRequest_FailsClosedWithoutTenant proves a span-view request with no
// gateway-asserted tenant is REFUSED — never run as an un-scoped, all-orgs query.
func TestViewRequest_FailsClosedWithoutTenant(t *testing.T) {
r := httptest.NewRequest(http.MethodGet, "/api/observations", nil) // no X-Org-Id
r := httptest.NewRequest(http.MethodGet, "/v1/o11y/llm/observations", nil) // no X-Org-Id
if _, _, err := viewRequest(claimsCtx(), r); err == nil {
t.Fatal("viewRequest must FAIL CLOSED when X-Org-Id is absent (would otherwise read every tenant)")
}
// A blank header is likewise refused.
r2 := httptest.NewRequest(http.MethodGet, "/api/observations", nil)
r2 := httptest.NewRequest(http.MethodGet, "/v1/o11y/llm/observations", nil)
r2.Header.Set("X-Org-Id", " ")
if _, _, err := viewRequest(claimsCtx(), r2); err == nil {
t.Fatal("viewRequest must FAIL CLOSED on a blank X-Org-Id")
@@ -25,7 +25,7 @@ func NewHandler(module llmpricingrule.Module) llmpricingrule.Handler {
return &handler{module: module}
}
// List handles GET /api/v1/llm_pricing_rules.
// List handles GET /v1/o11y/llm_pricing_rules.
func (h *handler) List(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -63,7 +63,7 @@ func (h *handler) List(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusOK, llmpricingruletypes.NewGettableLLMPricingRulesFromLLMPricingRules(rules, total, q.Offset, q.Limit))
}
// Get handles GET /api/v1/llm_pricing_rules/{id}.
// Get handles GET /v1/o11y/llm_pricing_rules/{id}.
func (h *handler) Get(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -118,7 +118,7 @@ func (h *handler) CreateOrUpdate(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusNoContent, nil)
}
// Delete handles DELETE /api/v1/llm_pricing_rules/{id}.
// Delete handles DELETE /v1/o11y/llm_pricing_rules/{id}.
func (h *handler) Delete(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -23,7 +23,7 @@ func NewHandler(module spanmapper.Module) spanmapper.Handler {
return &handler{module: module}
}
// ListGroups handles GET /api/v1/span_mapper_groups.
// ListGroups handles GET /v1/o11y/span_mapper_groups.
func (h *handler) ListGroups(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -51,7 +51,7 @@ func (h *handler) ListGroups(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusOK, spantypes.NewGettableSpanMapperGroups(groups))
}
// CreateGroup handles POST /api/v1/span_mapper_groups.
// CreateGroup handles POST /v1/o11y/span_mapper_groups.
func (h *handler) CreateGroup(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -79,7 +79,7 @@ func (h *handler) CreateGroup(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusCreated, group)
}
// UpdateGroup handles PUT /api/v1/span_mapper_groups/{id}.
// UpdateGroup handles PUT /v1/o11y/span_mapper_groups/{id}.
func (h *handler) UpdateGroup(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -112,7 +112,7 @@ func (h *handler) UpdateGroup(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusNoContent, nil)
}
// DeleteGroup handles DELETE /api/v1/span_mapper_groups/{id}.
// DeleteGroup handles DELETE /v1/o11y/span_mapper_groups/{id}.
func (h *handler) DeleteGroup(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -139,7 +139,7 @@ func (h *handler) DeleteGroup(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusNoContent, nil)
}
// ListMappers handles GET /api/v1/span_mapper_groups/{id}/span_mappers.
// ListMappers handles GET /v1/o11y/span_mapper_groups/{id}/span_mappers.
func (h *handler) ListMappers(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -167,7 +167,7 @@ func (h *handler) ListMappers(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusOK, spantypes.NewGettableSpanMappers(mappers))
}
// CreateMapper handles POST /api/v1/span_mapper_groups/{id}/span_mappers.
// CreateMapper handles POST /v1/o11y/span_mapper_groups/{id}/span_mappers.
func (h *handler) CreateMapper(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -201,7 +201,7 @@ func (h *handler) CreateMapper(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusCreated, mapper)
}
// UpdateMapper handles PUT /api/v1/span_mapper_groups/{groupId}/span_mappers/{mapperId}.
// UpdateMapper handles PUT /v1/o11y/span_mapper_groups/{groupId}/span_mappers/{mapperId}.
func (h *handler) UpdateMapper(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -240,7 +240,7 @@ func (h *handler) UpdateMapper(rw http.ResponseWriter, r *http.Request) {
render.Success(rw, http.StatusNoContent, nil)
}
// DeleteMapper handles DELETE /api/v1/span_mapper_groups/{groupId}/span_mappers/{mapperId}.
// DeleteMapper handles DELETE /v1/o11y/span_mapper_groups/{groupId}/span_mappers/{mapperId}.
func (h *handler) DeleteMapper(rw http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
defer cancel()
@@ -61,7 +61,7 @@ func TestHandler_List(t *testing.T) {
mockModule := new(MockModule)
handler := NewHandler(mockModule)
req := httptest.NewRequest(http.MethodGet, "/api/v1/trace-funnels/list", nil)
req := httptest.NewRequest(http.MethodGet, "/v1/o11y/trace-funnels/list", nil)
orgID := valuer.GenerateUUID()
claims := authtypes.Claims{
@@ -5602,7 +5602,7 @@ func (r *DatastoreReader) GetNormalizedStatus(
// GetRecentLogs reads the most recent logs in [startNano, endNano], newest first,
// capped at limit, from the configured logs table (r.logsDB.r.logsTableV2) — the
// real read behind the classic GET /api/v1/logs endpoint, replacing the empty
// real read behind GET /v1/o11y/logs, replacing the empty
// {"results":[]} stub. The bounds are int64 nanosecond epochs and limit is an int
// (never user strings), so the fmt.Sprintf interpolation is injection-safe. It
// selects the core log columns plus service.name and the k8s namespace/pod/
+1 -1
View File
@@ -2575,7 +2575,7 @@ func (aH *APIHandler) logFieldUpdate(w http.ResponseWriter, r *http.Request) {
aH.WriteJSON(w, r, field)
}
// getLogs serves the classic GET /api/v1/logs — the most recent logs over the
// getLogs serves GET /v1/o11y/logs — the most recent logs over the
// query window, newest first. Reads the configured logs table via the reader
// (real Datastore rows), replacing the former {"results":[]} stub. Params:
// limit (default 100, max 1000), timestampStart / timestampEnd (nanosecond
+1 -1
View File
@@ -158,7 +158,7 @@ func TestPrepareQuery(t *testing.T) {
t.Fatal(err)
}
req := httptest.NewRequest(http.MethodPost, "/api/v2/variables/query", &b)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/variables/query", &b)
query, err := prepareQuery(req)
if tc.expectedErr {
@@ -5,7 +5,7 @@
API endpoint:
```
POST /api/v1/messaging-queues/kafka/consumer-lag/consumer-details
POST /v1/o11y/messaging-queues/kafka/consumer-lag/consumer-details
```
Request-Body
@@ -82,7 +82,7 @@ Response in query range `table` format
API endpoint:
```
POST /api/v1/messaging-queues/kafka/consumer-lag/producer-details
POST /v1/o11y/messaging-queues/kafka/consumer-lag/producer-details
```
Request-Body
@@ -150,7 +150,7 @@ Response in query range `table` format
API endpoint:
```
POST /api/v1/messaging-queues/kafka/consumer-lag/network-latency
POST /v1/o11y/messaging-queues/kafka/consumer-lag/network-latency
```
Request-Body
@@ -231,7 +231,7 @@ Response in query range `table` format
### Onboarding APIs
```
/api/v1/messaging-queues/kafka/onboarding/producers
/v1/o11y/messaging-queues/kafka/onboarding/producers
```
```json
@@ -321,7 +321,7 @@ Response in query range `table` format
```
/api/v1/messaging-queues/kafka/onboarding/consumers
/v1/o11y/messaging-queues/kafka/onboarding/consumers
```
```json
@@ -453,7 +453,7 @@ Response in query range `table` format
```
```
/api/v1/messaging-queues/kafka/onboarding/kafka
/v1/o11y/messaging-queues/kafka/onboarding/kafka
```
```json
@@ -523,7 +523,7 @@ Response in query range `table` format
### Partition Latency
```json
/api/v1/messaging-queues/kafka/partition-latency/overview
/v1/o11y/messaging-queues/kafka/partition-latency/overview
```
```json
{
@@ -589,7 +589,7 @@ Response in query range `table` format
---------
```json
/api/v1/messaging-queues/kafka/partition-latency/consumer
/v1/o11y/messaging-queues/kafka/partition-latency/consumer
```
```json
{
@@ -658,7 +658,7 @@ Response in query range `table` format
### Topic throughput
```json
/api/v1/messaging-queues/kafka/topic-throughput/producer
/v1/o11y/messaging-queues/kafka/topic-throughput/producer
```
```json
{
@@ -767,7 +767,7 @@ Response in query range `table` format
### Topic throughput
```json
/api/v1/messaging-queues/kafka/topic-throughput/producer-details
/v1/o11y/messaging-queues/kafka/topic-throughput/producer-details
```
```json
{
@@ -830,7 +830,7 @@ Response in query range `table` format
### Topic throughput
```json
/api/v1/messaging-queues/kafka/topic-throughput/consumer
/v1/o11y/messaging-queues/kafka/topic-throughput/consumer
```
```json
{
@@ -920,7 +920,7 @@ Response in query range `table` format
### Topic throughput
```json
/api/v1/messaging-queues/kafka/topic-throughput/consumer-details
/v1/o11y/messaging-queues/kafka/topic-throughput/consumer-details
```
```json
{
+9 -9
View File
@@ -107,7 +107,7 @@ func TestParseAggregateAttrReques(t *testing.T) {
}
for _, reqCase := range reqCases {
r := httptest.NewRequest("GET", "/api/v3/autocomplete/aggregate_attributes?"+reqCase.queryString, nil)
r := httptest.NewRequest("GET", "/v1/o11y/autocomplete/aggregate_attributes?"+reqCase.queryString, nil)
aggregateAttrRequest, err := parseAggregateAttributeRequest(r)
if reqCase.expectErr {
if err == nil {
@@ -231,7 +231,7 @@ func TestParseFilterAttributeKeyRequest(t *testing.T) {
}
for _, reqCase := range reqCases {
r := httptest.NewRequest("GET", "/api/v3/autocomplete/filter_attributes?"+reqCase.queryString, nil)
r := httptest.NewRequest("GET", "/v1/o11y/autocomplete/filter_attributes?"+reqCase.queryString, nil)
filterAttrRequest, err := parseFilterAttributeKeyRequest(r)
if reqCase.expectErr {
if err == nil {
@@ -328,7 +328,7 @@ func TestParseFilterAttributeValueRequest(t *testing.T) {
}
for _, reqCase := range reqCases {
r := httptest.NewRequest("GET", "/api/v3/autocomplete/filter_attribute_values?"+reqCase.queryString, nil)
r := httptest.NewRequest("GET", "/v1/o11y/autocomplete/filter_attribute_values?"+reqCase.queryString, nil)
filterAttrRequest, err := parseFilterAttributeValueRequest(r)
if reqCase.expectErr {
if err == nil {
@@ -624,7 +624,7 @@ func TestParseQueryRangeParamsCompositeQuery(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
params, apiErr := ParseQueryRangeParams(req)
if tc.expectErr {
@@ -725,7 +725,7 @@ func TestParseQueryRangeParamsExpressions(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
_, apiErr := ParseQueryRangeParams(req)
if tc.expectErr {
@@ -961,7 +961,7 @@ func TestParseQueryRangeParamsDashboardVarsSubstitution(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
parsedQueryRangeParams, apiErr := ParseQueryRangeParams(req)
if tc.expectErr {
@@ -1133,7 +1133,7 @@ func TestParseQueryRangeParamsPromQLVars(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
parsedQueryRangeParams, apiErr := ParseQueryRangeParams(req)
if tc.expectErr {
@@ -1494,7 +1494,7 @@ func TestQueryRangeFormula(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v4/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
_, apiErr := ParseQueryRangeParams(req)
if tc.expectErr {
@@ -1591,7 +1591,7 @@ func TestParseQueryRangeParamsStepIntervalAdjustment(t *testing.T) {
body := &bytes.Buffer{}
err := json.NewEncoder(body).Encode(queryRangeParams)
require.NoError(t, err)
req := httptest.NewRequest(http.MethodPost, "/api/v3/query_range", body)
req := httptest.NewRequest(http.MethodPost, "/v1/o11y/query_range", body)
p, apiErr := ParseQueryRangeParams(req)
if apiErr != nil && apiErr.Err != nil {
+2 -2
View File
@@ -25,7 +25,7 @@ func (aH *APIHandler) mountMisc(router routing.Router, am *middleware.AuthZ) {
router.Get("/v1/o11y/query", am.ViewAccess(aH.queryMetrics))
// dashboards + dashboards/{id} + dashboards/{id}/lock are served by
// o11yapiserver/dashboard.go (formerly /api/v2/dashboards). Highest version wins.
// o11yapiserver/dashboard.go.
router.Post("/v1/o11y/variables/query", am.ViewAccess(aH.queryDashboardVarsV2))
router.Post("/v1/o11y/event", am.ViewAccess(aH.registerEvent))
@@ -34,7 +34,7 @@ func (aH *APIHandler) mountMisc(router routing.Router, am *middleware.AuthZ) {
router.Post("/v1/o11y/dependency_graph", am.ViewAccess(aH.dependencyGraph))
router.Get("/v1/o11y/version", am.OpenAccess(aH.getVersion))
// features is served by o11yapiserver/flagger.go (formerly /api/v2/features).
// features is served by o11yapiserver/flagger.go.
router.Get("/v1/o11y/health", am.OpenAccess(aH.getHealth))
router.Get("/v1/o11y/disks", am.ViewAccess(aH.getDisks))
+1 -3
View File
@@ -8,9 +8,7 @@ import (
// mountRules registers alert-rule evaluation and rule state history. 5 routes.
//
// rules + rules/{id} (GET/POST/PUT/DELETE/PATCH) are NOT here: they are served
// by o11yapiserver/ruler.go (formerly /api/v2/rules). Highest version wins —
// the same handler the version-less /v1/o11y contract already resolved to
// before the flatten.
// by o11yapiserver/ruler.go, the one handler /v1/o11y/rules resolves to.
// ALL of these routes are ALSO declared as typed ops at the module's mount seam
// (rulesalerts.go in the repo root) — the v1 history reads and the legacy
// /testRule — which is what carries them into the composed document, the SDK,
+1 -1
View File
@@ -64,7 +64,7 @@ type Reader interface {
GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error)
// GetRecentLogs reads the most recent logs in [startNano, endNano] (nanosecond
// epochs), newest first, capped at limit, from the configured logs table — the
// real read behind the classic GET /api/v1/logs endpoint (un-stubbed).
// real read behind GET /v1/o11y/logs.
GetRecentLogs(ctx context.Context, startNano, endNano int64, limit int) ([]*v3.Row, error)
// Logs
GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError)
+10 -10
View File
@@ -278,7 +278,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
},
},
{
// ["GET /api/v1/health", "DELETE /api/v1/health"] so result should be ["DELETE /api/v1/health"] although it has lower value
// ["GET /v1/health", "DELETE /v1/health"] so result should be ["DELETE /v1/health"] although it has lower value
name: "test limit with operation asc",
inputResult: []*v3.Result{
{
@@ -287,7 +287,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "frontend",
"operation": "GET /api/v1/health",
"operation": "GET /v1/health",
},
Points: []v3.Point{
{
@@ -303,7 +303,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
},
Points: []v3.Point{
{
@@ -347,7 +347,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
},
Points: []v3.Point{
{
@@ -373,7 +373,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "frontend",
"operation": "GET /api/v1/health",
"operation": "GET /v1/health",
"status_code": "200",
"priority": "P0",
},
@@ -391,7 +391,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
"status_code": "301",
"priority": "P1",
},
@@ -409,7 +409,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
"status_code": "400",
"priority": "P0",
},
@@ -427,7 +427,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
"status_code": "200",
"priority": "P1",
},
@@ -476,7 +476,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "frontend",
"operation": "GET /api/v1/health",
"operation": "GET /v1/health",
"status_code": "200",
"priority": "P0",
},
@@ -494,7 +494,7 @@ func TestApplyLimitOnMetricResult(t *testing.T) {
{
Labels: map[string]string{
"service_name": "route",
"operation": "DELETE /api/v1/health",
"operation": "DELETE /v1/health",
"status_code": "400",
"priority": "P0",
},
+1 -1
View File
@@ -3,7 +3,7 @@ package querybuilder
import "strings"
// A telemetry field key NAME is caller text. It arrives as JSON on
// /api/v5/query_range, and it is replayed out of stored dashboards and alert
// /v1/o11y/query_range, and it is replayed out of stored dashboards and alert
// rules — the rule evaluator builds a QueryRangeRequest and calls the querier
// directly, so a name on that path never passes the request validator at all.
//
+1 -1
View File
@@ -182,7 +182,7 @@ func TestAPI_AnalyzeQueryFilter(t *testing.T) {
}
// Create HTTP request
req := httptest.NewRequestWithContext(context.Background(), http.MethodPost, "/api/v1/query_filter/analyze", bytes.NewBuffer(reqBody))
req := httptest.NewRequestWithContext(context.Background(), http.MethodPost, "/v1/o11y/query_filter/analyze", bytes.NewBuffer(reqBody))
req.Header.Set("Content-Type", "application/json")
// Create response recorder
@@ -15,7 +15,7 @@ import (
"github.com/stretchr/testify/require"
)
// A group-by key name is caller text: it arrives as JSON on /api/v5/query_range
// A group-by key name is caller text: it arrives as JSON on /v1/o11y/query_range
// and is replayed out of stored dashboards and alert rules — the rule evaluator
// builds a QueryRangeRequest and calls the querier directly, so a name on that
// path never meets the request validator at all.
+4 -4
View File
@@ -38,8 +38,8 @@ func TestNewAuditEvent(t *testing.T) {
{
name: "Success_DashboardCreated",
method: http.MethodPost,
path: "/api/v1/dashboards",
route: "/api/v1/dashboards",
path: "/v1/o11y/dashboards",
route: "/v1/o11y/dashboards",
statusCode: http.StatusOK,
action: coretypes.VerbCreate,
category: coretypes.ActionCategoryConfigurationChange,
@@ -52,8 +52,8 @@ func TestNewAuditEvent(t *testing.T) {
{
name: "Failure_ForbiddenDashboardUpdate",
method: http.MethodPut,
path: "/api/v1/dashboards/019b-5678-efgh-9012",
route: "/api/v1/dashboards/{id}",
path: "/v1/o11y/dashboards/019b-5678-efgh-9012",
route: "/v1/o11y/dashboards/{id}",
statusCode: http.StatusForbidden,
action: coretypes.VerbUpdate,
category: coretypes.ActionCategoryConfigurationChange,
+2 -10
View File
@@ -62,22 +62,14 @@ var ManagedRoleToTransactions = map[string][]Transaction{
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorPassword}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindFactorPassword}, WildCardSelectorString)},
// license — admin only.
// Uniform LCRUD shape; actual ee routes are POST /api/v3/licenses (create
// = Activate), PUT /api/v3/licenses (update = Refresh), GET
// /api/v3/licenses/active (read; currently exposed as ViewAccess on the
// route side). delete and list are placeholders for shape parity, no
// route serves them today.
// Uniform LCRUD shape; no route serves licenses in this build.
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbCreate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
{Verb: VerbList, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindLicense}, WildCardSelectorString)},
// subscription — admin only.
// Uniform LCRUD shape; actual ee routes are POST /api/v1/checkout
// (create), POST /api/v1/portal (update — opens Stripe portal), GET
// /api/v1/billing (read — current billing state). delete and list are
// placeholders for shape parity; cancellation flows through Stripe's
// portal, no in-process route serves them.
// Uniform LCRUD shape; no in-process route serves subscriptions.
{Verb: VerbRead, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbUpdate, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
{Verb: VerbDelete, Object: *MustNewObject(ResourceRef{Type: TypeMetaResource, Kind: KindSubscription}, WildCardSelectorString)},
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"github.com/hanzoai/o11y/pkg/errors"
)
// PostableChecks is the request for GET /api/v2/infra_monitoring/checks.
// PostableChecks is the request for GET /v1/o11y/infra_monitoring/checks.
// The single `type` query param selects which infra-monitoring subsection the
// readiness check runs for.
type PostableChecks struct {
@@ -30,7 +30,7 @@ func (req *PostableChecks) Validate() error {
return nil
}
// Checks is the response for GET /api/v2/infra_monitoring/checks.
// Checks is the response for GET /v1/o11y/infra_monitoring/checks.
//
// The three present/missing pairs partition a type's requirements into three
// dimensions — default-enabled metrics, optional metrics, required attributes —
+5 -5
View File
@@ -71,7 +71,7 @@ async function postDashboard(
body: Record<string, unknown>,
): Promise<string> {
const token = await authToken(page);
const res = await page.request.post('/api/v1/dashboards', {
const res = await page.request.post('/v1/o11y/dashboards', {
data: body,
headers: { Authorization: `Bearer ${token}` },
});
@@ -104,7 +104,7 @@ async function loadDashboardFromTemplate(
): Promise<string> {
const id = await postDashboard(page, { title, uploadedGrafana: false });
const token = await authToken(page);
const putRes = await page.request.put(`/api/v1/dashboards/${id}`, {
const putRes = await page.request.put(`/v1/o11y/dashboards/${id}`, {
data: { ...template, title },
headers: { Authorization: `Bearer ${token}` },
});
@@ -272,7 +272,7 @@ export async function awaitVariablesResolved(
await expect
.poll(
async () => {
const res = await page.request.get(`/api/v1/dashboards/${dashboardId}`, {
const res = await page.request.get(`/v1/o11y/dashboards/${dashboardId}`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok()) {
@@ -342,7 +342,7 @@ export async function deleteDashboardViaApi(
token: string,
): Promise<void> {
await request
.delete(`/api/v1/dashboards/${id}`, {
.delete(`/v1/o11y/dashboards/${id}`, {
headers: { Authorization: `Bearer ${token}` },
})
.catch(() => undefined);
@@ -354,7 +354,7 @@ export async function findDashboardIdByTitle(
title: string,
): Promise<string | undefined> {
const token = await authToken(page);
const res = await page.request.get('/api/v1/dashboards', {
const res = await page.request.get('/v1/o11y/dashboards', {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok()) {
@@ -382,7 +382,7 @@ test.describe('Dashboard Detail — Variables', () => {
// `k8s.namespace.name=o11y-<service>` for 8 distinct services.
// O11y's `o11y_metrics.distributed_metadata` table is populated
// naturally by the collector's o11ydatastoremetrics exporter, and
// `/api/v1/fields/values?signal=metrics&name=k8s.namespace.name`
// `/v1/o11y/fields/values?signal=metrics&name=k8s.namespace.name`
// surfaces the values so the Dynamic variable auto-resolves.
await gotoVariablesDashboard(page);
@@ -473,7 +473,7 @@ test.describe('Dashboard Detail — Variables', () => {
// Restore the persisted variable so subsequent serial-mode tests still pass.
const token = await authToken(page);
await page.request.put(`/api/v1/dashboards/${varDashboardId}`, {
await page.request.put(`/v1/o11y/dashboards/${varDashboardId}`, {
data: { ...variablesTemplate, title: 'detail-variables-suite' },
headers: { Authorization: `Bearer ${token}` },
});
+2 -2
View File
@@ -27,7 +27,7 @@ def create_alert_rule(o11y: types.O11y, get_token: Callable[[str, str], str]) ->
def _create_alert_rule(rule_data: dict) -> str:
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/rules"),
o11y.self.host_configs["8080"].get("/v1/o11y/rules"),
json=rule_data,
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
@@ -40,7 +40,7 @@ def create_alert_rule(o11y: types.O11y, get_token: Callable[[str, str], str]) ->
def _delete_alert_rule(rule_id: str):
logger.info("Deleting rule: %s", {"rule_id": rule_id})
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/rules/{rule_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/rules/{rule_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
+15 -15
View File
@@ -31,13 +31,13 @@ USER_VIEWER_NAME = "viewer"
USER_VIEWER_EMAIL = "[email protected]"
USER_VIEWER_PASSWORD = "password123Z$"
USERS_BASE = "/api/v2/users"
USERS_BASE = "/v1/o11y/users"
def _login(o11y: types.O11y, email: str, password: str) -> str:
"""Complete GET /sessions/context + POST /sessions/email_password; return accessToken."""
ctx = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/sessions/context"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/context"),
params={
"email": email,
"ref": f"{o11y.self.host_configs['8080'].base()}",
@@ -48,7 +48,7 @@ def _login(o11y: types.O11y, email: str, password: str) -> str:
org_id = ctx.json()["data"]["orgs"][0]["id"]
login = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/sessions/email_password"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/email_password"),
json={"email": email, "password": password, "orgId": org_id},
timeout=5,
)
@@ -60,7 +60,7 @@ def _login(o11y: types.O11y, email: str, password: str) -> str:
def create_user_admin(o11y: types.O11y, request: pytest.FixtureRequest, pytestconfig: pytest.Config) -> types.Operation:
def create() -> None:
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/register"),
o11y.self.host_configs["8080"].get("/v1/o11y/register"),
json={
"name": USER_ADMIN_NAME,
"orgName": "",
@@ -95,7 +95,7 @@ def create_user_admin(o11y: types.O11y, request: pytest.FixtureRequest, pytestco
def get_session_context(o11y: types.O11y) -> Callable[[str, str], str]:
def _get_session_context(email: str) -> str:
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/sessions/context"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/context"),
params={
"email": email,
"ref": f"{o11y.self.host_configs['8080'].base()}",
@@ -113,7 +113,7 @@ def get_session_context(o11y: types.O11y) -> Callable[[str, str], str]:
def get_token(o11y: types.O11y) -> Callable[[str, str], str]:
def _get_token(email: str, password: str) -> str:
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/sessions/context"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/context"),
params={
"email": email,
"ref": f"{o11y.self.host_configs['8080'].base()}",
@@ -125,7 +125,7 @@ def get_token(o11y: types.O11y) -> Callable[[str, str], str]:
org_id = response.json()["data"]["orgs"][0]["id"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/sessions/email_password"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/email_password"),
json={
"email": email,
"password": password,
@@ -144,7 +144,7 @@ def get_token(o11y: types.O11y) -> Callable[[str, str], str]:
def get_tokens(o11y: types.O11y) -> Callable[[str, str], tuple[str, str]]:
def _get_tokens(email: str, password: str) -> str:
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/sessions/context"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/context"),
params={
"email": email,
"ref": f"{o11y.self.host_configs['8080'].base()}",
@@ -156,7 +156,7 @@ def get_tokens(o11y: types.O11y) -> Callable[[str, str], tuple[str, str]]:
org_id = response.json()["data"]["orgs"][0]["id"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/sessions/email_password"),
o11y.self.host_configs["8080"].get("/v1/o11y/sessions/email_password"),
json={
"email": email,
"password": password,
@@ -180,7 +180,7 @@ def apply_license(
request: pytest.FixtureRequest,
pytestconfig: pytest.Config,
) -> types.Operation:
"""Stub Zeus license-lookup, then POST /api/v3/licenses so the BE flips
"""Stub Zeus license-lookup, then POST /v1/o11y/licenses so the BE flips
to ENTERPRISE. Package-scoped so an e2e bootstrap can pull it in and
every spec inherits the licensed state."""
@@ -220,7 +220,7 @@ def apply_license(
# 202 = applied, 409 = already applied. Retry transient failures —
# the BE occasionally 5xxs right after startup before the license
# sync goroutine is ready.
license_url = o11y.self.host_configs["8080"].get("/api/v3/licenses")
license_url = o11y.self.host_configs["8080"].get("/v1/o11y/licenses")
auth_header = {"Authorization": f"Bearer {access_token}"}
for attempt in range(10):
resp = requests.post(
@@ -239,7 +239,7 @@ def apply_license(
# redirects first-time admins to a questionnaire. Mark the preference
# complete so specs can navigate directly to the feature under test.
pref_resp = requests.put(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences/org_onboarding"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences/org_onboarding"),
json={"value": True},
headers=auth_header,
timeout=5,
@@ -308,7 +308,7 @@ def add_license(
access_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
url=o11y.self.host_configs["8080"].get("/api/v3/licenses"),
url=o11y.self.host_configs["8080"].get("/v1/o11y/licenses"),
json={"key": "secret-key"},
headers={"Authorization": "Bearer " + access_token},
timeout=5,
@@ -338,7 +338,7 @@ def create_active_user(
) -> str:
"""Invite a user and activate via resetPassword. Returns user ID."""
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json={"email": email, "role": role, "name": name},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
@@ -347,7 +347,7 @@ def create_active_user(
invited_user = response.json()["data"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/resetPassword"),
o11y.self.host_configs["8080"].get("/v1/o11y/resetPassword"),
json={"password": password, "token": invited_user["token"]},
timeout=5,
)
+6 -6
View File
@@ -31,7 +31,7 @@ def deprecated_create_cloud_integration_account(
admin_token: str,
cloud_provider: str = "aws",
) -> dict:
endpoint = f"/api/v1/cloud-integrations/{cloud_provider}/accounts/generate-connection-url"
endpoint = f"/v1/o11y/cloud-integrations/{cloud_provider}/accounts/generate-connection-url"
request_payload = {
"account_config": {"regions": ["us-east-1"]},
@@ -68,7 +68,7 @@ def deprecated_create_cloud_integration_account(
try:
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
for account_id, cloud_provider in created_accounts:
disconnect_endpoint = f"/api/v1/cloud-integrations/{cloud_provider}/accounts/{account_id}/disconnect"
disconnect_endpoint = f"/v1/o11y/cloud-integrations/{cloud_provider}/accounts/{account_id}/disconnect"
r = requests.post(
o11y.self.host_configs["8080"].get(disconnect_endpoint),
headers={"Authorization": f"Bearer {admin_token}"},
@@ -101,7 +101,7 @@ def create_cloud_integration_account(
if regions is None:
regions = ["us-east-1"]
endpoint = f"/api/v1/cloud_integrations/{cloud_provider}/accounts"
endpoint = f"/v1/o11y/cloud_integrations/{cloud_provider}/accounts"
request_payload = {
"config": {
@@ -139,7 +139,7 @@ def create_cloud_integration_account(
try:
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
for account_id, cloud_provider in created_accounts:
delete_endpoint = f"/api/v1/cloud_integrations/{cloud_provider}/accounts/{account_id}"
delete_endpoint = f"/v1/o11y/cloud_integrations/{cloud_provider}/accounts/{account_id}"
r = requests.delete(
o11y.self.host_configs["8080"].get(delete_endpoint),
headers={"Authorization": f"Bearer {admin_token}"},
@@ -163,7 +163,7 @@ def deprecated_simulate_agent_checkin(
account_id: str,
cloud_account_id: str,
) -> requests.Response:
endpoint = f"/api/v1/cloud-integrations/{cloud_provider}/agent-check-in"
endpoint = f"/v1/o11y/cloud-integrations/{cloud_provider}/agent-check-in"
checkin_payload = {
"account_id": account_id,
@@ -264,7 +264,7 @@ def simulate_agent_checkin(
cloud_account_id: str,
data: dict | None = None,
) -> requests.Response:
endpoint = f"/api/v1/cloud_integrations/{cloud_provider}/accounts/check_in"
endpoint = f"/v1/o11y/cloud_integrations/{cloud_provider}/accounts/check_in"
checkin_payload = {
"cloudIntegrationId": account_id,
+3 -3
View File
@@ -621,7 +621,7 @@ def _ensure_groups_client_scope(client: KeycloakAdmin) -> None:
def get_oidc_domain(o11y: types.O11y, admin_token: str) -> dict:
"""Helper to get the OIDC domain."""
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -634,7 +634,7 @@ def get_oidc_domain(o11y: types.O11y, admin_token: str) -> dict:
def get_user_by_email(o11y: types.O11y, admin_token: str, email: str) -> dict:
"""Helper to get a user by email."""
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user"),
o11y.self.host_configs["8080"].get("/v1/o11y/user"),
timeout=2,
headers={"Authorization": f"Bearer {admin_token}"},
)
@@ -664,7 +664,7 @@ def perform_oidc_login(
def get_saml_domain(o11y: types.O11y, admin_token: str) -> dict:
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
+2 -2
View File
@@ -379,7 +379,7 @@ def create_json_index(
) -> Generator[Callable[[str, list[dict[str, Any]]], None]]:
"""
Create ClickHouse data-skipping indexes on body_v2 JSON sub-columns via
POST /api/v1/logs/promote_paths.
POST /v1/o11y/logs/promote_paths.
**Must be called BEFORE insert_logs** so that newly inserted data parts are
covered by the index and the QB uses the indexed condition path.
@@ -416,7 +416,7 @@ def create_json_index(
def _create_json_body_index(token: str, paths: list[dict[str, Any]]) -> None:
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/promote_paths"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/promote_paths"),
headers={"authorization": f"Bearer {token}"},
json=paths,
timeout=30,
+1 -1
View File
@@ -555,7 +555,7 @@ def materialize_log_field(
field_type: str,
) -> None:
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/fields"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/fields"),
headers={"authorization": f"Bearer {token}"},
json={
"name": name,
+6 -6
View File
@@ -249,9 +249,9 @@ class MetricsDataGenerator:
services = ["api", "web", "auth"]
if endpoints is None:
endpoints = [
"/api/v1/users",
"/api/v1/orders",
"/api/v1/products",
"/v1/users",
"/v1/orders",
"/v1/products",
"/health",
"/metrics",
]
@@ -304,9 +304,9 @@ class MetricsDataGenerator:
services = ["api", "web", "auth"]
if endpoints is None:
endpoints = [
"/api/v1/users",
"/api/v1/orders",
"/api/v1/products",
"/v1/users",
"/v1/orders",
"/v1/products",
"/health",
"/metrics",
]
+1 -1
View File
@@ -83,7 +83,7 @@ def create_webhook_notification_channel(
send_resolved: bool = True,
) -> str:
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/channels"),
o11y.self.host_configs["8080"].get("/v1/o11y/channels"),
json={
"name": channel_name,
"webhook_configs": [
+1 -1
View File
@@ -110,7 +110,7 @@ def create_o11y(
for attempt in range(10):
try:
response = requests.get(
f"http://{container.get_container_host_ip()}:{container.get_exposed_port(8080)}/api/v2/healthz",
f"http://{container.get_container_host_ip()}:{container.get_exposed_port(8080)}/v1/o11y/healthz",
timeout=2,
)
if response.status_code == HTTPStatus.OK:
+1 -1
View File
@@ -182,7 +182,7 @@ def make_query_request(
payload["variables"] = variables
return requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=timeout,
headers={"authorization": f"Bearer {token}"},
json=payload,
+2 -2
View File
@@ -9,7 +9,7 @@ from fixtures.logger import setup_logger
logger = setup_logger(__name__)
ROLES_BASE = "/api/v1/roles"
ROLES_BASE = "/v1/o11y/roles"
def find_role_by_name(o11y: types.O11y, token: str, name: str) -> str:
@@ -55,7 +55,7 @@ def patch_role_objects(
additions=None,
deletions=None,
) -> None:
"""PATCH /api/v1/roles/{id}/relations/{relation}/objects."""
"""PATCH /v1/o11y/roles/{id}/relations/{relation}/objects."""
body = {}
if additions is not None:
body["additions"] = additions
+1 -1
View File
@@ -10,7 +10,7 @@ from fixtures.role import ROLES_BASE, find_role_by_name # noqa: F401 — re-exp
logger = setup_logger(__name__)
SERVICE_ACCOUNT_BASE = "/api/v1/service_accounts"
SERVICE_ACCOUNT_BASE = "/v1/o11y/service_accounts"
def create_service_account(o11y: types.O11y, token: str, name: str, role: str = "o11y-viewer") -> str:
+2 -2
View File
@@ -10,10 +10,10 @@ logger = logging.getLogger(__name__)
def test_setup(o11y: types.O11y) -> None:
response = requests.get(o11y.self.host_configs["8080"].get("/api/v1/version"), timeout=2)
response = requests.get(o11y.self.host_configs["8080"].get("/v1/o11y/version"), timeout=2)
assert response.status_code == HTTPStatus.OK
healthz = requests.get(o11y.self.host_configs["8080"].get("/api/v2/healthz"), timeout=2)
healthz = requests.get(o11y.self.host_configs["8080"].get("/v1/o11y/healthz"), timeout=2)
logger.info("healthz response: %s", healthz.json())
assert healthz.status_code == HTTPStatus.OK
@@ -65,7 +65,7 @@ def test_webhook_notification_channel(
# Call test API for the notification channel
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
url=o11y.self.host_configs["8080"].get("/api/v1/testChannel"),
url=o11y.self.host_configs["8080"].get("/v1/o11y/testChannel"),
json={
"name": notification_channel_name,
"webhook_configs": [
@@ -16,7 +16,7 @@ def test_create_and_get_domain(
# Get domains which should be an empty list
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -28,7 +28,7 @@ def test_create_and_get_domain(
# Create a domain with google auth config
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "domain-google.integration.test",
"config": {
@@ -49,7 +49,7 @@ def test_create_and_get_domain(
# Create a domain with saml config
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "domain-saml.integration.test",
"config": {
@@ -70,7 +70,7 @@ def test_create_and_get_domain(
# List the domains
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -98,7 +98,7 @@ def test_create_invalid(
# Create a domain with type saml and body for oidc, this should fail because oidcConfig is not allowed for saml
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "domain.integration.test",
"config": {
@@ -119,7 +119,7 @@ def test_create_invalid(
# Create a domain with invalid name
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "$%^invalid",
"config": {
@@ -140,7 +140,7 @@ def test_create_invalid(
# Create a domain with no name
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"config": {
"ssoEnabled": True,
@@ -160,7 +160,7 @@ def test_create_invalid(
# Create a domain with no config
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "domain.integration.test",
},
@@ -181,7 +181,7 @@ def test_create_invalid_role_mapping(
# Create domain with invalid defaultRole
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "invalid-role-test.integration.test",
"config": {
@@ -205,7 +205,7 @@ def test_create_invalid_role_mapping(
# Create domain with invalid role in groupMappings
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "invalid-group-role.integration.test",
"config": {
@@ -232,7 +232,7 @@ def test_create_invalid_role_mapping(
# Valid role mapping should succeed
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "valid-role-mapping.integration.test",
"config": {
@@ -41,7 +41,7 @@ def test_create_auth_domain(
get_token: Callable[[str, str], str],
) -> None:
# Create a saml client in the idp.
create_saml_client("saml.integration.test", "/api/v1/complete/saml")
create_saml_client("saml.integration.test", "/v1/o11y/complete/saml")
# Get the saml settings from keycloak.
settings = get_saml_settings()
@@ -50,7 +50,7 @@ def test_create_auth_domain(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "saml.integration.test",
"config": {
@@ -71,7 +71,7 @@ def test_create_auth_domain(
# Get the domains from o11y
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -174,7 +174,7 @@ def test_saml_update_domain_with_group_mappings(
# update the existing saml domain to have role mappings also
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/domains/{domain['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/domains/{domain['id']}"),
json={
"config": {
"ssoEnabled": True,
@@ -338,7 +338,7 @@ def test_saml_update_domain_with_use_role_claim(
settings = get_saml_settings()
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/domains/{domain['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/domains/{domain['id']}"),
json={
"config": {
"ssoEnabled": True,
@@ -520,7 +520,7 @@ def test_saml_sso_login_activates_pending_invite_user(
# Invite user as ADMIN
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json={"email": email, "role": "ADMIN", "name": "SAML SSO Pending User"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -559,7 +559,7 @@ def test_saml_sso_deleted_user_gets_new_user_on_login(
# --- Step 1: Invite and activate via password reset ---
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json={"email": email, "role": "EDITOR", "name": "SAML SSO Lifecycle User"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -569,7 +569,7 @@ def test_saml_sso_deleted_user_gets_new_user_on_login(
reset_token = response.json()["data"]["token"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/resetPassword"),
o11y.self.host_configs["8080"].get("/v1/o11y/resetPassword"),
json={"password": "password123Z$", "token": reset_token},
timeout=2,
)
@@ -577,7 +577,7 @@ def test_saml_sso_deleted_user_gets_new_user_on_login(
# --- Step 2: Soft delete via DB using API
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/user/{user_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/user/{user_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -600,7 +600,7 @@ def test_saml_sso_deleted_user_gets_new_user_on_login(
# Verify a NEW active user was auto-provisioned via SSO
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users"),
o11y.self.host_configs["8080"].get("/v1/o11y/users"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -614,7 +614,7 @@ def test_saml_sso_deleted_user_gets_new_user_on_login(
assert new_user["status"] == "active"
# Fetch full user with roles to check the assigned role
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{new_user['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{new_user['id']}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -45,7 +45,7 @@ def test_create_auth_domain(
"""
client_id = f"oidc.integration.test.{o11y.self.host_configs['8080'].address}:{o11y.self.host_configs['8080'].port}"
# Create a saml client in the idp.
create_oidc_client(client_id, "/api/v1/complete/oidc")
create_oidc_client(client_id, "/v1/o11y/complete/oidc")
# Get the saml settings from keycloak.
settings = get_oidc_settings(client_id)
@@ -54,7 +54,7 @@ def test_create_auth_domain(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/domains"),
o11y.self.host_configs["8080"].get("/v1/o11y/domains"),
json={
"name": "oidc.integration.test",
"config": {
@@ -130,7 +130,7 @@ def test_oidc_update_domain_with_group_mappings(
settings = get_oidc_settings(client_id)
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/domains/{domain['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/domains/{domain['id']}"),
json={
"config": {
"ssoEnabled": True,
@@ -299,7 +299,7 @@ def test_oidc_update_domain_with_use_role_claim(
settings = get_oidc_settings(client_id)
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/domains/{domain['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/domains/{domain['id']}"),
json={
"config": {
"ssoEnabled": True,
@@ -487,7 +487,7 @@ def test_oidc_sso_login_activates_pending_invite_user(
# Invite user as ADMIN
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json={"email": email, "role": "ADMIN", "name": "OIDC SSO Pending User"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -17,7 +17,7 @@ from fixtures.logger import setup_logger
logger = setup_logger(__name__)
CLOUD_PROVIDER = "aws"
CREDENTIALS_ENDPOINT = f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/credentials"
CREDENTIALS_ENDPOINT = f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/credentials"
def test_apply_license(
@@ -143,7 +143,7 @@ def test_get_credentials_unsupported_provider(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/cloud_integrations/gcp/credentials"),
o11y.self.host_configs["8080"].get("/v1/o11y/cloud_integrations/gcp/credentials"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -57,7 +57,7 @@ def test_create_account_unsupported_provider(
"""Test that creating an account with an unsupported cloud provider returns 400."""
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
cloud_provider = "gcp"
endpoint = f"/api/v1/cloud_integrations/{cloud_provider}/accounts"
endpoint = f"/v1/o11y/cloud_integrations/{cloud_provider}/accounts"
response = requests.post(
o11y.self.host_configs["8080"].get(endpoint),
@@ -33,7 +33,7 @@ def test_list_accounts_empty(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -63,7 +63,7 @@ def test_list_accounts_after_checkin(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -92,7 +92,7 @@ def test_get_account(
account_id = account["id"]
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -117,7 +117,7 @@ def test_get_account_not_found(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -143,7 +143,7 @@ def test_update_account(
updated_regions = ["us-east-1", "us-west-2", "eu-west-1"]
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"regions": updated_regions}}},
timeout=10,
@@ -152,7 +152,7 @@ def test_update_account(
assert response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204, got {response.status_code}"
get_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -185,7 +185,7 @@ def test_update_account_after_checkin_preserves_connected_status(
# 3. Verify the account appears in the connected list
list_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -197,7 +197,7 @@ def test_update_account_after_checkin_preserves_connected_status(
# 4. Update account config
updated_regions = ["us-east-1", "us-west-2"]
update_response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"regions": updated_regions}}},
timeout=10,
@@ -206,7 +206,7 @@ def test_update_account_after_checkin_preserves_connected_status(
# 5. Verify the account still appears in the connected list with correct fields
list_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -236,7 +236,7 @@ def test_disconnect_account(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -244,7 +244,7 @@ def test_disconnect_account(
assert response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204, got {response.status_code}"
list_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -261,7 +261,7 @@ def test_disconnect_account_idempotent(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -35,7 +35,7 @@ def test_list_services_without_account(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -70,7 +70,7 @@ def test_list_services_with_account(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -95,7 +95,7 @@ def test_get_service_details_without_account(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -128,7 +128,7 @@ def test_get_service_details_with_account(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -149,7 +149,7 @@ def test_get_service_not_found(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/non-existent-service"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/non-existent-service"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -173,7 +173,7 @@ def test_update_service_config(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
put_response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"metrics": {"enabled": True}, "logs": {"enabled": True}}}},
timeout=10,
@@ -182,7 +182,7 @@ def test_update_service_config(
assert put_response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204, got {put_response.status_code}: {put_response.text}"
get_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -211,7 +211,7 @@ def test_update_service_config_disable(
checkin = simulate_agent_checkin(o11y, admin_token, CLOUD_PROVIDER, account_id, str(uuid.uuid4()))
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
endpoint = o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}")
endpoint = o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}")
# Enable
r = requests.put(
@@ -232,7 +232,7 @@ def test_update_service_config_disable(
assert r.status_code == HTTPStatus.NO_CONTENT, f"Disable failed: {r.status_code}: {r.text}"
get_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -253,7 +253,7 @@ def test_update_service_account_not_found(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}/services/{SERVICE_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{uuid.uuid4()}/services/{SERVICE_ID}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"metrics": {"enabled": True}}}},
timeout=10,
@@ -271,7 +271,7 @@ def test_list_services_unsupported_provider(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/cloud_integrations/gcp/services"),
o11y.self.host_configs["8080"].get("/v1/o11y/cloud_integrations/gcp/services"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -295,14 +295,14 @@ def test_list_services_account_removed(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
delete_response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
assert delete_response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204 on delete, got {delete_response.status_code}"
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -326,14 +326,14 @@ def test_get_service_details_account_removed(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
delete_response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
assert delete_response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204 on delete, got {delete_response.status_code}"
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -357,14 +357,14 @@ def test_update_service_account_removed(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
delete_response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
assert delete_response.status_code == HTTPStatus.NO_CONTENT, f"Expected 204 on delete, got {delete_response.status_code}"
response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"metrics": {"enabled": True}}}},
timeout=10,
@@ -389,7 +389,7 @@ def test_enable_metrics_provisions_dashboards(
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
put_response = requests.put(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"config": {"aws": {"metrics": {"enabled": True}, "logs": {"enabled": False}}}},
timeout=10,
@@ -398,7 +398,7 @@ def test_enable_metrics_provisions_dashboards(
# Assertion 1: GetService returns provisioned dashboard UUIDs
get_svc_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -450,7 +450,7 @@ def test_disable_metrics_deprovisions_dashboards(
checkin = simulate_agent_checkin(o11y, admin_token, CLOUD_PROVIDER, account_id, str(uuid.uuid4()))
assert checkin.status_code == HTTPStatus.OK, f"Check-in failed: {checkin.text}"
endpoint = o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}")
endpoint = o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/accounts/{account_id}/services/{SERVICE_ID}")
# Enable metrics to provision dashboards first
enable_response = requests.put(
@@ -463,7 +463,7 @@ def test_disable_metrics_deprovisions_dashboards(
# Capture the provisioned dashboard IDs before disabling
get_svc_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -482,7 +482,7 @@ def test_disable_metrics_deprovisions_dashboards(
# Assertion 1: GetService no longer returns UUID dashboard IDs
get_svc_after = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/cloud_integrations/{CLOUD_PROVIDER}/services/{SERVICE_ID}?cloud_integration_id={account_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -497,7 +497,7 @@ def test_disable_metrics_deprovisions_dashboards(
# Assertion 2: Dashboards listing API no longer contains the provisioned dashboard IDs
list_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=10,
)
@@ -16,7 +16,7 @@ def test_create_and_delete_dashboard_without_license(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={"title": "Sample Title", "uploadedGrafana": False, "version": "v5"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -28,7 +28,7 @@ def test_create_and_delete_dashboard_without_license(
dashboard_id = data["id"]
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -56,7 +56,7 @@ def test_create_and_delete_dashboard_with_license(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={"title": "Sample Title", "uploadedGrafana": False, "version": "v5"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -68,7 +68,7 @@ def test_create_and_delete_dashboard_with_license(
dashboard_id = data["id"]
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -32,7 +32,7 @@ def test_create_and_get_public_dashboard(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={"title": "Sample Title", "uploadedGrafana": False, "version": "v5"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -44,7 +44,7 @@ def test_create_and_get_public_dashboard(
dashboard_id = data["id"]
response = requests.post(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}/public"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}/public"),
json={
"timeRangeEnabled": True,
"defaultTimeRange": "10s",
@@ -57,7 +57,7 @@ def test_create_and_get_public_dashboard(
assert "id" in response.json()["data"]
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}/public"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}/public"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -151,7 +151,7 @@ def test_public_dashboard_widget_query_range(
],
}
create_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json=dashboard_req,
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -162,7 +162,7 @@ def test_public_dashboard_widget_query_range(
# create public dashboard
response = requests.post(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}/public"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}/public"),
json={
"timeRangeEnabled": False,
"defaultTimeRange": "10m",
@@ -175,7 +175,7 @@ def test_public_dashboard_widget_query_range(
assert "id" in response.json()["data"]
response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/dashboards/{dashboard_id}/public"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/dashboards/{dashboard_id}/public"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -186,20 +186,20 @@ def test_public_dashboard_widget_query_range(
public_dashboard_id = public_path.split("/public/dashboard/")[-1]
resp = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/public/dashboards/{public_dashboard_id}/widgets/0/query_range"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/public/dashboards/{public_dashboard_id}/widgets/0/query_range"),
timeout=2,
)
assert resp.status_code == HTTPStatus.OK
assert resp.json().get("status") == "success"
resp = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/public/dashboards/{public_dashboard_id}/widgets/-1/query_range"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/public/dashboards/{public_dashboard_id}/widgets/-1/query_range"),
timeout=2,
)
assert resp.status_code == HTTPStatus.BAD_REQUEST
resp = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/public/dashboards/{public_dashboard_id}/widgets/1/query_range"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/public/dashboards/{public_dashboard_id}/widgets/1/query_range"),
timeout=2,
)
assert resp.status_code == HTTPStatus.BAD_REQUEST
@@ -218,7 +218,7 @@ def test_anonymous_role_has_public_dashboard_permission(
# Get the roles to find the org_id
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -44,7 +44,7 @@ def test_create_editor_user(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
invite_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json={"email": GATEWAY_APIS_EDITOR_EMAIL, "role": "EDITOR"},
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
@@ -53,7 +53,7 @@ def test_create_editor_user(
reset_token = invite_response.json()["data"]["token"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/resetPassword"),
o11y.self.host_configs["8080"].get("/v1/o11y/resetPassword"),
json={"password": GATEWAY_APIS_EDITOR_PASSWORD, "token": reset_token},
timeout=5,
)
@@ -71,7 +71,7 @@ def test_create_ingestion_key(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""POST /api/v2/gateway/ingestion_keys creates a key via the gateway."""
"""POST /v1/o11y/gateway/ingestion_keys creates a key via the gateway."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
make_http_mocks(
@@ -99,7 +99,7 @@ def test_create_ingestion_key(
)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/gateway/ingestion_keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/gateway/ingestion_keys"),
json={
"name": "my-test-key",
"tags": ["env:test", "team:platform"],
@@ -128,7 +128,7 @@ def test_get_ingestion_keys(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""GET /api/v2/gateway/ingestion_keys lists keys via the gateway."""
"""GET /v1/o11y/gateway/ingestion_keys lists keys via the gateway."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
# Default page=1, per_page=10 → gateway gets ?page=1&per_page=10
@@ -171,7 +171,7 @@ def test_get_ingestion_keys(
)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/gateway/ingestion_keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/gateway/ingestion_keys"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -191,7 +191,7 @@ def test_get_ingestion_keys_custom_pagination(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""GET /api/v2/gateway/ingestion_keys with custom pagination params."""
"""GET /v1/o11y/gateway/ingestion_keys with custom pagination params."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
make_http_mocks(
@@ -221,7 +221,7 @@ def test_get_ingestion_keys_custom_pagination(
)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/gateway/ingestion_keys?page=2&per_page=5"),
o11y.self.host_configs["8080"].get("/v1/o11y/gateway/ingestion_keys?page=2&per_page=5"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -240,7 +240,7 @@ def test_search_ingestion_keys(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""GET /api/v2/gateway/ingestion_keys/search searches keys by name."""
"""GET /v1/o11y/gateway/ingestion_keys/search searches keys by name."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
# name, page, per_page are sorted alphabetically by Go url.Values.Encode()
@@ -283,7 +283,7 @@ def test_search_ingestion_keys(
)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/gateway/ingestion_keys/search?name=my-test"),
o11y.self.host_configs["8080"].get("/v1/o11y/gateway/ingestion_keys/search?name=my-test"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -331,7 +331,7 @@ def test_search_ingestion_keys_empty(
)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/gateway/ingestion_keys/search?name=nonexistent"),
o11y.self.host_configs["8080"].get("/v1/o11y/gateway/ingestion_keys/search?name=nonexistent"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -349,7 +349,7 @@ def test_update_ingestion_key(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""PATCH /api/v2/gateway/ingestion_keys/{keyId} updates a key via the gateway."""
"""PATCH /v1/o11y/gateway/ingestion_keys/{keyId} updates a key via the gateway."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
gateway_url = f"/v1/workspaces/me/keys/{TEST_KEY_ID}"
@@ -370,7 +370,7 @@ def test_update_ingestion_key(
)
response = requests.patch(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/{TEST_KEY_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/{TEST_KEY_ID}"),
json={
"name": "renamed-key",
"tags": ["env:prod"],
@@ -395,7 +395,7 @@ def test_delete_ingestion_key(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""DELETE /api/v2/gateway/ingestion_keys/{keyId} deletes a key via the gateway."""
"""DELETE /v1/o11y/gateway/ingestion_keys/{keyId} deletes a key via the gateway."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
gateway_url = f"/v1/workspaces/me/keys/{TEST_KEY_ID}"
@@ -416,7 +416,7 @@ def test_delete_ingestion_key(
)
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/{TEST_KEY_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/{TEST_KEY_ID}"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -74,7 +74,7 @@ def test_create_ingestion_key_limit_only_size(
)
response = requests.post(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
json={
"signal": "logs",
"config": {"day": {"size": 1000}},
@@ -130,7 +130,7 @@ def test_create_ingestion_key_limit_only_count(
)
response = requests.post(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
json={
"signal": "traces",
"config": {"day": {"count": 500}},
@@ -183,7 +183,7 @@ def test_create_ingestion_key_limit_both_size_and_count(
)
response = requests.post(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/{TEST_KEY_ID}/limits"),
json={
"signal": "metrics",
"config": {
@@ -240,7 +240,7 @@ def test_update_ingestion_key_limit_only_size(
)
response = requests.patch(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
json={
"config": {"day": {"size": 2000}},
"tags": ["test"],
@@ -286,7 +286,7 @@ def test_update_ingestion_key_limit_only_count(
)
response = requests.patch(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
json={
"config": {"day": {"count": 750}},
"tags": ["test"],
@@ -331,7 +331,7 @@ def test_update_ingestion_key_limit_both_size_and_count(
)
response = requests.patch(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
json={
"config": {"day": {"size": 1000, "count": 500}},
"tags": ["test"],
@@ -360,7 +360,7 @@ def test_delete_ingestion_key_limit(
make_http_mocks: Callable[[types.TestContainerDocker, list], None],
get_token: Callable[[str, str], str],
) -> None:
"""DELETE /api/v2/gateway/ingestion_keys/limits/{limitId} deletes a limit."""
"""DELETE /v1/o11y/gateway/ingestion_keys/limits/{limitId} deletes a limit."""
editor_token = get_token(GATEWAY_APIS_EDITOR_EMAIL, GATEWAY_APIS_EDITOR_PASSWORD)
gateway_url = f"/v1/workspaces/me/limits/{TEST_LIMIT_ID}"
@@ -381,7 +381,7 @@ def test_delete_ingestion_key_limit(
)
response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v2/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/gateway/ingestion_keys/limits/{TEST_LIMIT_ID}"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=10,
)
@@ -72,7 +72,7 @@ def test_create_logs_pipeline_success(
}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -158,7 +158,7 @@ def test_list_logs_pipelines_success(
}
create_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -171,7 +171,7 @@ def test_list_logs_pipelines_success(
# List pipelines
list_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines/latest"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines/latest"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -248,7 +248,7 @@ def test_list_logs_pipelines_by_version(
}
v1_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -304,7 +304,7 @@ def test_list_logs_pipelines_by_version(
}
v2_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -321,7 +321,7 @@ def test_list_logs_pipelines_by_version(
# List by version 1
v1_list_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/logs/pipelines/{v1_version}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/logs/pipelines/{v1_version}"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -337,7 +337,7 @@ def test_list_logs_pipelines_by_version(
# List by version 2
v2_list_response = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v1/logs/pipelines/{v2_version}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/logs/pipelines/{v2_version}"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -423,7 +423,7 @@ def test_preview_logs_pipelines_success(
}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines/preview"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines/preview"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -535,7 +535,7 @@ def test_create_multiple_pipelines_success(
}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -616,7 +616,7 @@ def test_delete_all_pipelines_success(
}
create_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -632,7 +632,7 @@ def test_delete_all_pipelines_success(
delete_payload = {"pipelines": []}
delete_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -651,7 +651,7 @@ def test_delete_all_pipelines_success(
# Verify pipelines are deleted by listing
list_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/logs/pipelines/latest"),
o11y.self.host_configs["8080"].get("/v1/o11y/logs/pipelines/latest"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -18,7 +18,7 @@ def test_get_user_preference(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -36,7 +36,7 @@ def test_get_set_user_preference_by_name(
# preference does not exist
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences/somenonexistentpreference"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences/somenonexistentpreference"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -46,7 +46,7 @@ def test_get_set_user_preference_by_name(
# get preference by name
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences/welcome_checklist_do_later"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences/welcome_checklist_do_later"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -58,7 +58,7 @@ def test_get_set_user_preference_by_name(
# play with welcome_checklist_do_later preference
response = requests.put(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences/welcome_checklist_do_later"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences/welcome_checklist_do_later"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"value": True},
timeout=2,
@@ -68,7 +68,7 @@ def test_get_set_user_preference_by_name(
# get preference by name
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences/welcome_checklist_do_later"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences/welcome_checklist_do_later"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
+5 -5
View File
@@ -18,7 +18,7 @@ def test_get_org_preference(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -36,7 +36,7 @@ def test_get_set_org_preference_by_name(
# preference does not exist
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences/somenonexistentpreference"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences/somenonexistentpreference"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -46,7 +46,7 @@ def test_get_set_org_preference_by_name(
# get preference by name
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences/org_onboarding"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences/org_onboarding"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -58,7 +58,7 @@ def test_get_set_org_preference_by_name(
# play with org_onboarding preference
response = requests.put(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences/org_onboarding"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences/org_onboarding"),
headers={"Authorization": f"Bearer {admin_token}"},
json={"value": True},
timeout=2,
@@ -68,7 +68,7 @@ def test_get_set_org_preference_by_name(
# get preference by name
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/org/preferences/org_onboarding"),
o11y.self.host_configs["8080"].get("/v1/o11y/org/preferences/org_onboarding"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
+29 -29
View File
@@ -94,7 +94,7 @@ def test_logs_list(
# Query Logs for the last 10 seconds and check if the logs are returned in the correct order
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -176,7 +176,7 @@ def test_logs_list(
# Query values of severity_text attribute from the autocomplete API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v3/autocomplete/attribute_values"),
o11y.self.host_configs["8080"].get("/v1/o11y/autocomplete/attribute_values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -202,7 +202,7 @@ def test_logs_list(
# Query values of severity_text attribute from the fields API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -224,7 +224,7 @@ def test_logs_list(
# Query values of code.file attribute from the autocomplete API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v3/autocomplete/attribute_values"),
o11y.self.host_configs["8080"].get("/v1/o11y/autocomplete/attribute_values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -250,7 +250,7 @@ def test_logs_list(
# Query values of code.file attribute from the fields API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -272,7 +272,7 @@ def test_logs_list(
# Query values of code.line attribute from the autocomplete API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v3/autocomplete/attribute_values"),
o11y.self.host_configs["8080"].get("/v1/o11y/autocomplete/attribute_values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -297,7 +297,7 @@ def test_logs_list(
# Query values of code.line attribute from the fields API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -318,7 +318,7 @@ def test_logs_list(
# Query keys from the fields API with context specified in the key
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/keys"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -338,7 +338,7 @@ def test_logs_list(
# Do not treat `metric.` as a context prefix for logs
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/keys"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -357,7 +357,7 @@ def test_logs_list(
# Query values of service.name resource attribute using context-prefixed key
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -378,7 +378,7 @@ def test_logs_list(
# Query values of metric.domain_id (string attribute) and ensure context collision doesn't break it
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -607,7 +607,7 @@ def test_logs_time_series_count(
# count() of all logs for the last 5 minutes
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -674,7 +674,7 @@ def test_logs_time_series_count(
# count() of all logs where code.line = 7 for last 5 minutes
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -742,7 +742,7 @@ def test_logs_time_series_count(
# count() of all logs where service.name = "erlang" OR cloud.account.id = "000" for last 5 minutes
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -803,7 +803,7 @@ def test_logs_time_series_count(
# count() of all logs grouped by host.name for the last 5 minutes
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1035,7 +1035,7 @@ def test_datatype_collision(
# count() of all logs for the where severity_number > '7'
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1076,7 +1076,7 @@ def test_datatype_collision(
# count() of all logs for the where severity_number > '7.0'
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1117,7 +1117,7 @@ def test_datatype_collision(
# Test 2: severity_number comparison with string value
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1159,7 +1159,7 @@ def test_datatype_collision(
# Test 3: http.status_code with numeric value (query contains number, actual value is string "200")
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1201,7 +1201,7 @@ def test_datatype_collision(
# Test 4: http.status_code with string value (query contains string, actual value is numeric 404)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1243,7 +1243,7 @@ def test_datatype_collision(
# Test 5: Edge case - empty string comparison
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1318,7 +1318,7 @@ def test_logs_fill_gaps(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1404,7 +1404,7 @@ def test_logs_fill_gaps_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1505,7 +1505,7 @@ def test_logs_fill_gaps_formula(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1612,7 +1612,7 @@ def test_logs_fill_gaps_formula_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1733,7 +1733,7 @@ def test_logs_fill_zero(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1816,7 +1816,7 @@ def test_logs_fill_zero_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1916,7 +1916,7 @@ def test_logs_fill_zero_formula(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -2024,7 +2024,7 @@ def test_logs_fill_zero_formula_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -90,7 +90,7 @@ def test_logs_json_body_simple_searches(
# Test 1: Search by body.message = "User logged in successfully"
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -131,7 +131,7 @@ def test_logs_json_body_simple_searches(
# Test 2: Search by body.status = 200
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -173,7 +173,7 @@ def test_logs_json_body_simple_searches(
# Test 3: Search by body.active = true
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -215,7 +215,7 @@ def test_logs_json_body_simple_searches(
# Test 4: Search by body.level CONTAINS "error"
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -256,7 +256,7 @@ def test_logs_json_body_simple_searches(
# Test 5: Search by body.code > 100
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -396,7 +396,7 @@ def test_logs_json_body_nested_keys(
# Test 1: Search by body.user.name = "john_doe"
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -438,7 +438,7 @@ def test_logs_json_body_nested_keys(
# Test 2: Search by body.request.secure = true
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -480,7 +480,7 @@ def test_logs_json_body_nested_keys(
# Test 3: Search by body.response.latency = 123.45
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -522,7 +522,7 @@ def test_logs_json_body_nested_keys(
# Test 4: Search by body.response.status.code = 200
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -646,7 +646,7 @@ def test_logs_json_body_array_membership(
# Test 1: Search by has(body.tags[*], "production")
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -688,7 +688,7 @@ def test_logs_json_body_array_membership(
# Test 2: Search by has(body.ids[*], 200)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -730,7 +730,7 @@ def test_logs_json_body_array_membership(
# Test 3: Search by has(body.flags[*], true)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -875,7 +875,7 @@ def test_logs_json_body_listing(
# Test 1: List all logs with JSON bodies
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -915,7 +915,7 @@ def test_logs_json_body_listing(
# Test 2: List logs with pagination (limit=2, offset=0)
# Should return the 1st and 2nd logs (log-5 and log-4) when ordered by timestamp desc
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -958,7 +958,7 @@ def test_logs_json_body_listing(
# Test 3: List logs with pagination (limit=2, offset=2)
# Should return the 3rd and 4th logs (log-3 and log-2) when ordered by timestamp desc
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1000,7 +1000,7 @@ def test_logs_json_body_listing(
# Test 4: List logs with multiple filters combined (AND)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1044,7 +1044,7 @@ def test_logs_json_body_listing(
# Test 5: List logs with OR filter
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1087,7 +1087,7 @@ def test_logs_json_body_listing(
# Test 6: Count logs matching JSON body filters
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={"authorization": f"Bearer {token}"},
json={
+13 -13
View File
@@ -106,7 +106,7 @@ def test_metrics_fill_no_group_by(
_maybe_add_functions(query_spec, fill_mode)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -213,7 +213,7 @@ def test_metrics_fill_with_group_by(
_maybe_add_functions(query_spec, fill_mode)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -316,7 +316,7 @@ def test_metrics_fill_formula(
_maybe_add_formula_functions(formula_spec, fill_mode)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -487,7 +487,7 @@ def test_metrics_fill_formula_with_group_by(
_maybe_add_formula_functions(formula_spec, fill_mode)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -640,7 +640,7 @@ def test_non_existent_metrics_returns_404(
assert get_error_message(response.json()) == "could not find the metric whatevergoennnsgoeshere"
# Verify /api/v1/fields/values filters label values by metricNamespace prefix.
# Verify /v1/o11y/fields/values filters label values by metricNamespace prefix.
# Inserts metrics under ns.a and ns.b, then asserts a specific prefix returns
# only matching values while a common prefix returns both.
def test_metric_namespace_values_filtering(
@@ -671,7 +671,7 @@ def test_metric_namespace_values_filtering(
# Specific prefix: metricNamespace=ns.a should return only svc-a
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -691,7 +691,7 @@ def test_metric_namespace_values_filtering(
# Common prefix: metricNamespace=ns should return both
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -710,7 +710,7 @@ def test_metric_namespace_values_filtering(
assert "svc-b" in values
# Verify /api/v1/fields/values with name=metric_name filters metric names by
# Verify /v1/o11y/fields/values with name=metric_name filters metric names by
# metricNamespace prefix. A specific prefix returns only its metric names;
# a common prefix returns metric names from all matching namespaces.
def test_metric_namespace_metric_name_values_filtering(
@@ -741,7 +741,7 @@ def test_metric_namespace_metric_name_values_filtering(
# Specific prefix: metricNamespace=ns.a should return only ns.a.* metric names
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -761,7 +761,7 @@ def test_metric_namespace_metric_name_values_filtering(
# Common prefix: metricNamespace=ns should return both
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -780,7 +780,7 @@ def test_metric_namespace_metric_name_values_filtering(
assert "ns.b.cpu.utilization" in values
# Verify /api/v1/fields/keys filters attribute keys by metricNamespace prefix.
# Verify /v1/o11y/fields/keys filters attribute keys by metricNamespace prefix.
# Metrics under ns.a and ns.b carry distinct labels; a specific prefix returns
# only its keys while a common prefix returns keys from both namespaces.
def test_metric_namespace_keys_filtering(
@@ -811,7 +811,7 @@ def test_metric_namespace_keys_filtering(
# Specific prefix: metricNamespace=ns.a should return only a_only_label
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/keys"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -830,7 +830,7 @@ def test_metric_namespace_keys_filtering(
# Common prefix: metricNamespace=ns should return both keys
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/keys"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
+14 -14
View File
@@ -153,7 +153,7 @@ def test_traces_list(
# Query all traces for the past 5 minutes
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -328,7 +328,7 @@ def test_traces_list(
# Query root spans for the last 5 minutes and check if the spans are returned in the correct order
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -383,7 +383,7 @@ def test_traces_list(
# Query values of http.request.method attribute from the autocomplete API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v3/autocomplete/attribute_values"),
o11y.self.host_configs["8080"].get("/v1/o11y/autocomplete/attribute_values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -409,7 +409,7 @@ def test_traces_list(
# Query values of http.request.method attribute from the fields API
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -431,7 +431,7 @@ def test_traces_list(
# Query keys from the fields API with context specified in the key
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/keys"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/keys"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -451,7 +451,7 @@ def test_traces_list(
# Query values of service.name resource attribute using context-prefixed key
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=2,
headers={
"authorization": f"Bearer {token}",
@@ -1119,7 +1119,7 @@ def test_traces_fill_gaps(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1215,7 +1215,7 @@ def test_traces_fill_gaps_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1328,7 +1328,7 @@ def test_traces_fill_gaps_formula(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1448,7 +1448,7 @@ def test_traces_fill_gaps_formula_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1576,7 +1576,7 @@ def test_traces_fill_zero(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1672,7 +1672,7 @@ def test_traces_fill_zero_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1786,7 +1786,7 @@ def test_traces_fill_zero_formula(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -1906,7 +1906,7 @@ def test_traces_fill_zero_formula_with_group_by(
end_ms = int(now.timestamp() * 1000)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -93,7 +93,7 @@ def make_scalar_query_request(
lookback_minutes: int = 5,
) -> requests.Response:
return requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -88,7 +88,7 @@ def test_list_meter_metric_names(
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/metrics"),
o11y.self.host_configs["8080"].get("/v1/o11y/metrics"),
params={
"start": start_ms,
"end": end_ms,
@@ -108,7 +108,7 @@ def test_list_meter_metric_names(
assert metric_name in metric_names, f"Expected {metric_name} in metric names, got: {metric_names}"
# Verify /api/v1/fields/values with source=meter filters label values by metricNamespace
# Verify /v1/o11y/fields/values with source=meter filters label values by metricNamespace
# prefix. Inserts meter-source metrics under ns.a and ns.b, then asserts a specific
# prefix returns only matching values while a common prefix returns both.
def test_metric_namespace_meter_values_filtering(
@@ -145,7 +145,7 @@ def test_metric_namespace_meter_values_filtering(
# Specific prefix: metricNamespace=meter.ns.a should return only billing-a
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -166,7 +166,7 @@ def test_metric_namespace_meter_values_filtering(
# Common prefix: metricNamespace=meter.ns should return both
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/fields/values"),
o11y.self.host_configs["8080"].get("/v1/o11y/fields/values"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
params={
@@ -1,6 +1,6 @@
"""
Integration tests for TraceOperatorQuery (builder_trace_operator) through the
/api/v5/query_range endpoint.
/v1/o11y/query_range endpoint.
Covers:
1. Order-by variants (A -> B, A => B) with returnSpansFrom="A".
@@ -417,7 +417,7 @@ def test_trace_operator(
spec["order"] = case["order"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v5/query_range"),
o11y.self.host_configs["8080"].get("/v1/o11y/query_range"),
timeout=5,
headers={"authorization": f"Bearer {token}"},
json={
@@ -25,7 +25,7 @@ def test_export_raw_data_get_not_allowed(
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -115,7 +115,7 @@ def test_export_logs_csv(
# Export logs as CSV (default format)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data"),
json=body,
timeout=30,
headers={
@@ -211,7 +211,7 @@ def test_export_logs_jsonl(
# Export logs as JSONL
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -306,7 +306,7 @@ def test_export_logs_with_filter(
# Export logs with filter
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -377,7 +377,7 @@ def test_export_logs_with_limit(
# Export logs with limit
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=csv"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=csv"),
json=body,
timeout=10,
headers={
@@ -455,7 +455,7 @@ def test_export_logs_with_columns(
# Export logs with specific columns
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=csv"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=csv"),
json=body,
timeout=10,
headers={
@@ -551,7 +551,7 @@ def test_export_logs_with_order_by(
# Export logs with ascending order
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -642,7 +642,7 @@ def test_export_logs_with_complex_filter(
# Export logs with complex filter
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -31,7 +31,7 @@ def test_export_raw_data_get_not_allowed(
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data"),
timeout=10,
headers={
"authorization": f"Bearer {token}",
@@ -152,7 +152,7 @@ def test_export_traces_csv(
# Export traces as CSV
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data"),
json=body,
timeout=30,
headers={
@@ -215,7 +215,7 @@ def test_export_traces_jsonl(
trace_id=http_service_trace_id,
span_id=http_service_span_id,
parent_span_id="",
name="POST /api/test",
name="POST /v1/test",
kind=TracesKind.SPAN_KIND_SERVER,
status_code=TracesStatusCode.STATUS_CODE_OK,
status_message="",
@@ -264,7 +264,7 @@ def test_export_traces_jsonl(
# Export traces as JSONL
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -297,7 +297,7 @@ def test_export_traces_jsonl(
# Verify span names are present
span_names = [obj.get("name") for obj in json_objects]
assert "POST /api/test" in span_names
assert "POST /v1/test" in span_names
assert "queue.process" in span_names
@@ -378,7 +378,7 @@ def test_export_traces_with_filter(
# Export traces with filter
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl"),
json=body,
timeout=10,
headers={
@@ -452,7 +452,7 @@ def test_export_traces_with_limit(
# Export traces with limit
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=csv"),
o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=csv"),
json=body,
timeout=10,
headers={
@@ -508,7 +508,7 @@ def test_export_traces_multiple_queries_rejected(
],
).to_dict()
url = o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl")
url = o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl")
response = requests.post(
url,
json=body,
@@ -635,7 +635,7 @@ def test_export_traces_with_composite_query_trace_operator(
queries=[query_a, query_b, query_c],
).to_dict()
url = o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl")
url = o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl")
response = requests.post(
url,
json=body,
@@ -730,7 +730,7 @@ def test_export_traces_with_select_fields(
],
).to_dict()
url = o11y.self.host_configs["8080"].get("/api/v1/export_raw_data?format=jsonl")
url = o11y.self.host_configs["8080"].get("/v1/o11y/export_raw_data?format=jsonl")
response = requests.post(
url,
json=body,
+4 -4
View File
@@ -20,7 +20,7 @@ def test_managed_roles_create_on_register(
# get the list of all roles.
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -52,7 +52,7 @@ def test_root_user_o11y_admin_assignment(
# Get the user from the v2 /users/me endpoint and extract the id
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -61,7 +61,7 @@ def test_root_user_o11y_admin_assignment(
user_id = user_data["id"]
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -111,7 +111,7 @@ def test_anonymous_user_o11y_anonymous_assignment(
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
+10 -10
View File
@@ -29,7 +29,7 @@ def test_user_invite_accept_role_grant(
"role": "EDITOR",
}
invite_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/invite"),
o11y.self.host_configs["8080"].get("/v1/o11y/invite"),
json=invite_payload,
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
@@ -39,7 +39,7 @@ def test_user_invite_accept_role_grant(
reset_token = invited_user["token"]
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/resetPassword"),
o11y.self.host_configs["8080"].get("/v1/o11y/resetPassword"),
json={"password": USER_EDITOR_PASSWORD, "token": reset_token},
timeout=2,
)
@@ -48,7 +48,7 @@ def test_user_invite_accept_role_grant(
# Login with editor email and password
editor_token = get_token(USER_EDITOR_EMAIL, USER_EDITOR_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=5,
)
@@ -58,14 +58,14 @@ def test_user_invite_accept_role_grant(
# check the forbidden response for admin api for editor user
admin_roles_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=2,
)
assert admin_roles_response.status_code == HTTPStatus.FORBIDDEN
roles_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -104,7 +104,7 @@ def test_user_update_role_grant(
# Get the editor user's id
editor_token = get_token(USER_EDITOR_EMAIL, USER_EDITOR_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=5,
)
@@ -115,7 +115,7 @@ def test_user_update_role_grant(
# Get the role id for viewer
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
roles_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -171,7 +171,7 @@ def test_user_delete_role_revoke(
# login with editor to get the user_id and check if user exists
editor_token = get_token(USER_EDITOR_EMAIL, USER_EDITOR_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"Authorization": f"Bearer {editor_token}"},
timeout=5,
)
@@ -182,7 +182,7 @@ def test_user_delete_role_revoke(
# delete the editor user
admin_token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
delete_response = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v1/user/{editor_id}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/user/{editor_id}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
@@ -190,7 +190,7 @@ def test_user_delete_role_revoke(
# get the role id from roles list
roles_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/roles"),
o11y.self.host_configs["8080"].get("/v1/o11y/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=2,
)
+2 -2
View File
@@ -330,7 +330,7 @@ def test_role_fga_cleanup(
# Remove the custom role from the user first.
resp = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{user['id']}/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -339,7 +339,7 @@ def test_role_fga_cleanup(
custom_entry = next((r for r in roles if r["name"] == ROLE_FGA_CUSTOM_ROLE_NAME), None)
if custom_entry is not None:
resp = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles/{custom_entry['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{user['id']}/roles/{custom_entry['id']}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -13,14 +13,14 @@ def test_root_user_created(o11y: types.O11y) -> None:
"""
The root user service reconciles asynchronously after startup.
Phase 1: Poll /api/v1/version until setupCompleted=true.
Phase 2: Poll /api/v2/users until it returns 200, confirming the root
Phase 1: Poll /v1/o11y/version until setupCompleted=true.
Phase 2: Poll /v1/o11y/users until it returns 200, confirming the root
user actually exists and the impersonation provider works.
"""
# Phase 1: wait for setupCompleted
for attempt in range(15):
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/version"),
o11y.self.host_configs["8080"].get("/v1/o11y/version"),
timeout=2,
)
assert response.status_code == HTTPStatus.OK
@@ -37,13 +37,13 @@ def test_root_user_created(o11y: types.O11y) -> None:
# Phase 2: wait for root user to be fully resolved
for attempt in range(15):
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users"),
o11y.self.host_configs["8080"].get("/v1/o11y/users"),
timeout=2,
)
if response.status_code == HTTPStatus.OK:
return
logger.info(
"Attempt %s: /api/v2/users returned %s, retrying ...",
"Attempt %s: /v1/o11y/users returned %s, retrying ...",
attempt + 1,
response.status_code,
)
@@ -11,11 +11,11 @@ logger = setup_logger(__name__)
def test_global_config_returns_impersonation_enabled(o11y: types.O11y) -> None:
"""
GET /api/v1/global/config without any auth header should return 200
GET /v1/o11y/global/config without any auth header should return 200
and report impersonation as enabled.
"""
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/global/config"),
o11y.self.host_configs["8080"].get("/v1/o11y/global/config"),
timeout=2,
)
@@ -33,7 +33,7 @@ def test_impersonated_user_is_admin(o11y: types.O11y) -> None:
Listing users is an admin-only endpoint.
"""
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users"),
o11y.self.host_configs["8080"].get("/v1/o11y/users"),
timeout=2,
)
@@ -50,7 +50,7 @@ def test_impersonated_user_is_admin(o11y: types.O11y) -> None:
# Verify root user has admin role via v2 detail endpoint
root_detail = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{root_user['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{root_user['id']}"),
timeout=2,
)
assert root_detail.status_code == HTTPStatus.OK
@@ -155,7 +155,7 @@ def test_create_api_key_with_expiry(
# key should work since it hasn't expired
dash_resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -211,7 +211,7 @@ def test_create_api_key_no_expiry(
api_key = response.json()["data"]["key"]
dash_resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -259,7 +259,7 @@ def test_update_api_key_expiry(
# key should still work since the update was rejected
dash_resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -25,7 +25,7 @@ def test_service_account_key_auth_on_dashboards(
_, api_key = create_service_account_with_key(o11y, token, "sa-dashboard-test")
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -38,12 +38,12 @@ def test_service_account_key_forbidden_on_user_me(
create_user_admin: types.Operation, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
):
"""Service account key must not access /api/v2/users/me — it's user-only."""
"""Service account key must not access /v1/o11y/users/me — it's user-only."""
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
_, api_key = create_service_account_with_key(o11y, token, "sa-user-me-test")
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -62,7 +62,7 @@ def test_service_account_key_forbidden_on_user_preferences(
_, api_key = create_service_account_with_key(o11y, token, "sa-pref-test")
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -90,7 +90,7 @@ def test_service_account_role_access_admin(
# EditAccess: create a dashboard
resp = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={
"title": "admin-sa-dash",
"uploadedGrafana": False,
@@ -103,7 +103,7 @@ def test_service_account_role_access_admin(
# ViewAccess: list dashboards
resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -129,7 +129,7 @@ def test_service_account_role_access_editor(
# EditAccess: create a dashboard
resp = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={
"title": "editor-sa-dash",
"uploadedGrafana": False,
@@ -142,7 +142,7 @@ def test_service_account_role_access_editor(
# ViewAccess: list dashboards
resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -168,7 +168,7 @@ def test_service_account_role_access_viewer(
# EditAccess: should be forbidden
resp = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
json={
"title": "viewer-sa-dash",
"uploadedGrafana": False,
@@ -181,7 +181,7 @@ def test_service_account_role_access_viewer(
# ViewAccess: list dashboards
resp = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -199,7 +199,7 @@ def test_service_account_key_deleted_account_rejected(
# verify the key works before deleting
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -210,7 +210,7 @@ def test_service_account_key_deleted_account_rejected(
# now the key should be rejected
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -229,7 +229,7 @@ def test_service_account_key_revoked_key_rejected(
# verify the key works first
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -253,7 +253,7 @@ def test_service_account_key_revoked_key_rejected(
# now the key should be rejected
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/dashboards"),
o11y.self.host_configs["8080"].get("/v1/o11y/dashboards"),
headers={"O11Y-API-KEY": api_key},
timeout=5,
)
@@ -270,7 +270,7 @@ def test_user_token_still_works_on_user_me(
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/users/me"),
o11y.self.host_configs["8080"].get("/v1/o11y/users/me"),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
@@ -289,7 +289,7 @@ def test_user_token_still_works_on_user_preferences(
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/user/preferences"),
o11y.self.host_configs["8080"].get("/v1/o11y/user/preferences"),
headers={"Authorization": f"Bearer {token}"},
timeout=5,
)
@@ -669,7 +669,7 @@ def test_delete_custom_role_cleanup(
# Remove the custom role from the user first — role deletion requires no assignees.
resp = requests.get(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{user['id']}/roles"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
@@ -678,7 +678,7 @@ def test_delete_custom_role_cleanup(
custom_entry = next((r for r in roles if r["name"] == SA_FGA_CUSTOM_ROLE_NAME), None)
if custom_entry is not None:
resp = requests.delete(
o11y.self.host_configs["8080"].get(f"/api/v2/users/{user['id']}/roles/{custom_entry['id']}"),
o11y.self.host_configs["8080"].get(f"/v1/o11y/users/{user['id']}/roles/{custom_entry['id']}"),
headers={"Authorization": f"Bearer {admin_token}"},
timeout=5,
)
+20 -20
View File
@@ -106,7 +106,7 @@ def test_set_ttl_traces_success(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -154,7 +154,7 @@ def test_set_ttl_traces_with_cold_storage(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -214,7 +214,7 @@ def test_set_ttl_metrics_success(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -264,7 +264,7 @@ def test_set_ttl_metrics_with_cold_storage(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -325,7 +325,7 @@ def test_set_ttl_invalid_type(o11y: types.O11y, get_token: Callable[[str, str],
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -355,7 +355,7 @@ def test_set_custom_retention_ttl_basic(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -415,7 +415,7 @@ def test_set_custom_retention_ttl_basic_with_cold_storage(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -481,7 +481,7 @@ def test_set_custom_retention_ttl_basic_fallback(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -543,7 +543,7 @@ def test_set_custom_retention_ttl_basic_101_times(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -591,7 +591,7 @@ def test_set_custom_retention_ttl_with_conditions(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -607,7 +607,7 @@ def test_set_custom_retention_ttl_with_conditions(
]
insert_logs(logs)
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -700,7 +700,7 @@ def test_set_custom_retention_ttl_with_invalid_cold_storage(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -740,7 +740,7 @@ def test_set_custom_retention_ttl_duplicate_conditions(o11y: types.O11y, get_tok
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -773,7 +773,7 @@ def test_set_custom_retention_ttl_invalid_condition(o11y: types.O11y, get_token:
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,
@@ -807,7 +807,7 @@ def test_get_custom_retention_ttl(o11y: types.O11y, get_token: Callable[[str, st
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
set_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=set_payload,
headers=headers,
timeout=30,
@@ -821,7 +821,7 @@ def test_get_custom_retention_ttl(o11y: types.O11y, get_token: Callable[[str, st
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
get_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params={"type": "logs"},
headers=headers,
timeout=30,
@@ -855,7 +855,7 @@ def test_set_ttl_logs_success(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=payload,
headers=headers,
timeout=30,
@@ -893,7 +893,7 @@ def test_get_ttl_traces_success(o11y: types.O11y, get_token: Callable[[str, str]
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
set_response = requests.post(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params=set_payload,
headers=headers,
timeout=30,
@@ -906,7 +906,7 @@ def test_get_ttl_traces_success(o11y: types.O11y, get_token: Callable[[str, str]
# Now get the TTL configuration for traces
get_response = requests.get(
o11y.self.host_configs["8080"].get("/api/v1/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
params={"type": "traces"},
headers=headers,
timeout=30,
@@ -954,7 +954,7 @@ def test_large_ttl_conditions_list(
headers = {"Authorization": f"Bearer {get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)}"}
response = requests.post(
o11y.self.host_configs["8080"].get("/api/v2/settings/ttl"),
o11y.self.host_configs["8080"].get("/v1/o11y/settings/ttl"),
json=payload,
headers=headers,
timeout=30,