Skip to content

Commit 3e4ec5c

Browse files
authored
Merge pull request #714 from camunda/feat/admin-api-complete-surface
feat(admin): implement all missing Admin API operations
2 parents def83e6 + 4758af8 commit 3e4ec5c

4 files changed

Lines changed: 668 additions & 5 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import { AdminApiClient } from '../../admin/index'
2+
import { matrix } from '../../test-support/testTags'
3+
4+
vi.setConfig({ testTimeout: 15_000 })
5+
6+
const saasMatrix = matrix({
7+
include: {
8+
versions: ['8.8', '8.7'],
9+
deployments: ['saas'],
10+
tenancy: ['single-tenant', 'multi-tenant'],
11+
security: ['secured', 'unsecured'],
12+
},
13+
})
14+
15+
describe('AdminApiClient - new operations', () => {
16+
let c: AdminApiClient
17+
let clusterUuid: string
18+
19+
beforeAll(async () => {
20+
c = new AdminApiClient()
21+
const clusters = await c.getClusters()
22+
expect(clusters.length).toBeGreaterThan(0)
23+
clusterUuid = clusters[0].uuid
24+
})
25+
26+
describe('Meta', () => {
27+
test.runIf(saasMatrix)('getIpRanges', async () => {
28+
const res = await c.getIpRanges()
29+
expect(res).toBeTruthy()
30+
expect(res['web-modeler']).toBeDefined()
31+
expect(Array.isArray(res['web-modeler'])).toBe(true)
32+
})
33+
})
34+
35+
describe('Cluster management', () => {
36+
test.runIf(saasMatrix)('getCluster returns cluster details', async () => {
37+
const cluster = await c.getCluster(clusterUuid)
38+
expect(cluster).toBeTruthy()
39+
expect(cluster.uuid).toBe(clusterUuid)
40+
expect(cluster.name).toBeTruthy()
41+
expect(cluster.status).toBeTruthy()
42+
})
43+
})
44+
45+
describe('Secrets', () => {
46+
const testSecretName = `__test_secret_${Date.now()}`
47+
const testSecretValue = 'test-value-initial'
48+
const updatedSecretValue = 'test-value-updated'
49+
50+
afterAll(async () => {
51+
// Cleanup: delete test secret
52+
await c.deleteSecret(clusterUuid, testSecretName).catch(() => {})
53+
})
54+
55+
test.runIf(saasMatrix)('create and update a secret', async () => {
56+
// Create
57+
await c.createSecret({
58+
clusterUuid,
59+
secretName: testSecretName,
60+
secretValue: testSecretValue,
61+
})
62+
63+
// Verify it exists
64+
const secrets = await c.getSecrets(clusterUuid)
65+
expect(secrets[testSecretName]).toBe(testSecretValue)
66+
67+
// Update
68+
await c.updateSecret(clusterUuid, testSecretName, updatedSecretValue)
69+
70+
// Verify update
71+
const updatedSecrets = await c.getSecrets(clusterUuid)
72+
expect(updatedSecrets[testSecretName]).toBe(updatedSecretValue)
73+
})
74+
})
75+
76+
describe('IP Allowlist', () => {
77+
test.runIf(saasMatrix)(
78+
'updateIpAllowlist can set and clear an allowlist',
79+
async () => {
80+
// Set a test allowlist entry
81+
await c.updateIpAllowlist(clusterUuid, [
82+
{ description: '__test_entry', ip: '203.0.113.0/24' },
83+
])
84+
85+
// Clear the allowlist to restore original state
86+
await c.updateIpAllowlist(clusterUuid, [])
87+
}
88+
)
89+
})
90+
91+
describe('Backups', () => {
92+
test.runIf(saasMatrix)('getBackups returns an array', async () => {
93+
const backups = await c.getBackups(clusterUuid)
94+
expect(Array.isArray(backups)).toBe(true)
95+
})
96+
})
97+
98+
describe('Secure Connectivity', () => {
99+
test.runIf(saasMatrix)(
100+
'getSecureConnectivityStatus returns status',
101+
async () => {
102+
try {
103+
const status = await c.getSecureConnectivityStatus(clusterUuid)
104+
expect(status).toBeTruthy()
105+
expect(status.status).toBeDefined()
106+
} catch (e: unknown) {
107+
// 403 = feature not available on this plan
108+
const err = e as { response?: { statusCode?: number } }
109+
if (err.response?.statusCode === 403) {
110+
return
111+
}
112+
throw e
113+
}
114+
}
115+
)
116+
})
117+
118+
describe('Monitoring', () => {
119+
test.runIf(saasMatrix)(
120+
'getMonitoringClients returns response',
121+
async () => {
122+
try {
123+
const res = await c.getMonitoringClients(clusterUuid)
124+
expect(res).toBeTruthy()
125+
expect(res.clients).toBeDefined()
126+
expect(Array.isArray(res.clients)).toBe(true)
127+
} catch (e: unknown) {
128+
// 403 = feature not available on this plan
129+
const err = e as { response?: { statusCode?: number } }
130+
if (err.response?.statusCode === 403) {
131+
return
132+
}
133+
throw e
134+
}
135+
}
136+
)
137+
})
138+
139+
describe('Activity / Audit', () => {
140+
test.runIf(saasMatrix)(
141+
'getActivityEvents returns audit events',
142+
async () => {
143+
const events = await c.getActivityEvents()
144+
expect(Array.isArray(events)).toBe(true)
145+
if (events.length > 0) {
146+
expect(events[0].service).toBeDefined()
147+
expect(events[0].orgId).toBeDefined()
148+
expect(events[0].timestamp).toBeDefined()
149+
expect(events[0].auditType).toBeDefined()
150+
}
151+
}
152+
)
153+
154+
test.runIf(saasMatrix)(
155+
'getActivityEventsCsv returns a CSV string',
156+
async () => {
157+
const csv = await c.getActivityEventsCsv()
158+
expect(typeof csv).toBe('string')
159+
}
160+
)
161+
})
162+
163+
describe('Members', () => {
164+
test.runIf(saasMatrix)(
165+
'getUsers returns organization members',
166+
async () => {
167+
const members = await c.getUsers()
168+
expect(Array.isArray(members)).toBe(true)
169+
expect(members.length).toBeGreaterThan(0)
170+
expect(members[0].email).toBeDefined()
171+
expect(members[0].roles).toBeDefined()
172+
}
173+
)
174+
})
175+
})

0 commit comments

Comments
 (0)