fix: fetch actual agent/environment counts from server for tenant dashboard
All checks were successful
CI / build (push) Successful in 1m8s
CI / docker (push) Successful in 43s

The dashboard was showing hardcoded zeroes for agent and environment usage.
Now fetches real counts via M2M API from the tenant's server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-10 20:35:24 +02:00
parent cab6e409b9
commit a5445e332e
5 changed files with 51 additions and 5 deletions

View File

@@ -124,6 +124,38 @@ public class ServerApiClient {
}
}
/** Fetch agent count from a tenant's server. */
public int getAgentCount(String serverEndpoint) {
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. */
public int getEnvironmentCount(String serverEndpoint) {
try {
var resp = RestClient.create().get()
.uri(serverEndpoint + "/api/v1/admin/environments")
.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("Environment count fetch failed for {}: {}", serverEndpoint, e.getMessage());
return 0;
}
}
public record ServerHealthResponse(boolean healthy, String status) {}
private synchronized String getAccessToken() {

View File

@@ -47,7 +47,8 @@ public class TenantPortalService {
String name, String slug, String tier, String status,
boolean serverHealthy, String serverStatus, String serverEndpoint,
String licenseTier, long licenseDaysRemaining,
Map<String, Object> limits, Map<String, Object> features
Map<String, Object> limits, Map<String, Object> features,
int agentCount, int environmentCount
) {}
public record LicenseData(
@@ -82,10 +83,16 @@ public class TenantPortalService {
boolean serverHealthy = false;
String serverStatus = "NO_ENDPOINT";
int agentCount = 0;
int environmentCount = 0;
if (endpoint != null && !endpoint.isBlank()) {
var health = serverApiClient.getHealth(endpoint);
serverHealthy = health.healthy();
serverStatus = health.status();
if (serverHealthy) {
agentCount = serverApiClient.getAgentCount(endpoint);
environmentCount = serverApiClient.getEnvironmentCount(endpoint);
}
}
String licenseTier = null;
@@ -107,7 +114,7 @@ public class TenantPortalService {
tenant.getTier().name(), tenant.getStatus().name(),
serverHealthy, serverStatus, endpoint,
licenseTier, licenseDaysRemaining,
limits, features
limits, features, agentCount, environmentCount
);
}

View File

@@ -104,6 +104,8 @@ class TenantPortalServiceTest {
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(serverApiClient.getHealth("http://server:8080")).thenReturn(new ServerHealthResponse(true, "UP"));
when(serverApiClient.getAgentCount("http://server:8080")).thenReturn(3);
when(serverApiClient.getEnvironmentCount("http://server:8080")).thenReturn(1);
when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.of(license));
var result = tenantPortalService.getDashboard();
@@ -119,6 +121,8 @@ class TenantPortalServiceTest {
assertThat(result.licenseDaysRemaining()).isGreaterThanOrEqualTo(29);
assertThat(result.limits()).isNotEmpty();
assertThat(result.features()).isNotEmpty();
assertThat(result.agentCount()).isEqualTo(3);
assertThat(result.environmentCount()).isEqualTo(1);
}
@Test
@@ -136,6 +140,8 @@ class TenantPortalServiceTest {
assertThat(result.serverEndpoint()).isNull();
assertThat(result.licenseTier()).isNull();
assertThat(result.licenseDaysRemaining()).isZero();
assertThat(result.agentCount()).isZero();
assertThat(result.environmentCount()).isZero();
}
// --- getLicense tests ---

View File

@@ -54,9 +54,8 @@ export function TenantDashboardPage() {
const agentLimit = data.limits?.['agents'] ?? -1;
const envLimit = data.limits?.['environments'] ?? -1;
// Dashboard doesn't expose usage counts directly — show limit info from license
const agentUsed = 0;
const envUsed = 0;
const agentUsed = data.agentCount ?? 0;
const envUsed = data.environmentCount ?? 0;
return (
<div style={{ padding: 24, display: 'flex', flexDirection: 'column', gap: 20 }}>

View File

@@ -72,6 +72,8 @@ export interface DashboardData {
licenseDaysRemaining: number;
limits: Record<string, number>;
features: Record<string, boolean>;
agentCount: number;
environmentCount: number;
}
export interface TenantLicenseData {