fix: use license/usage endpoint for agent/env/app counts
Some checks failed
CI / docker (push) Has been cancelled
CI / build (push) Has been cancelled

Server moved GET /agents to /environments/{envSlug}/agents and removed
GET /admin/apps. Replace three broken individual calls with a single
GET /admin/license/usage call that returns all counts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-28 12:58:35 +02:00
parent c43d7f639f
commit bc32d7e994
4 changed files with 38 additions and 49 deletions

View File

@@ -125,51 +125,37 @@ public class ServerApiClient {
} }
} }
/** Fetch agent count from a tenant's server. */ public record UsageCounts(int agents, int environments, int apps) {
public int getAgentCount(String serverEndpoint) { public static final UsageCounts ZERO = new UsageCounts(0, 0, 0);
try {
var resp = RestClient.create().get()
.uri(serverEndpoint + "/api/v1/agents")
.header("Authorization", "Bearer " + getAccessToken())
.header("X-Cameleer-Protocol-Version", "1")
.retrieve()
.body(java.util.List.class);
return resp != null ? resp.size() : 0;
} catch (Exception e) {
log.warn("Agent count fetch failed for {}: {}", serverEndpoint, e.getMessage());
return 0;
}
} }
/** Fetch environment count from a tenant's server. */ /** Fetch usage counts from a tenant's server via the license usage endpoint. */
public int getEnvironmentCount(String serverEndpoint) { @SuppressWarnings("unchecked")
public UsageCounts getUsageCounts(String serverEndpoint) {
try { try {
var resp = RestClient.create().get() var resp = RestClient.create().get()
.uri(serverEndpoint + "/api/v1/admin/environments") .uri(serverEndpoint + "/api/v1/admin/license/usage")
.header("Authorization", "Bearer " + getAccessToken()) .header("Authorization", "Bearer " + getAccessToken())
.header("X-Cameleer-Protocol-Version", "1") .header("X-Cameleer-Protocol-Version", "1")
.retrieve() .retrieve()
.body(java.util.List.class); .body(Map.class);
return resp != null ? resp.size() : 0; if (resp == null) return UsageCounts.ZERO;
} catch (Exception e) { var limits = (List<Map<String, Object>>) resp.get("limits");
log.warn("Environment count fetch failed for {}: {}", serverEndpoint, e.getMessage()); if (limits == null) return UsageCounts.ZERO;
return 0; int agents = 0, environments = 0, apps = 0;
for (var row : limits) {
String key = (String) row.get("key");
int current = ((Number) row.get("current")).intValue();
switch (key) {
case "max_agents" -> agents = current;
case "max_environments" -> environments = current;
case "max_apps" -> apps = current;
} }
} }
return new UsageCounts(agents, environments, apps);
/** Fetch app count from a tenant's server. */
public int getAppCount(String serverEndpoint) {
try {
var resp = RestClient.create().get()
.uri(serverEndpoint + "/api/v1/admin/apps")
.header("Authorization", "Bearer " + getAccessToken())
.header("X-Cameleer-Protocol-Version", "1")
.retrieve()
.body(java.util.List.class);
return resp != null ? resp.size() : 0;
} catch (Exception e) { } catch (Exception e) {
log.warn("App count fetch failed for {}: {}", serverEndpoint, e.getMessage()); log.warn("Usage counts fetch failed for {}: {}", serverEndpoint, e.getMessage());
return 0; return UsageCounts.ZERO;
} }
} }

View File

@@ -113,8 +113,9 @@ public class TenantPortalService {
serverHealthy = health.healthy(); serverHealthy = health.healthy();
serverStatus = health.status(); serverStatus = health.status();
if (serverHealthy) { if (serverHealthy) {
agentCount = serverApiClient.getAgentCount(endpoint); var counts = serverApiClient.getUsageCounts(endpoint);
environmentCount = serverApiClient.getEnvironmentCount(endpoint); agentCount = counts.agents();
environmentCount = counts.environments();
} }
} }
@@ -160,9 +161,10 @@ public class TenantPortalService {
Map<String, Integer> usage = new HashMap<>(); Map<String, Integer> usage = new HashMap<>();
String endpoint = tenant.getServerEndpoint(); String endpoint = tenant.getServerEndpoint();
if (endpoint != null && !endpoint.isBlank()) { if (endpoint != null && !endpoint.isBlank()) {
usage.put("agents", serverApiClient.getAgentCount(endpoint)); var counts = serverApiClient.getUsageCounts(endpoint);
usage.put("environments", serverApiClient.getEnvironmentCount(endpoint)); usage.put("agents", counts.agents());
usage.put("apps", serverApiClient.getAppCount(endpoint)); usage.put("environments", counts.environments());
usage.put("apps", counts.apps());
} }
// User count from Logto org membership // User count from Logto org membership
String orgId = tenant.getLogtoOrgId(); String orgId = tenant.getLogtoOrgId();

View File

@@ -80,8 +80,9 @@ public class VendorTenantController {
boolean isActive = "ACTIVE".equals(tenant.getStatus().name()); boolean isActive = "ACTIVE".equals(tenant.getStatus().name());
if (isActive && endpoint != null && !endpoint.isBlank() && "RUNNING".equals(status.state().name())) { if (isActive && endpoint != null && !endpoint.isBlank() && "RUNNING".equals(status.state().name())) {
var serverApi = vendorTenantService.getServerApiClient(); var serverApi = vendorTenantService.getServerApiClient();
agentCount = serverApi.getAgentCount(endpoint); var counts = serverApi.getUsageCounts(endpoint);
environmentCount = serverApi.getEnvironmentCount(endpoint); agentCount = counts.agents();
environmentCount = counts.environments();
} }
var license = vendorTenantService.getLicenseForTenant(tenant.getId()); var license = vendorTenantService.getLicenseForTenant(tenant.getId());
if (license.isPresent() && license.get().getLimits() != null) { if (license.isPresent() && license.get().getLimits() != null) {
@@ -130,9 +131,10 @@ public class VendorTenantController {
String endpoint = tenant.getServerEndpoint(); String endpoint = tenant.getServerEndpoint();
if (health.healthy() && endpoint != null && !endpoint.isBlank()) { if (health.healthy() && endpoint != null && !endpoint.isBlank()) {
var serverApi = vendorTenantService.getServerApiClient(); var serverApi = vendorTenantService.getServerApiClient();
usage.put("agents", serverApi.getAgentCount(endpoint)); var counts = serverApi.getUsageCounts(endpoint);
usage.put("environments", serverApi.getEnvironmentCount(endpoint)); usage.put("agents", counts.agents());
usage.put("apps", serverApi.getAppCount(endpoint)); usage.put("environments", counts.environments());
usage.put("apps", counts.apps());
} }
return ResponseEntity.ok(new VendorTenantDetail( return ResponseEntity.ok(new VendorTenantDetail(

View File

@@ -108,8 +108,7 @@ class TenantPortalServiceTest {
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant)); when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(serverApiClient.getHealth("http://server:8080")).thenReturn(new ServerHealthResponse(true, "UP")); when(serverApiClient.getHealth("http://server:8080")).thenReturn(new ServerHealthResponse(true, "UP"));
when(serverApiClient.getAgentCount("http://server:8080")).thenReturn(3); when(serverApiClient.getUsageCounts("http://server:8080")).thenReturn(new ServerApiClient.UsageCounts(3, 1, 2));
when(serverApiClient.getEnvironmentCount("http://server:8080")).thenReturn(1);
when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.of(license)); when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.of(license));
var result = tenantPortalService.getDashboard(); var result = tenantPortalService.getDashboard();