1use std::collections::BTreeMap;
2
3use crate::{Platform, ResourceType};
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use serde_json::Value as JsonValue;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
10#[serde(rename_all = "camelCase")]
11pub struct ResourceHeartbeat {
12 pub deployment_id: Option<String>,
13 pub resource_id: String,
16 pub resource_type: ResourceType,
17 pub controller_platform: Platform,
18 pub backend: HeartbeatBackend,
19 pub observed_at: DateTime<Utc>,
20 pub data: ResourceHeartbeatData,
21 pub raw: Vec<RawHeartbeatSnippet>,
22}
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
26#[serde(rename_all = "camelCase")]
27pub struct ObservedInventoryBatch {
28 pub source_kind: String,
31 pub inventory_scope: String,
33 pub controller_platform: Platform,
35 pub backend: HeartbeatBackend,
37 pub observed_at: DateTime<Utc>,
39 pub complete: bool,
43 pub resources: Vec<ObservedResourceSample>,
44}
45
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
48#[serde(rename_all = "camelCase")]
49pub struct ObservedResourceSample {
50 pub deployment_id: Option<String>,
51 pub raw_identity: String,
54 pub provider_kind: String,
58 pub display_name: String,
59 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub namespace: Option<String>,
61 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub region: Option<String>,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub scope: Option<String>,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub resource_type_hint: Option<ResourceType>,
67 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub version: Option<String>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub alien_resource_id: Option<String>,
72 pub health: ObservedHealth,
73 pub lifecycle: ProviderLifecycleState,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub message: Option<String>,
76 pub partial: bool,
77 pub provider_stale: bool,
78 #[serde(default, skip_serializing_if = "Option::is_none")]
79 pub counts: Option<ObservedCounts>,
80 #[serde(default, skip_serializing_if = "Vec::is_empty")]
81 pub collection_issues: Vec<HeartbeatCollectionIssue>,
82 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
83 pub labels: BTreeMap<String, String>,
84 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
85 pub attributes: BTreeMap<String, JsonValue>,
86 #[serde(default, skip_serializing_if = "Vec::is_empty")]
87 pub raw: Vec<RawHeartbeatSnippet>,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
91#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
92#[serde(rename_all = "camelCase")]
93pub enum HeartbeatBackend {
94 Aws,
95 Gcp,
96 Azure,
97 Kubernetes,
98 Local,
99 Managed,
100 External,
101 Test,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
105#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
106#[serde(rename_all = "kebab-case")]
107pub enum HeartbeatCollectionIssueReason {
108 Forbidden,
109 NotInstalled,
110 ApiUnavailable,
111 CollectionFailed,
112 TimedOut,
113}
114
115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
117#[serde(tag = "resourceType", content = "data")]
118pub enum ResourceHeartbeatData {
119 #[serde(rename = "storage")]
120 Storage(StorageHeartbeatData),
121 #[serde(rename = "worker")]
122 Worker(WorkerHeartbeatData),
123 #[serde(rename = "container")]
124 Container(ContainerHeartbeatData),
125 #[serde(rename = "daemon")]
126 Daemon(DaemonHeartbeatData),
127 #[serde(rename = "compute-cluster")]
128 ComputeCluster(ComputeClusterHeartbeatData),
129 #[serde(rename = "kubernetes-cluster")]
130 KubernetesCluster(KubernetesClusterHeartbeatData),
131 #[serde(rename = "queue")]
132 Queue(QueueHeartbeatData),
133 #[serde(rename = "kv")]
134 Kv(KvHeartbeatData),
135 #[serde(rename = "postgres")]
136 Postgres(PostgresHeartbeatData),
137 #[serde(rename = "vault")]
138 Vault(VaultHeartbeatData),
139 #[serde(rename = "service-account")]
140 ServiceAccount(ServiceAccountHeartbeatData),
141 #[serde(rename = "network")]
142 Network(NetworkHeartbeatData),
143 #[serde(rename = "remote-stack-management")]
144 RemoteStackManagement(RemoteStackManagementHeartbeatData),
145 #[serde(rename = "artifact-registry")]
146 ArtifactRegistry(ArtifactRegistryHeartbeatData),
147 #[serde(rename = "build")]
148 Build(BuildHeartbeatData),
149 #[serde(rename = "service_activation")]
150 ServiceActivation(ServiceActivationHeartbeatData),
151 #[serde(rename = "azure_resource_group")]
152 AzureResourceGroup(AzureResourceGroupHeartbeatData),
153 #[serde(rename = "azure_storage_account")]
154 AzureStorageAccount(AzureStorageAccountHeartbeatData),
155 #[serde(rename = "azure_container_apps_environment")]
156 AzureContainerAppsEnvironment(AzureContainerAppsEnvironmentHeartbeatData),
157 #[serde(rename = "azure_service_bus_namespace")]
158 AzureServiceBusNamespace(AzureServiceBusNamespaceHeartbeatData),
159 #[serde(rename = "ai")]
160 Ai(AiHeartbeatData),
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
164#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
165#[serde(rename_all = "kebab-case")]
166pub enum ObservedHealth {
167 Unknown,
168 Healthy,
169 Degraded,
170 Unhealthy,
171}
172
173#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
174#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
175#[serde(rename_all = "kebab-case")]
176pub enum ProviderLifecycleState {
177 Unknown,
178 Creating,
179 Updating,
180 Running,
181 Scaling,
182 Stopping,
183 Stopped,
184 Deleting,
185 Deleted,
186 Failed,
187}
188
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
191#[serde(rename_all = "camelCase")]
192pub struct HeartbeatCollectionIssue {
193 pub source: String,
194 pub reason: HeartbeatCollectionIssueReason,
195 pub severity: HeartbeatIssueSeverity,
196 pub message: String,
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
200#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
201#[serde(rename_all = "kebab-case")]
202pub enum HeartbeatIssueSeverity {
203 Info,
204 Warning,
205 Error,
206}
207
208#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
209#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
210#[serde(rename_all = "camelCase")]
211pub struct KubernetesEventSnapshot {
212 pub reason: String,
213 #[serde(rename = "type")]
214 pub type_: Option<String>,
215 pub message: String,
216 pub count: Option<i32>,
217 pub first_timestamp: Option<DateTime<Utc>>,
218 pub last_timestamp: Option<DateTime<Utc>>,
219 pub event_time: Option<DateTime<Utc>>,
220 pub source: Option<KubernetesEventSource>,
221 pub involved_object: Option<KubernetesEventInvolvedObject>,
222 pub raw: Option<JsonValue>,
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
226#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
227#[serde(rename_all = "camelCase")]
228pub struct KubernetesEventSource {
229 pub component: Option<String>,
230 pub host: Option<String>,
231}
232
233#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
234#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
235#[serde(rename_all = "camelCase")]
236pub struct KubernetesEventInvolvedObject {
237 pub kind: Option<String>,
238 pub namespace: Option<String>,
239 pub name: Option<String>,
240 pub uid: Option<String>,
241 pub api_version: Option<String>,
242 pub resource_version: Option<String>,
243 pub field_path: Option<String>,
244}
245
246#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
247#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
248#[serde(rename_all = "camelCase")]
249pub struct ManagedRuntimeEventSnapshot {
250 pub event_id: Option<String>,
251 pub reason: String,
252 #[serde(rename = "type")]
253 pub type_: Option<String>,
254 pub message: String,
255 pub count: Option<i32>,
256 pub first_timestamp: Option<DateTime<Utc>>,
257 pub last_timestamp: Option<DateTime<Utc>>,
258 pub event_time: Option<DateTime<Utc>>,
259 pub source: Option<ManagedRuntimeEventSource>,
260 pub involved_object: Option<ManagedRuntimeEventInvolvedObject>,
261 pub details: Option<JsonValue>,
262 pub raw: Option<JsonValue>,
263}
264
265#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
266#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
267#[serde(rename_all = "camelCase")]
268pub struct ManagedRuntimeEventSource {
269 pub component: Option<String>,
270 pub host: Option<String>,
271}
272
273#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
274#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
275#[serde(rename_all = "camelCase")]
276pub struct ManagedRuntimeEventInvolvedObject {
277 pub kind: Option<String>,
278 pub id: Option<String>,
279 pub name: Option<String>,
280 pub replica_id: Option<String>,
281 pub machine_id: Option<String>,
282 pub details: Option<JsonValue>,
283}
284
285#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
286#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
287#[serde(rename_all = "camelCase")]
288pub struct LocalRuntimeEventSnapshot {
289 pub timestamp: DateTime<Utc>,
290 pub severity: HeartbeatIssueSeverity,
291 pub kind: String,
292 pub message: String,
293 pub subject: Option<LocalRuntimeEventSubject>,
294 pub raw: Option<JsonValue>,
295}
296
297#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
298#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
299#[serde(rename_all = "camelCase")]
300pub struct LocalRuntimeEventSubject {
301 pub kind: String,
302 pub id: Option<String>,
303 pub name: Option<String>,
304}
305
306#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
307#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
308#[serde(rename_all = "camelCase")]
309pub struct RawHeartbeatSnippet {
310 pub source: String,
311 pub format: RawHeartbeatSnippetFormat,
312 pub collected_at: DateTime<Utc>,
313 pub body: String,
314 pub truncated: bool,
315}
316
317#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
318#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
319#[serde(rename_all = "kebab-case")]
320pub enum RawHeartbeatSnippetFormat {
321 Json,
322 Yaml,
323 Text,
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
327#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
328#[serde(rename_all = "camelCase")]
329pub struct ObservedCounts {
330 pub desired: Option<u32>,
331 pub current: Option<u32>,
332 pub ready: Option<u32>,
333}
334
335#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
336#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
337#[serde(rename_all = "camelCase")]
338pub struct MetricSample {
339 pub value: f64,
340 pub unit: MetricUnit,
341}
342
343#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
344#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
345#[serde(rename_all = "kebab-case")]
346pub enum MetricUnit {
347 Count,
348 Percent,
349 Bytes,
350 Cores,
351 Milliseconds,
352 RequestsPerSecond,
353}
354
355#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
356#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
357#[serde(tag = "backend", rename_all = "camelCase")]
358pub enum StorageHeartbeatData {
359 AwsS3(AwsS3StorageHeartbeatData),
360 GcpCloudStorage(GcpCloudStorageHeartbeatData),
361 AzureBlob(AzureBlobStorageHeartbeatData),
362 Local(LocalStorageHeartbeatData),
363}
364
365#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
366#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
367#[serde(rename_all = "camelCase")]
368pub struct StorageHeartbeatStatus {
369 pub health: ObservedHealth,
370 pub lifecycle: ProviderLifecycleState,
371 pub message: Option<String>,
372 pub stale: bool,
373 pub partial: bool,
374 pub collection_issues: Vec<HeartbeatCollectionIssue>,
375}
376
377#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
378#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
379#[serde(rename_all = "camelCase")]
380pub struct AwsS3StorageHeartbeatData {
381 pub status: StorageHeartbeatStatus,
382 pub name: String,
383 pub region: Option<String>,
384 pub bucket_location: Option<String>,
385 pub versioning_status: Option<String>,
386 pub versioning_enabled: Option<bool>,
387 pub lifecycle_present: bool,
388 pub lifecycle_rule_count: Option<u64>,
389 pub encryption_config_present: bool,
390 pub encryption_enabled: Option<bool>,
391 pub public_access_block_present: bool,
392 pub block_public_acls: Option<bool>,
393 pub ignore_public_acls: Option<bool>,
394 pub block_public_policy: Option<bool>,
395 pub restrict_public_buckets: Option<bool>,
396 pub bucket_policy_present: Option<bool>,
397 pub bucket_acl_present: Option<bool>,
398}
399
400#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
401#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
402#[serde(rename_all = "camelCase")]
403pub struct AzureBlobStorageHeartbeatData {
404 pub status: StorageHeartbeatStatus,
405 pub name: String,
406 pub storage_account_name: Option<String>,
407 pub resource_group: Option<String>,
408 pub location: Option<String>,
409 pub account_kind: Option<String>,
410 pub sku_name: Option<String>,
411 pub sku_tier: Option<String>,
412 pub access_tier: Option<String>,
413 pub provisioning_state: Option<String>,
414 pub primary_location: Option<String>,
415 pub secondary_location: Option<String>,
416 pub status_of_primary: Option<String>,
417 pub status_of_secondary: Option<String>,
418 pub public_network_access: Option<String>,
419 pub allow_blob_public_access: Option<bool>,
420 pub encryption_key_source: Option<String>,
421 pub blob_encryption_enabled: Option<bool>,
422 pub file_encryption_enabled: Option<bool>,
423 pub queue_encryption_enabled: Option<bool>,
424 pub table_encryption_enabled: Option<bool>,
425 pub blob_versioning_enabled: Option<bool>,
426 pub blob_delete_retention_enabled: Option<bool>,
427 pub blob_delete_retention_days: Option<u64>,
428 pub container_delete_retention_enabled: Option<bool>,
429 pub container_delete_retention_days: Option<u64>,
430 pub change_feed_enabled: Option<bool>,
431 pub change_feed_retention_days: Option<u64>,
432 pub container_public_access: Option<String>,
433}
434
435#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
436#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
437#[serde(rename_all = "camelCase")]
438pub struct GcpCloudStorageHeartbeatData {
439 pub status: StorageHeartbeatStatus,
440 pub name: String,
441 pub bucket_id: Option<String>,
442 pub location: Option<String>,
443 pub location_type: Option<String>,
444 pub storage_class: Option<String>,
445 pub versioning_enabled: Option<bool>,
446 pub lifecycle_present: bool,
447 pub lifecycle_rule_count: Option<u64>,
448 pub retention_policy_effective_time: Option<String>,
449 pub retention_policy_is_locked: Option<bool>,
450 pub retention_period: Option<String>,
451 pub soft_delete_retention_duration_seconds: Option<String>,
452 pub soft_delete_effective_time: Option<String>,
453 pub uniform_bucket_level_access_enabled: Option<bool>,
454 pub uniform_bucket_level_access_locked_time: Option<String>,
455 pub public_access_prevention: Option<String>,
456 pub encryption_config_present: bool,
457 pub default_kms_key_name: Option<String>,
458}
459
460#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
461#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
462#[serde(rename_all = "camelCase")]
463pub struct LocalStorageHeartbeatData {
464 pub status: StorageHeartbeatStatus,
465 pub path: String,
466 pub path_exists: bool,
467 pub is_directory: Option<bool>,
468 pub readonly: Option<bool>,
469 pub modified_at: Option<DateTime<Utc>>,
470}
471
472#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
473#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
474#[serde(tag = "backend", rename_all = "camelCase")]
475pub enum WorkerHeartbeatData {
476 AwsLambda(AwsLambdaWorkerHeartbeatData),
477 GcpCloudRun(GcpCloudRunWorkerHeartbeatData),
478 AzureContainerApps(AzureContainerAppsWorkerHeartbeatData),
479 Kubernetes(KubernetesWorkerHeartbeatData),
480 Local(LocalWorkerHeartbeatData),
481}
482
483#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
484#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
485#[serde(tag = "backend", rename_all = "camelCase")]
486pub enum ContainerHeartbeatData {
487 HorizonPlatform(HorizonContainerHeartbeatData),
488 Kubernetes(KubernetesContainerHeartbeatData),
489 Local(LocalContainerHeartbeatData),
490}
491
492#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
493#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
494#[serde(tag = "backend", rename_all = "camelCase")]
495pub enum DaemonHeartbeatData {
496 Aws(AwsDaemonHeartbeatData),
497 Gcp(GcpDaemonHeartbeatData),
498 Azure(AzureDaemonHeartbeatData),
499 Machines(MachinesDaemonHeartbeatData),
500 Kubernetes(KubernetesDaemonHeartbeatData),
501 Local(LocalDaemonHeartbeatData),
502}
503
504#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
505#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
506#[serde(rename_all = "camelCase")]
507pub struct WorkloadHeartbeatStatus {
508 pub health: ObservedHealth,
509 pub lifecycle: ProviderLifecycleState,
510 pub message: Option<String>,
511 pub stale: bool,
512 pub partial: bool,
513 pub collection_issues: Vec<HeartbeatCollectionIssue>,
514}
515
516#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
517#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
518#[serde(rename_all = "camelCase")]
519pub struct WorkloadReplicaStatus {
520 pub desired: Option<u32>,
521 pub current: Option<u32>,
522 pub ready: Option<u32>,
523 pub available: Option<u32>,
524 pub updated: Option<u32>,
525 pub misscheduled: Option<u32>,
526}
527
528#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
529#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
530#[serde(rename_all = "camelCase")]
531pub struct AwsLambdaWorkerHeartbeatData {
532 pub status: WorkloadHeartbeatStatus,
533 pub function_name: String,
534 pub runtime: Option<String>,
535 pub package_type: Option<String>,
536 pub memory_size_mb: Option<i64>,
537 pub timeout_seconds: Option<i64>,
538 pub version: Option<String>,
539 pub revision_id: Option<String>,
540 pub last_modified: Option<String>,
541 pub state: Option<String>,
542 pub state_reason: Option<String>,
543 pub state_reason_code: Option<String>,
544 pub last_update_status: Option<String>,
545 pub last_update_status_reason: Option<String>,
546 pub last_update_status_reason_code: Option<String>,
547 pub code_sha256: Option<String>,
548 pub layer_count: u32,
549 pub function_url_auth_type: Option<String>,
550 pub function_url_cors_present: bool,
551 pub trigger_count: u32,
552}
553
554#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
555#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
556#[serde(rename_all = "camelCase")]
557pub struct GcpCloudRunWorkerHeartbeatData {
558 pub status: WorkloadHeartbeatStatus,
559 pub service: String,
560 pub region: Option<String>,
561 pub uri: Option<String>,
562 pub urls: Vec<String>,
563 pub latest_created_revision: Option<String>,
564 pub latest_ready_revision: Option<String>,
565 pub generation: Option<i64>,
566 pub observed_generation: Option<i64>,
567 pub traffic_count: u32,
568 pub min_instance_count: Option<i32>,
569 pub max_instance_count: Option<i32>,
570 pub container_image: Option<String>,
571 pub cpu_limit: Option<String>,
572 pub memory_limit: Option<String>,
573}
574
575#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
576#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
577#[serde(rename_all = "camelCase")]
578pub struct AzureContainerAppsWorkerHeartbeatData {
579 pub status: WorkloadHeartbeatStatus,
580 pub app_name: String,
581 pub revision: Option<String>,
582 pub environment_name: Option<String>,
583 pub provisioning_state: Option<String>,
584 pub running_status: Option<String>,
585 pub ingress_fqdn: Option<String>,
586 pub min_replicas: Option<i32>,
587 pub max_replicas: Option<i32>,
588 pub cpu: Option<f64>,
589 pub memory: Option<String>,
590}
591
592#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
593#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
594#[serde(rename_all = "camelCase")]
595pub struct KubernetesWorkerHeartbeatData {
596 pub status: WorkloadHeartbeatStatus,
597 pub namespace: String,
598 pub name: String,
599 pub workload_kind: KubernetesWorkloadKind,
600 pub replicas: WorkloadReplicaStatus,
601 pub restarts: Option<u32>,
602 pub cpu: Option<MetricSample>,
603 pub memory: Option<MetricSample>,
604 pub workload: Option<KubernetesWorkloadStatus>,
605 pub pods: Vec<KubernetesPodRuntimeUnitStatus>,
606 pub trigger_count: u32,
607 pub events: Vec<KubernetesEventSnapshot>,
608}
609
610#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
611#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
612#[serde(rename_all = "camelCase")]
613pub struct LocalWorkerHeartbeatData {
614 pub status: WorkloadHeartbeatStatus,
615 pub pid: Option<u32>,
616 pub command_supported: bool,
617 pub image_path_present: bool,
618 pub readiness_probe_ok: Option<bool>,
619 pub trigger_count: u32,
620 pub cpu: Option<MetricSample>,
621 pub memory: Option<MetricSample>,
622 pub process: Option<LocalRuntimeUnitStatus>,
623 pub events: Vec<LocalRuntimeEventSnapshot>,
624}
625
626#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
627#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
628#[serde(rename_all = "camelCase")]
629pub struct HorizonContainerHeartbeatData {
630 pub status: WorkloadHeartbeatStatus,
631 pub container_id: String,
632 pub image: Option<String>,
633 #[serde(default)]
634 pub observed_image: Option<String>,
635 #[serde(default)]
636 pub latest_update_timestamp: Option<String>,
637 pub scheduling_mode: HorizonWorkloadSchedulingMode,
638 pub replicas: WorkloadReplicaStatus,
639 pub cpu: Option<MetricSample>,
640 pub memory: Option<MetricSample>,
641 pub attention_count: u32,
642 pub replica_units: Vec<ManagedRuntimeUnitStatus>,
643 pub events: Vec<ManagedRuntimeEventSnapshot>,
644}
645
646#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
647#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
648#[serde(rename_all = "camelCase")]
649pub enum HorizonWorkloadSchedulingMode {
650 Replicated,
651 Stateful,
652 Daemon,
653}
654
655#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
656#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
657#[serde(rename_all = "camelCase")]
658pub struct KubernetesContainerHeartbeatData {
659 pub status: WorkloadHeartbeatStatus,
660 pub namespace: String,
661 pub name: String,
662 pub workload_kind: KubernetesWorkloadKind,
663 pub replicas: WorkloadReplicaStatus,
664 pub restarts: Option<u32>,
665 pub cpu: Option<MetricSample>,
666 pub memory: Option<MetricSample>,
667 pub workload: Option<KubernetesWorkloadStatus>,
668 pub pods: Vec<KubernetesPodRuntimeUnitStatus>,
669 pub events: Vec<KubernetesEventSnapshot>,
670}
671
672#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
673#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
674#[serde(rename_all = "camelCase")]
675pub struct LocalContainerHeartbeatData {
676 pub status: WorkloadHeartbeatStatus,
677 pub container_id: Option<String>,
678 pub name: Option<String>,
679 pub image: Option<String>,
680 pub runtime_status: Option<String>,
681 pub restart_count: Option<u32>,
682 pub port_count: u32,
683 pub bind_mount_count: u32,
684 pub local_url: Option<String>,
685 pub runtime_reachable: bool,
686 pub cpu: Option<MetricSample>,
687 pub memory: Option<MetricSample>,
688 pub container_unit: Option<LocalRuntimeUnitStatus>,
689 pub events: Vec<LocalRuntimeEventSnapshot>,
690}
691
692#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
693#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
694#[serde(rename_all = "camelCase")]
695pub struct AwsDaemonHeartbeatData {
696 pub status: WorkloadHeartbeatStatus,
697 pub horizon_cluster_id: String,
698 #[serde(default)]
699 pub daemon_name: String,
700 pub horizon_status: String,
701 pub horizon_status_reason: Option<String>,
702 pub horizon_status_message: Option<String>,
703 pub capacity_group: String,
704 pub desired_machines: u32,
705 pub assigned_machines: u32,
706 pub healthy_instances: u32,
707 pub unavailable_instances: u32,
708 pub command_supported: bool,
709 #[serde(default)]
710 pub observed_image: Option<String>,
711 pub latest_update_timestamp: String,
712 pub daemon_instances: Vec<ManagedRuntimeUnitStatus>,
713 pub events: Vec<ManagedRuntimeEventSnapshot>,
714}
715
716#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
717#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
718#[serde(rename_all = "camelCase")]
719pub struct GcpDaemonHeartbeatData {
720 pub status: WorkloadHeartbeatStatus,
721 pub horizon_cluster_id: String,
722 #[serde(default)]
723 pub daemon_name: String,
724 pub horizon_status: String,
725 pub horizon_status_reason: Option<String>,
726 pub horizon_status_message: Option<String>,
727 pub capacity_group: String,
728 pub desired_machines: u32,
729 pub assigned_machines: u32,
730 pub healthy_instances: u32,
731 pub unavailable_instances: u32,
732 pub command_supported: bool,
733 #[serde(default)]
734 pub observed_image: Option<String>,
735 pub latest_update_timestamp: String,
736 pub daemon_instances: Vec<ManagedRuntimeUnitStatus>,
737 pub events: Vec<ManagedRuntimeEventSnapshot>,
738}
739
740#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
741#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
742#[serde(rename_all = "camelCase")]
743pub struct AzureDaemonHeartbeatData {
744 pub status: WorkloadHeartbeatStatus,
745 pub horizon_cluster_id: String,
746 #[serde(default)]
747 pub daemon_name: String,
748 pub horizon_status: String,
749 pub horizon_status_reason: Option<String>,
750 pub horizon_status_message: Option<String>,
751 pub capacity_group: String,
752 pub desired_machines: u32,
753 pub assigned_machines: u32,
754 pub healthy_instances: u32,
755 pub unavailable_instances: u32,
756 pub command_supported: bool,
757 #[serde(default)]
758 pub observed_image: Option<String>,
759 pub latest_update_timestamp: String,
760 pub daemon_instances: Vec<ManagedRuntimeUnitStatus>,
761 pub events: Vec<ManagedRuntimeEventSnapshot>,
762}
763
764#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
765#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
766#[serde(rename_all = "camelCase")]
767pub struct MachinesDaemonHeartbeatData {
768 pub status: WorkloadHeartbeatStatus,
769 pub horizon_cluster_id: String,
770 #[serde(default)]
771 pub daemon_name: String,
772 pub horizon_status: String,
773 pub horizon_status_reason: Option<String>,
774 pub horizon_status_message: Option<String>,
775 pub capacity_group: String,
776 pub desired_machines: u32,
777 pub assigned_machines: u32,
778 pub healthy_instances: u32,
779 pub unavailable_instances: u32,
780 pub command_supported: bool,
781 #[serde(default)]
782 pub observed_image: Option<String>,
783 pub latest_update_timestamp: String,
784 pub daemon_instances: Vec<ManagedRuntimeUnitStatus>,
785 pub events: Vec<ManagedRuntimeEventSnapshot>,
786}
787
788#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
789#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
790#[serde(rename_all = "camelCase")]
791pub struct ManagedRuntimeUnitStatus {
792 pub replica_id: String,
793 pub name: String,
794 pub machine_id: Option<String>,
795 pub node_name: Option<String>,
796 pub ip: Option<String>,
797 pub ready: bool,
798 pub phase: Option<String>,
799 pub status: Option<String>,
800 pub reason: Option<String>,
801 pub message: Option<String>,
802 pub restart_count: Option<u32>,
803 pub waiting_reason: Option<String>,
804 pub terminated_reason: Option<String>,
805 pub metrics_healthy: Option<bool>,
806 pub metrics_status: Option<String>,
807 pub metrics_last_updated: Option<String>,
808 pub cpu: Option<MetricSample>,
809 pub memory: Option<MetricSample>,
810}
811
812#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
813#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
814#[serde(rename_all = "camelCase")]
815pub struct KubernetesDaemonHeartbeatData {
816 pub status: WorkloadHeartbeatStatus,
817 pub namespace: String,
818 pub name: String,
819 pub replicas: WorkloadReplicaStatus,
820 pub restarts: Option<u32>,
821 pub command_supported: bool,
822 pub cpu: Option<MetricSample>,
823 pub memory: Option<MetricSample>,
824 pub workload: Option<KubernetesWorkloadStatus>,
825 pub pods: Vec<KubernetesPodRuntimeUnitStatus>,
826 pub events: Vec<KubernetesEventSnapshot>,
827}
828
829#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
830#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
831#[serde(rename_all = "camelCase")]
832pub struct LocalDaemonHeartbeatData {
833 pub status: WorkloadHeartbeatStatus,
834 #[serde(default)]
835 pub daemon_name: String,
836 pub runtime_id: String,
837 pub pid: Option<u32>,
838 pub command_supported: bool,
839 pub image_path_present: bool,
840 pub restart_count: Option<u32>,
841 pub exit_reason: Option<String>,
842 pub daemon_instance: Option<LocalRuntimeUnitStatus>,
843 pub events: Vec<LocalRuntimeEventSnapshot>,
844}
845
846#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
847#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
848#[serde(rename_all = "camelCase")]
849pub struct LocalRuntimeUnitStatus {
850 pub unit_id: String,
851 pub name: String,
852 pub kind: LocalRuntimeUnitKind,
853 pub ready: bool,
854 pub phase: Option<String>,
855 pub pid: Option<u32>,
856 pub restart_count: Option<u32>,
857 pub cpu: Option<MetricSample>,
858 pub memory: Option<MetricSample>,
859}
860
861#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
862#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
863#[serde(rename_all = "kebab-case")]
864pub enum LocalRuntimeUnitKind {
865 Container,
866 Process,
867 Daemon,
868}
869
870#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
871#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
872#[serde(rename_all = "camelCase")]
873pub enum KubernetesWorkloadKind {
874 Deployment,
875 StatefulSet,
876 DaemonSet,
877 ReplicaSet,
878 Pod,
879}
880
881#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
882#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
883#[serde(rename_all = "camelCase")]
884pub struct KubernetesWorkloadStatus {
885 pub desired_replicas: Option<u32>,
886 pub ready_replicas: Option<u32>,
887 pub available_replicas: Option<u32>,
888 pub updated_replicas: Option<u32>,
889 pub observed_generation: Option<i64>,
890 pub desired_generation: Option<i64>,
891 pub rollout_reason: Option<String>,
892 pub conditions: Vec<KubernetesWorkloadCondition>,
893}
894
895#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
896#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
897#[serde(rename_all = "camelCase")]
898pub struct KubernetesWorkloadCondition {
899 #[serde(rename = "type")]
900 pub condition_type: String,
901 pub status: String,
902 pub reason: Option<String>,
903 pub message: Option<String>,
904 pub last_transition_time: Option<DateTime<Utc>>,
905}
906
907#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
908#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
909#[serde(rename_all = "camelCase")]
910pub struct KubernetesPodRuntimeUnitStatus {
911 pub name: String,
912 pub uid: Option<String>,
913 pub phase: Option<String>,
914 pub ready: bool,
915 pub restart_count: u32,
916 pub waiting_reason: Option<String>,
917 pub terminated_reason: Option<String>,
918 pub node_name: Option<String>,
919 pub pod_ip: Option<String>,
920 pub owner_references: Vec<KubernetesOwnerReference>,
921 pub cpu: Option<MetricSample>,
922 pub memory: Option<MetricSample>,
923}
924
925#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
926#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
927#[serde(rename_all = "camelCase")]
928pub struct KubernetesOwnerReference {
929 pub kind: String,
930 pub name: String,
931 pub uid: String,
932 pub controller: bool,
933}
934
935#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
936#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
937#[serde(tag = "backend", rename_all = "camelCase")]
938pub enum ComputeClusterHeartbeatData {
939 Aws(AwsComputeClusterHeartbeatData),
940 Gcp(GcpComputeClusterHeartbeatData),
941 Azure(AzureComputeClusterHeartbeatData),
942 Machines(MachinesComputeClusterHeartbeatData),
943 Local(LocalComputeClusterHeartbeatData),
944}
945
946#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
947#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
948#[serde(rename_all = "camelCase")]
949pub struct ComputeClusterHeartbeatStatus {
950 pub health: ObservedHealth,
951 pub lifecycle: ProviderLifecycleState,
952 pub message: Option<String>,
953 pub stale: bool,
954 pub partial: bool,
955 pub collection_issues: Vec<HeartbeatCollectionIssue>,
956}
957
958#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
959#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
960#[serde(rename_all = "camelCase")]
961pub struct LocalComputeClusterHeartbeatData {
962 pub status: ComputeClusterHeartbeatStatus,
963 pub nodes: ObservedCounts,
964 pub name: String,
965 pub host_identifier: Option<String>,
966 pub docker_available: bool,
967 pub docker_version: Option<String>,
968 pub docker_api_version: Option<String>,
969 pub docker_os: Option<String>,
970 pub docker_arch: Option<String>,
971 pub network_name: Option<String>,
972 pub network_available: bool,
973 pub tracked_containers: Option<u32>,
974 pub running_containers: Option<u32>,
975}
976
977#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
978#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
979#[serde(rename_all = "camelCase")]
980pub struct AwsComputeClusterHeartbeatData {
981 pub status: ComputeClusterHeartbeatStatus,
982 pub nodes: ObservedCounts,
983 pub cpu: Option<MetricSample>,
984 pub memory: Option<MetricSample>,
985 pub name: String,
986 pub region: Option<String>,
987 pub backend_cluster_id: Option<String>,
988 pub capacity_groups: Vec<ComputeCapacityGroupStatus>,
989 pub provider_fleets: Vec<ProviderFleetStatus>,
990}
991
992#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
993#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
994#[serde(rename_all = "camelCase")]
995pub struct GcpComputeClusterHeartbeatData {
996 pub status: ComputeClusterHeartbeatStatus,
997 pub nodes: ObservedCounts,
998 pub cpu: Option<MetricSample>,
999 pub memory: Option<MetricSample>,
1000 pub name: String,
1001 pub region: Option<String>,
1002 pub backend_cluster_id: Option<String>,
1003 pub capacity_groups: Vec<ComputeCapacityGroupStatus>,
1004 pub provider_fleets: Vec<ProviderFleetStatus>,
1005}
1006
1007#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1008#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1009#[serde(rename_all = "camelCase")]
1010pub struct AzureComputeClusterHeartbeatData {
1011 pub status: ComputeClusterHeartbeatStatus,
1012 pub nodes: ObservedCounts,
1013 pub cpu: Option<MetricSample>,
1014 pub memory: Option<MetricSample>,
1015 pub name: String,
1016 pub region: Option<String>,
1017 pub backend_cluster_id: Option<String>,
1018 pub capacity_groups: Vec<ComputeCapacityGroupStatus>,
1019 pub provider_fleets: Vec<ProviderFleetStatus>,
1020}
1021
1022#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1023#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1024#[serde(rename_all = "camelCase")]
1025pub struct MachinesComputeClusterHeartbeatData {
1026 pub status: ComputeClusterHeartbeatStatus,
1027 pub nodes: ObservedCounts,
1028 pub cpu: Option<MetricSample>,
1029 pub memory: Option<MetricSample>,
1030 pub name: String,
1031 pub backend_cluster_id: Option<String>,
1032 pub capacity_groups: Vec<ComputeCapacityGroupStatus>,
1033 pub machines: Vec<MachinesComputeMachineStatus>,
1034}
1035
1036#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1037#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1038#[serde(rename_all = "camelCase")]
1039pub struct MachinesComputeMachineStatus {
1040 pub machine_id: String,
1041 pub status: String,
1042 pub capacity_group: String,
1043 pub zone: String,
1044 pub public_ip: Option<String>,
1045 pub overlay_ip: Option<String>,
1046 pub last_heartbeat: String,
1047 pub horizond_version: Option<String>,
1048 pub replica_count: i64,
1049 pub cpu_cores: Option<f64>,
1050 pub memory_bytes: Option<i64>,
1051 pub drain_force: bool,
1052 pub drain_requested_at: Option<String>,
1053 pub drain_deadline_at: Option<String>,
1054 pub drained_at: Option<String>,
1055 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1056 pub drain_blockers: Vec<ComputeDrainBlocker>,
1057}
1058
1059#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1060#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1061#[serde(rename_all = "camelCase")]
1062pub struct ComputeCapacityGroupStatus {
1063 pub group_id: String,
1064 pub current_machines: u32,
1065 pub desired_machines: u32,
1066 pub min_machines: Option<u32>,
1067 pub max_machines: Option<u32>,
1068 pub instance_type: Option<String>,
1069 pub recommendation: Option<ComputeCapacityRecommendation>,
1070 pub capacity_blocker: Option<ComputeCapacityBlocker>,
1071 #[serde(default, skip_serializing_if = "Option::is_none")]
1072 pub drain_progress: Option<ComputeDrainProgress>,
1073}
1074
1075#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1076#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1077#[serde(rename_all = "camelCase")]
1078pub enum ComputeCapacityBlockerCategory {
1079 Quota,
1080 Capacity,
1081 Allocation,
1082 Other,
1083}
1084
1085#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1086#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1087#[serde(rename_all = "camelCase")]
1088pub struct ComputeCapacityBlocker {
1089 pub category: ComputeCapacityBlockerCategory,
1090 pub provider_code: Option<String>,
1091 pub message: String,
1092 pub provider_reference: Option<String>,
1093 pub observed_at: DateTime<Utc>,
1094}
1095
1096#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1097#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1098#[serde(rename_all = "camelCase")]
1099pub struct ComputeCapacityRecommendation {
1100 pub desired_machines: u32,
1101 pub reason: Option<String>,
1102 pub utilization: Option<MetricSample>,
1103 pub unschedulable_replicas: Option<u32>,
1104}
1105
1106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1107#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1108#[serde(rename_all = "camelCase")]
1109pub enum ComputeDrainProgressStatus {
1110 Draining,
1111 Drained,
1112 Terminating,
1113}
1114
1115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1116#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1117#[serde(rename_all = "camelCase")]
1118pub struct ComputeDrainBlocker {
1119 pub workload_name: String,
1120 pub replica_id: String,
1121 pub scheduling_mode: String,
1122 pub state: String,
1123 pub reason: String,
1124}
1125
1126#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1127#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1128#[serde(rename_all = "camelCase")]
1129pub struct ComputeDrainProgress {
1130 pub machine_id: String,
1131 pub status: ComputeDrainProgressStatus,
1132 pub replica_count: i64,
1133 pub force: bool,
1134 pub stalled: bool,
1135 pub drain_requested_at: Option<String>,
1136 pub drain_deadline_at: Option<String>,
1137 pub drained_at: Option<String>,
1138 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1139 pub blockers: Vec<ComputeDrainBlocker>,
1140}
1141
1142#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1143#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1144#[serde(rename_all = "camelCase")]
1145pub struct ProviderFleetStatus {
1146 pub group_id: String,
1147 pub provider_id: String,
1148 pub location: Option<String>,
1149 pub current_machines: u32,
1150 pub desired_machines: u32,
1151}
1152
1153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1154#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1155#[serde(rename_all = "camelCase")]
1156pub struct KubernetesClusterHeartbeatData {
1157 pub status: WorkloadHeartbeatStatus,
1158 pub node_counts: ObservedCounts,
1159 pub pod_counts: ObservedCounts,
1160 pub cpu: Option<MetricSample>,
1161 pub memory: Option<MetricSample>,
1162 pub name: String,
1163 pub region: Option<String>,
1164 pub namespace: Option<String>,
1165 pub version: Option<String>,
1166 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1167 pub node_statuses: Vec<KubernetesClusterNodeStatus>,
1168 pub events: Vec<KubernetesEventSnapshot>,
1169}
1170
1171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1172#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1173#[serde(rename_all = "camelCase")]
1174pub struct KubernetesClusterNodeStatus {
1175 pub name: String,
1176 pub uid: Option<String>,
1177 pub ready: bool,
1178 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1179 pub conditions: Vec<KubernetesNodeConditionStatus>,
1180 pub roles: Vec<String>,
1181 pub labels: BTreeMap<String, String>,
1182 pub allocatable: KubernetesNodeResources,
1183 pub capacity: KubernetesNodeResources,
1184 pub usage: Option<KubernetesNodeUsage>,
1185 pub kubelet_version: Option<String>,
1186 pub container_runtime_version: Option<String>,
1187}
1188
1189#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1190#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1191#[serde(rename_all = "camelCase")]
1192pub struct KubernetesNodeConditionStatus {
1193 pub type_: String,
1194 pub status: String,
1195 pub reason: Option<String>,
1196 pub message: Option<String>,
1197}
1198
1199#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1200#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1201#[serde(rename_all = "camelCase")]
1202pub struct KubernetesNodeResources {
1203 pub cpu: Option<MetricSample>,
1204 pub memory: Option<MetricSample>,
1205 pub pods: Option<u64>,
1206}
1207
1208#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1209#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1210#[serde(rename_all = "camelCase")]
1211pub struct KubernetesNodeUsage {
1212 pub cpu: Option<MetricSample>,
1213 pub memory: Option<MetricSample>,
1214}
1215
1216#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1217#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1218#[serde(tag = "backend", rename_all = "camelCase")]
1219pub enum QueueHeartbeatData {
1220 AwsSqs(AwsSqsQueueHeartbeatData),
1221 GcpPubSub(GcpPubSubQueueHeartbeatData),
1222 AzureServiceBus(AzureServiceBusQueueHeartbeatData),
1223 Local(LocalQueueHeartbeatData),
1224}
1225
1226#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1227#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1228#[serde(rename_all = "camelCase")]
1229pub struct QueueHeartbeatStatus {
1230 pub health: ObservedHealth,
1231 pub lifecycle: ProviderLifecycleState,
1232 pub message: Option<String>,
1233 pub stale: bool,
1234 pub partial: bool,
1235 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1236}
1237
1238impl Default for QueueHeartbeatStatus {
1239 fn default() -> Self {
1240 Self {
1241 health: ObservedHealth::Unknown,
1242 lifecycle: ProviderLifecycleState::Unknown,
1243 message: None,
1244 stale: false,
1245 partial: false,
1246 collection_issues: vec![],
1247 }
1248 }
1249}
1250
1251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1252#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1253#[serde(rename_all = "camelCase")]
1254pub struct LocalQueueHeartbeatData {
1255 pub status: QueueHeartbeatStatus,
1256 pub name: String,
1257 pub path: Option<String>,
1258 pub service_status: Option<String>,
1259}
1260
1261#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1262#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1263#[serde(rename_all = "camelCase")]
1264pub struct GcpPubSubQueueHeartbeatData {
1265 pub status: QueueHeartbeatStatus,
1266 pub topic_name: String,
1267 pub subscription_name: Option<String>,
1268 pub project_id: Option<String>,
1269 pub topic_full_name: Option<String>,
1270 pub subscription_full_name: Option<String>,
1271 pub endpoint: Option<String>,
1272 pub topic_labels: BTreeMap<String, String>,
1273 pub subscription_labels: BTreeMap<String, String>,
1274 pub message_storage_allowed_persistence_regions: Vec<String>,
1275 pub message_storage_enforce_in_transit: Option<bool>,
1276 pub kms_key_name: Option<String>,
1277 pub schema_name: Option<String>,
1278 pub schema_encoding: Option<String>,
1279 pub schema_first_revision_id: Option<String>,
1280 pub schema_last_revision_id: Option<String>,
1281 pub topic_message_retention_duration: Option<String>,
1282 pub topic_state: Option<String>,
1283 pub subscription_ack_deadline_seconds: Option<u32>,
1284 pub subscription_message_retention_duration: Option<String>,
1285 pub subscription_retain_acked_messages: Option<bool>,
1286 pub subscription_enable_message_ordering: Option<bool>,
1287 pub subscription_filter: Option<String>,
1288 pub subscription_detached: Option<bool>,
1289 pub subscription_state: Option<String>,
1290 pub subscription_push_config_present: Option<bool>,
1291 pub subscription_push_endpoint: Option<String>,
1292 pub subscription_push_attributes: BTreeMap<String, String>,
1293 pub subscription_push_oidc_service_account_email: Option<String>,
1294 pub subscription_push_oidc_audience: Option<String>,
1295 pub subscription_push_pubsub_wrapper_write_metadata: Option<bool>,
1296 pub subscription_push_no_wrapper_write_metadata: Option<bool>,
1297 pub subscription_dead_letter_topic: Option<String>,
1298 pub subscription_dead_letter_max_delivery_attempts: Option<u32>,
1299}
1300
1301#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1302#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1303#[serde(rename_all = "camelCase")]
1304pub struct AzureServiceBusQueueHeartbeatData {
1305 pub status: QueueHeartbeatStatus,
1306 pub name: String,
1307 pub namespace_name: String,
1308 pub resource_group: Option<String>,
1309 pub resource_id: Option<String>,
1310 pub endpoint: Option<String>,
1311 pub queue_status: Option<String>,
1312 pub lock_duration: Option<String>,
1313 pub max_delivery_count: Option<u32>,
1314 pub requires_duplicate_detection: Option<bool>,
1315 pub duplicate_detection_history_time_window: Option<String>,
1316 pub requires_session: Option<bool>,
1317 pub dead_lettering_on_message_expiration: Option<bool>,
1318 pub forward_dead_lettered_messages_to: Option<String>,
1319 pub forward_to: Option<String>,
1320 pub default_message_time_to_live: Option<String>,
1321 pub auto_delete_on_idle: Option<String>,
1322 pub enable_batched_operations: Option<bool>,
1323 pub enable_express: Option<bool>,
1324 pub enable_partitioning: Option<bool>,
1325 pub max_message_size_in_kilobytes: Option<u64>,
1326 pub max_size_in_megabytes: Option<u32>,
1327 pub message_count: Option<u64>,
1328 pub active_message_count: Option<u64>,
1329 pub dead_letter_message_count: Option<u64>,
1330 pub scheduled_message_count: Option<u64>,
1331 pub transfer_message_count: Option<u64>,
1332 pub transfer_dead_letter_message_count: Option<u64>,
1333 pub size_in_bytes: Option<u64>,
1334 pub accessed_at: Option<String>,
1335 pub created_at: Option<String>,
1336 pub updated_at: Option<String>,
1337}
1338
1339#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1340#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1341#[serde(rename_all = "camelCase")]
1342pub struct AwsSqsQueueHeartbeatData {
1343 pub status: QueueHeartbeatStatus,
1344 pub name: String,
1345 pub region: Option<String>,
1346 pub queue_url: Option<String>,
1347 pub queue_arn: Option<String>,
1348 pub visibility_timeout_seconds: Option<u32>,
1349 pub message_retention_period_seconds: Option<u32>,
1350 pub delay_seconds: Option<u32>,
1351 pub receive_message_wait_time_seconds: Option<u32>,
1352 pub maximum_message_size: Option<u32>,
1353 pub redrive_policy: Option<String>,
1354 pub redrive_allow_policy: Option<String>,
1355 pub fifo_queue: Option<bool>,
1356 pub content_based_deduplication: Option<bool>,
1357 pub deduplication_scope: Option<String>,
1358 pub fifo_throughput_limit: Option<String>,
1359 pub sse_enabled: Option<bool>,
1360 pub kms_master_key_id: Option<String>,
1361 pub kms_data_key_reuse_period_seconds: Option<u32>,
1362 pub sqs_managed_sse_enabled: Option<bool>,
1363 pub approximate_visible_messages: Option<u64>,
1364 pub approximate_in_flight_messages: Option<u64>,
1365 pub approximate_delayed_messages: Option<u64>,
1366 pub approximate_counts: bool,
1367}
1368
1369#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1370#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1371#[serde(tag = "backend", rename_all = "camelCase")]
1372pub enum KvHeartbeatData {
1373 AwsDynamoDb(AwsDynamoDbKvHeartbeatData),
1374 GcpFirestore(GcpFirestoreKvHeartbeatData),
1375 AzureTable(AzureTableKvHeartbeatData),
1376 Local(LocalKvHeartbeatData),
1377}
1378
1379#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1380#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1381#[serde(rename_all = "camelCase")]
1382pub struct KvHeartbeatStatus {
1383 pub health: ObservedHealth,
1384 pub lifecycle: ProviderLifecycleState,
1385 pub message: Option<String>,
1386 pub stale: bool,
1387 pub partial: bool,
1388 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1389}
1390
1391impl Default for KvHeartbeatStatus {
1392 fn default() -> Self {
1393 Self {
1394 health: ObservedHealth::Unknown,
1395 lifecycle: ProviderLifecycleState::Unknown,
1396 message: None,
1397 stale: false,
1398 partial: false,
1399 collection_issues: vec![],
1400 }
1401 }
1402}
1403
1404#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1405#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1406#[serde(rename_all = "camelCase")]
1407pub struct AwsDynamoDbKvHeartbeatData {
1408 pub status: KvHeartbeatStatus,
1409 pub name: String,
1410 pub region: Option<String>,
1411 pub table_arn: Option<String>,
1412 pub table_status: Option<String>,
1413 pub billing_mode: Option<String>,
1414 pub key_schema: Vec<AwsDynamoDbKeySchemaElement>,
1415 pub global_secondary_index_count: Option<u32>,
1416 pub local_secondary_index_count: Option<u32>,
1417 pub item_count: Option<u64>,
1418 pub table_size_bytes: Option<u64>,
1419 pub stream_enabled: Option<bool>,
1420 pub stream_view_type: Option<String>,
1421 pub ttl_status: Option<String>,
1422 pub ttl_attribute_name: Option<String>,
1423 pub deletion_protection_enabled: Option<bool>,
1424 pub sse_status: Option<String>,
1425 pub sse_type: Option<String>,
1426 pub table_class: Option<String>,
1427 pub replica_count: Option<u32>,
1428 pub restore_in_progress: Option<bool>,
1429}
1430
1431#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1432#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1433#[serde(rename_all = "camelCase")]
1434pub struct AwsDynamoDbKeySchemaElement {
1435 pub attribute_name: String,
1436 pub key_type: String,
1437}
1438
1439#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1440#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1441#[serde(rename_all = "camelCase")]
1442pub struct GcpFirestoreKvHeartbeatData {
1443 pub status: KvHeartbeatStatus,
1444 pub database_name: String,
1445 pub project_id: Option<String>,
1446 pub endpoint: Option<String>,
1447 pub location_id: Option<String>,
1448 pub database_type: Option<String>,
1449 pub concurrency_mode: Option<String>,
1450 pub app_engine_integration_mode: Option<String>,
1451 pub delete_protection_state: Option<String>,
1452 pub point_in_time_recovery_enablement: Option<String>,
1453 pub version_retention_period: Option<String>,
1454 pub earliest_version_time: Option<String>,
1455 pub create_time: Option<String>,
1456 pub update_time: Option<String>,
1457 pub delete_time: Option<String>,
1458 pub database_edition: Option<String>,
1459 pub cmek_enabled: bool,
1460 pub source_info_present: bool,
1461}
1462
1463#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1464#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1465#[serde(rename_all = "camelCase")]
1466pub struct AzureTableKvHeartbeatData {
1467 pub status: KvHeartbeatStatus,
1468 pub table_name: String,
1469 pub storage_account_name: String,
1470 pub resource_group: Option<String>,
1471 pub endpoint: Option<String>,
1472 pub storage_account_resource_id: Option<String>,
1473 pub storage_account_location: Option<String>,
1474 pub storage_account_kind: Option<String>,
1475 pub storage_account_provisioning_state: Option<String>,
1476 pub storage_account_primary_status: Option<String>,
1477 pub table_exists: bool,
1478 pub signed_identifier_count: Option<u32>,
1479}
1480
1481#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1482#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1483#[serde(rename_all = "camelCase")]
1484pub struct LocalKvHeartbeatData {
1485 pub status: KvHeartbeatStatus,
1486 pub name: String,
1487 pub path: String,
1488 pub path_exists: bool,
1489 pub is_directory: Option<bool>,
1490 pub cloud_metadata_supported: bool,
1491}
1492
1493#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1494#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1495#[serde(tag = "backend", rename_all = "camelCase")]
1496pub enum PostgresHeartbeatData {
1497 Aurora(AuroraPostgresHeartbeatData),
1499 CloudSql(GcpCloudSqlPostgresHeartbeatData),
1501 FlexibleServer(AzureFlexibleServerPostgresHeartbeatData),
1503 Local(LocalPostgresHeartbeatData),
1505}
1506
1507#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1508#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1509#[serde(rename_all = "camelCase")]
1510pub struct PostgresHeartbeatStatus {
1511 pub health: ObservedHealth,
1512 pub lifecycle: ProviderLifecycleState,
1513 pub message: Option<String>,
1514 pub stale: bool,
1515 pub partial: bool,
1516 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1517}
1518
1519impl Default for PostgresHeartbeatStatus {
1520 fn default() -> Self {
1521 Self {
1522 health: ObservedHealth::Unknown,
1523 lifecycle: ProviderLifecycleState::Unknown,
1524 message: None,
1525 stale: false,
1526 partial: false,
1527 collection_issues: vec![],
1528 }
1529 }
1530}
1531
1532#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1533#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1534#[serde(tag = "backend", rename_all = "camelCase")]
1535pub enum AiHeartbeatData {
1536 AwsBedrock(AwsBedrockAiHeartbeatData),
1537 GcpVertex(GcpVertexAiHeartbeatData),
1538 AzureFoundry(AzureFoundryAiHeartbeatData),
1539 External(ExternalAiHeartbeatData),
1540}
1541
1542#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1543#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1544#[serde(rename_all = "camelCase")]
1545pub struct AiHeartbeatStatus {
1546 pub health: ObservedHealth,
1547 pub lifecycle: ProviderLifecycleState,
1548 pub message: Option<String>,
1549 pub stale: bool,
1550 pub partial: bool,
1551 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1552}
1553
1554impl Default for AiHeartbeatStatus {
1555 fn default() -> Self {
1556 Self {
1559 health: ObservedHealth::Healthy,
1560 lifecycle: ProviderLifecycleState::Running,
1561 message: None,
1562 stale: false,
1563 partial: false,
1564 collection_issues: vec![],
1565 }
1566 }
1567}
1568
1569#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1570#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1571#[serde(rename_all = "camelCase")]
1572pub struct LocalPostgresHeartbeatData {
1573 pub status: PostgresHeartbeatStatus,
1574 pub name: String,
1575 pub port: Option<u16>,
1576 pub version: String,
1577 pub process_running: bool,
1578}
1579
1580#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1581#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1582#[serde(rename_all = "camelCase")]
1583pub struct AuroraPostgresHeartbeatData {
1584 pub status: PostgresHeartbeatStatus,
1585 pub cluster_identifier: String,
1586 #[serde(skip_serializing_if = "Option::is_none")]
1587 pub engine_version: Option<String>,
1588 #[serde(skip_serializing_if = "Option::is_none")]
1589 pub endpoint: Option<String>,
1590 #[serde(skip_serializing_if = "Option::is_none")]
1592 pub serverless_capacity: Option<f64>,
1593 pub never_pauses: bool,
1596}
1597
1598#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1599#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1600#[serde(rename_all = "camelCase")]
1601pub struct GcpCloudSqlPostgresHeartbeatData {
1602 pub status: PostgresHeartbeatStatus,
1603 pub instance_name: String,
1604 #[serde(skip_serializing_if = "Option::is_none")]
1605 pub state: Option<String>,
1606 #[serde(skip_serializing_if = "Option::is_none")]
1607 pub database_version: Option<String>,
1608}
1609
1610#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1611#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1612#[serde(rename_all = "camelCase")]
1613pub struct AzureFlexibleServerPostgresHeartbeatData {
1614 pub status: PostgresHeartbeatStatus,
1615 pub server_name: String,
1616 #[serde(skip_serializing_if = "Option::is_none")]
1617 pub state: Option<String>,
1618 #[serde(skip_serializing_if = "Option::is_none")]
1619 pub version: Option<String>,
1620}
1621
1622#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1623#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1624#[serde(rename_all = "camelCase")]
1625pub struct AwsBedrockAiHeartbeatData {
1626 pub status: AiHeartbeatStatus,
1627 pub region: String,
1628}
1629
1630#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1631#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1632#[serde(rename_all = "camelCase")]
1633pub struct GcpVertexAiHeartbeatData {
1634 pub status: AiHeartbeatStatus,
1635 pub project: String,
1636 pub location: String,
1637}
1638
1639#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1640#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1641#[serde(rename_all = "camelCase")]
1642pub struct AzureFoundryAiHeartbeatData {
1643 pub status: AiHeartbeatStatus,
1644 pub account_name: String,
1645 pub endpoint: Option<String>,
1646 pub resource_group: Option<String>,
1647 pub location: Option<String>,
1648}
1649
1650#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1651#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1652#[serde(rename_all = "camelCase")]
1653pub struct ExternalAiHeartbeatData {
1654 pub status: AiHeartbeatStatus,
1655 pub provider: String,
1658}
1659
1660#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1661#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1662#[serde(tag = "backend", rename_all = "camelCase")]
1663pub enum VaultHeartbeatData {
1664 AwsParameterStore(AwsParameterStoreVaultHeartbeatData),
1665 GcpSecretManager(GcpSecretManagerVaultHeartbeatData),
1666 AzureKeyVault(AzureKeyVaultHeartbeatData),
1667 KubernetesSecret(KubernetesSecretVaultHeartbeatData),
1668 Local(LocalVaultHeartbeatData),
1669}
1670
1671#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1672#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1673#[serde(rename_all = "camelCase")]
1674pub struct VaultHeartbeatStatus {
1675 pub health: ObservedHealth,
1676 pub lifecycle: ProviderLifecycleState,
1677 pub message: Option<String>,
1678 pub stale: bool,
1679 pub partial: bool,
1680 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1681}
1682
1683impl Default for VaultHeartbeatStatus {
1684 fn default() -> Self {
1685 Self {
1686 health: ObservedHealth::Healthy,
1687 lifecycle: ProviderLifecycleState::Running,
1688 message: None,
1689 stale: false,
1690 partial: false,
1691 collection_issues: vec![],
1692 }
1693 }
1694}
1695
1696#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1697#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1698#[serde(rename_all = "camelCase")]
1699pub struct AwsParameterStoreVaultHeartbeatData {
1700 pub status: VaultHeartbeatStatus,
1701 pub account_id: String,
1702 pub region: String,
1703 pub prefix: String,
1704 pub parameter_metadata_sampled: bool,
1705 pub sampled_parameter_count: Option<u32>,
1706 pub sampled_secure_string_count: Option<u32>,
1707 pub sampled_string_count: Option<u32>,
1708 pub sampled_string_list_count: Option<u32>,
1709 pub sampled_advanced_tier_count: Option<u32>,
1710 pub sampled_kms_key_metadata_present_count: Option<u32>,
1711 pub latest_modified_at: Option<DateTime<Utc>>,
1712 pub has_more_parameters: Option<bool>,
1713}
1714
1715#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1716#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1717#[serde(rename_all = "camelCase")]
1718pub struct GcpSecretManagerVaultHeartbeatData {
1719 pub status: VaultHeartbeatStatus,
1720 pub project_id: String,
1721 pub location: String,
1722 pub prefix: String,
1723 pub secret_metadata_listed: bool,
1724}
1725
1726#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1727#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1728#[serde(rename_all = "camelCase")]
1729pub struct AzureKeyVaultHeartbeatData {
1730 pub status: VaultHeartbeatStatus,
1731 pub name: String,
1732 pub resource_group: Option<String>,
1733 pub resource_id: Option<String>,
1734 pub location: Option<String>,
1735 pub vault_uri: Option<String>,
1736 pub provisioning_state: Option<String>,
1737 pub sku_family: Option<String>,
1738 pub sku_name: Option<String>,
1739 pub soft_delete_enabled: bool,
1740 pub soft_delete_retention_days: i32,
1741 pub purge_protection_enabled: Option<bool>,
1742 pub rbac_authorization_enabled: bool,
1743 pub public_network_access: String,
1744 pub access_policy_count: u32,
1745 pub private_endpoint_connection_count: u32,
1746 pub secret_metadata_listed: bool,
1747}
1748
1749#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1750#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1751#[serde(rename_all = "camelCase")]
1752pub struct KubernetesSecretVaultHeartbeatData {
1753 pub status: VaultHeartbeatStatus,
1754 pub namespace: String,
1755 pub prefix: String,
1756 pub secret_metadata_listed: bool,
1757}
1758
1759#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1760#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1761#[serde(rename_all = "camelCase")]
1762pub struct LocalVaultHeartbeatData {
1763 pub status: VaultHeartbeatStatus,
1764 pub path: String,
1765 pub path_exists: bool,
1766 pub is_directory: Option<bool>,
1767 pub readonly: Option<bool>,
1768 pub modified_at: Option<DateTime<Utc>>,
1769 pub secret_metadata_listed: bool,
1770}
1771
1772#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1773#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1774#[serde(tag = "backend", rename_all = "camelCase")]
1775pub enum ServiceAccountHeartbeatData {
1776 AwsIamRole(AwsIamRoleServiceAccountHeartbeatData),
1777 GcpServiceAccount(GcpServiceAccountHeartbeatData),
1778 AzureManagedIdentity(AzureManagedIdentityServiceAccountHeartbeatData),
1779 Local(LocalServiceAccountHeartbeatData),
1780}
1781
1782#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1783#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1784#[serde(rename_all = "camelCase")]
1785pub struct ServiceAccountHeartbeatStatus {
1786 pub health: ObservedHealth,
1787 pub lifecycle: ProviderLifecycleState,
1788 pub message: Option<String>,
1789 pub stale: bool,
1790 pub partial: bool,
1791 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1792}
1793
1794#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1795#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1796#[serde(rename_all = "camelCase")]
1797pub struct AwsIamRoleServiceAccountHeartbeatData {
1798 pub status: ServiceAccountHeartbeatStatus,
1799 pub role_name: String,
1800 pub role_arn: String,
1801 pub role_id: String,
1802 pub path: String,
1803 pub create_date: String,
1804 pub description: Option<String>,
1805 pub max_session_duration: Option<i32>,
1806 pub assume_role_policy_present: bool,
1807 pub permissions_boundary_type: Option<String>,
1808 pub permissions_boundary_arn: Option<String>,
1809 pub tag_count: u32,
1810 pub managed_tag_count: u32,
1811 pub attached_policy_count: u32,
1812 pub attached_policy_names: Vec<String>,
1813 pub inline_policy_count: u32,
1814 pub inline_policy_names: Vec<String>,
1815 pub stack_permissions_applied: bool,
1816 pub last_used_date: Option<String>,
1817 pub last_used_region: Option<String>,
1818}
1819
1820#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1821#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1822#[serde(rename_all = "camelCase")]
1823pub struct GcpServiceAccountHeartbeatData {
1824 pub status: ServiceAccountHeartbeatStatus,
1825 pub name: Option<String>,
1826 pub project_id: Option<String>,
1827 pub unique_id: Option<String>,
1828 pub email: String,
1829 pub display_name: Option<String>,
1830 pub description: Option<String>,
1831 pub oauth2_client_id: Option<String>,
1832 pub disabled: Option<bool>,
1833 pub etag: Option<String>,
1834 pub project_binding_count: u32,
1835 pub project_roles: Vec<String>,
1836 pub service_account_binding_count: u32,
1837 pub service_account_roles: Vec<String>,
1838}
1839
1840#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1841#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1842#[serde(rename_all = "camelCase")]
1843pub struct AzureManagedIdentityServiceAccountHeartbeatData {
1844 pub status: ServiceAccountHeartbeatStatus,
1845 pub name: String,
1846 pub resource_id: String,
1847 pub resource_group: String,
1848 pub location: String,
1849 pub type_: Option<String>,
1850 pub client_id: Option<String>,
1851 pub principal_id: Option<String>,
1852 pub tenant_id: Option<String>,
1853 pub isolation_scope: Option<String>,
1854 pub managed_tag_count: u32,
1855 pub role_assignment_count: u32,
1856 pub role_assignment_ids: Vec<String>,
1857 pub custom_role_definition_count: u32,
1858 pub custom_role_definition_ids: Vec<String>,
1859 pub stack_permissions_applied: bool,
1860}
1861
1862#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1863#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1864#[serde(rename_all = "camelCase")]
1865pub struct LocalServiceAccountHeartbeatData {
1866 pub status: ServiceAccountHeartbeatStatus,
1867 pub identity: String,
1868 pub configured: bool,
1869}
1870
1871#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1872#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1873#[serde(tag = "backend", rename_all = "camelCase")]
1874pub enum NetworkHeartbeatData {
1875 AwsVpc(AwsVpcNetworkHeartbeatData),
1876 GcpVpc(GcpVpcNetworkHeartbeatData),
1877 AzureVnet(AzureVnetNetworkHeartbeatData),
1878}
1879
1880#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1881#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1882#[serde(rename_all = "camelCase")]
1883pub struct NetworkHeartbeatStatus {
1884 pub health: ObservedHealth,
1885 pub lifecycle: ProviderLifecycleState,
1886 pub message: Option<String>,
1887 pub stale: bool,
1888 pub partial: bool,
1889 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1890}
1891
1892#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1893#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1894#[serde(rename_all = "camelCase")]
1895pub struct AwsVpcNetworkHeartbeatData {
1896 pub status: NetworkHeartbeatStatus,
1897 pub vpc_id: Option<String>,
1898 pub vpc_state: Option<String>,
1899 pub cidr_block: Option<String>,
1900 pub public_subnet_ids: Vec<String>,
1901 pub private_subnet_ids: Vec<String>,
1902 pub availability_zones: Vec<String>,
1903 pub internet_gateway_id: Option<String>,
1904 pub nat_gateway_id: Option<String>,
1905 pub route_table_count: u32,
1906 pub security_group_id: Option<String>,
1907 pub is_byo_vpc: bool,
1908}
1909
1910#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1911#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1912#[serde(rename_all = "camelCase")]
1913pub struct GcpVpcNetworkHeartbeatData {
1914 pub status: NetworkHeartbeatStatus,
1915 pub network_name: Option<String>,
1916 pub network_self_link: Option<String>,
1917 pub subnetwork_name: Option<String>,
1918 pub subnetwork_self_link: Option<String>,
1919 pub region: Option<String>,
1920 pub cidr_block: Option<String>,
1921 pub router_name: Option<String>,
1922 pub cloud_nat_name: Option<String>,
1923 pub firewall_name: Option<String>,
1924 pub is_byo_vpc: bool,
1925}
1926
1927#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1928#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1929#[serde(rename_all = "camelCase")]
1930pub struct AzureVnetNetworkHeartbeatData {
1931 pub status: NetworkHeartbeatStatus,
1932 pub vnet_name: Option<String>,
1933 pub vnet_resource_id: Option<String>,
1934 pub resource_group: Option<String>,
1935 pub location: Option<String>,
1936 pub cidr_block: Option<String>,
1937 pub public_subnet_name: Option<String>,
1938 pub private_subnet_name: Option<String>,
1939 pub application_gateway_subnet_name: Option<String>,
1940 pub private_endpoint_subnet_name: Option<String>,
1941 pub nat_gateway_id: Option<String>,
1942 pub public_ip_id: Option<String>,
1943 pub nsg_id: Option<String>,
1944 pub is_byo_vnet: bool,
1945 pub last_byo_vnet_verification_error_code: Option<String>,
1946}
1947
1948#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1949#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1950#[serde(tag = "backend", rename_all = "camelCase")]
1951pub enum RemoteStackManagementHeartbeatData {
1952 AwsIamRole(AwsRemoteStackManagementHeartbeatData),
1953 GcpServiceAccount(GcpRemoteStackManagementHeartbeatData),
1954 AzureManagedIdentity(AzureRemoteStackManagementHeartbeatData),
1955}
1956
1957#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1958#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1959#[serde(rename_all = "camelCase")]
1960pub struct RemoteStackManagementHeartbeatStatus {
1961 pub health: ObservedHealth,
1962 pub lifecycle: ProviderLifecycleState,
1963 pub message: Option<String>,
1964 pub stale: bool,
1965 pub partial: bool,
1966 pub collection_issues: Vec<HeartbeatCollectionIssue>,
1967}
1968
1969#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1970#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1971#[serde(rename_all = "camelCase")]
1972pub struct AwsRemoteStackManagementHeartbeatData {
1973 pub status: RemoteStackManagementHeartbeatStatus,
1974 pub role_name: Option<String>,
1975 pub role_arn: Option<String>,
1976 pub management_permissions_applied: bool,
1977}
1978
1979#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1980#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1981#[serde(rename_all = "camelCase")]
1982pub struct GcpRemoteStackManagementHeartbeatData {
1983 pub status: RemoteStackManagementHeartbeatStatus,
1984 pub service_account_email: Option<String>,
1985 pub service_account_unique_id: Option<String>,
1986 pub role_bound: bool,
1987 pub impersonation_granted: bool,
1988}
1989
1990#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1991#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
1992#[serde(rename_all = "camelCase")]
1993pub struct AzureRemoteStackManagementHeartbeatData {
1994 pub status: RemoteStackManagementHeartbeatStatus,
1995 pub uami_resource_id: Option<String>,
1996 pub uami_client_id: Option<String>,
1997 pub uami_principal_id: Option<String>,
1998 pub tenant_id: Option<String>,
1999 pub fic_name: Option<String>,
2000 pub role_definition_id: Option<String>,
2001 pub role_assignment_ids: Vec<String>,
2002}
2003
2004#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2005#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2006#[serde(tag = "backend", rename_all = "camelCase")]
2007pub enum ArtifactRegistryHeartbeatData {
2008 AwsEcr(AwsEcrArtifactRegistryHeartbeatData),
2009 GcpArtifactRegistry(GcpArtifactRegistryHeartbeatData),
2010 AzureContainerRegistry(AzureContainerRegistryHeartbeatData),
2011 Local(LocalArtifactRegistryHeartbeatData),
2012}
2013
2014#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2015#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2016#[serde(rename_all = "camelCase")]
2017pub struct ArtifactRegistryHeartbeatStatus {
2018 pub health: ObservedHealth,
2019 pub lifecycle: ProviderLifecycleState,
2020 pub message: Option<String>,
2021 pub stale: bool,
2022 pub partial: bool,
2023 pub collection_issues: Vec<HeartbeatCollectionIssue>,
2024}
2025
2026#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2027#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2028#[serde(rename_all = "camelCase")]
2029pub struct AwsEcrArtifactRegistryHeartbeatData {
2030 pub status: ArtifactRegistryHeartbeatStatus,
2031 pub registry_id: String,
2032 pub region: String,
2033 pub registry_uri: String,
2034 pub repository_prefix: String,
2035 pub pull_role_arn: Option<String>,
2036 pub push_role_arn: Option<String>,
2037 pub repository_count: u32,
2038 pub repositories_truncated: bool,
2039 pub repositories: Vec<AwsEcrRepositoryHeartbeatData>,
2040}
2041
2042#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2043#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2044#[serde(rename_all = "camelCase")]
2045pub struct AwsEcrRepositoryHeartbeatData {
2046 pub repository_arn: String,
2047 pub registry_id: String,
2048 pub repository_name: String,
2049 pub repository_uri: String,
2050 pub created_at: f64,
2051 pub image_tag_mutability: Option<String>,
2052 pub scan_on_push: Option<bool>,
2053 pub encryption_type: Option<String>,
2054 pub kms_key_present: bool,
2055}
2056
2057#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2058#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2059#[serde(rename_all = "camelCase")]
2060pub struct GcpArtifactRegistryHeartbeatData {
2061 pub status: ArtifactRegistryHeartbeatStatus,
2062 pub project_id: String,
2063 pub location: String,
2064 pub repository_id: String,
2065 pub name: Option<String>,
2066 pub format: Option<String>,
2067 pub mode: Option<String>,
2068 pub description: Option<String>,
2069 pub label_count: u32,
2070 pub cleanup_policy_count: u32,
2071 pub cleanup_policy_dry_run: Option<bool>,
2072 pub kms_key_name_present: bool,
2073 pub size_bytes: Option<String>,
2074 pub satisfies_pzs: Option<bool>,
2075 pub create_time: Option<String>,
2076 pub update_time: Option<String>,
2077 pub iam_policy_etag_present: bool,
2078 pub iam_binding_count: u32,
2079 pub iam_roles: Vec<String>,
2080 pub pull_service_account_email: Option<String>,
2081 pub push_service_account_email: Option<String>,
2082}
2083
2084#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2085#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2086#[serde(rename_all = "camelCase")]
2087pub struct AzureContainerRegistryHeartbeatData {
2088 pub status: ArtifactRegistryHeartbeatStatus,
2089 pub name: String,
2090 pub resource_id: Option<String>,
2091 pub resource_group: String,
2092 pub location: String,
2093 pub type_: Option<String>,
2094 pub login_server: Option<String>,
2095 pub sku_name: String,
2096 pub sku_tier: Option<String>,
2097 pub provisioning_state: Option<String>,
2098 pub admin_user_enabled: bool,
2099 pub anonymous_pull_enabled: bool,
2100 pub public_network_access: String,
2101 pub network_rule_bypass_options: String,
2102 pub network_rule_default_action: Option<String>,
2103 pub ip_rule_count: u32,
2104 pub encryption_status: Option<String>,
2105 pub encryption_key_vault_uri_present: bool,
2106 pub encryption_key_identifier_present: bool,
2107 pub policies_present: bool,
2108 pub policy_count: u32,
2109 pub private_endpoint_connection_count: u32,
2110 pub data_endpoint_enabled: Option<bool>,
2111 pub data_endpoint_host_names: Vec<String>,
2112 pub zone_redundancy: String,
2113 pub creation_date: Option<String>,
2114 pub managed_tag_count: u32,
2115}
2116
2117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2118#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2119#[serde(rename_all = "camelCase")]
2120pub struct LocalArtifactRegistryHeartbeatData {
2121 pub status: ArtifactRegistryHeartbeatStatus,
2122 pub registry_url: String,
2123 pub reachable: bool,
2124}
2125
2126#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2127#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2128#[serde(tag = "backend", rename_all = "camelCase")]
2129pub enum BuildHeartbeatData {
2130 AwsCodeBuild(AwsCodeBuildHeartbeatData),
2131 GcpCloudBuild(GcpCloudBuildHeartbeatData),
2132 AzureContainerApps(AzureContainerAppsBuildHeartbeatData),
2133 KubernetesJob(KubernetesBuildHeartbeatData),
2134}
2135
2136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2137#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2138#[serde(rename_all = "camelCase")]
2139pub struct BuildHeartbeatStatus {
2140 pub health: ObservedHealth,
2141 pub lifecycle: ProviderLifecycleState,
2142 pub message: Option<String>,
2143 pub stale: bool,
2144 pub partial: bool,
2145 pub collection_issues: Vec<HeartbeatCollectionIssue>,
2146}
2147
2148#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2149#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2150#[serde(rename_all = "camelCase")]
2151pub struct AwsCodeBuildHeartbeatData {
2152 pub status: BuildHeartbeatStatus,
2153 pub project_name: String,
2154 pub project_arn: Option<String>,
2155 pub description: Option<String>,
2156 pub source_type: Option<String>,
2157 pub artifacts_type: Option<String>,
2158 pub artifacts_encryption_disabled: Option<bool>,
2159 pub environment_type: Option<String>,
2160 pub environment_image: Option<String>,
2161 pub compute_type: Option<String>,
2162 pub image_pull_credentials_type: Option<String>,
2163 pub privileged_mode: Option<bool>,
2164 pub environment_variable_count: u32,
2165 pub service_role_present: bool,
2166 pub encryption_key_present: bool,
2167 pub cloud_watch_logs_status: Option<String>,
2168 pub s3_logs_status: Option<String>,
2169 pub timeout_in_minutes: Option<i32>,
2170 pub queued_timeout_in_minutes: Option<i32>,
2171 pub created: Option<f64>,
2172 pub last_modified: Option<f64>,
2173}
2174
2175#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2176#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2177#[serde(rename_all = "camelCase")]
2178pub struct GcpCloudBuildHeartbeatData {
2179 pub status: BuildHeartbeatStatus,
2180 pub project_id: String,
2181 pub location: String,
2182 pub build_config_id: String,
2183 pub service_account: Option<String>,
2184 pub environment_variable_count: u32,
2185}
2186
2187#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2188#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2189#[serde(rename_all = "camelCase")]
2190pub struct AzureContainerAppsBuildHeartbeatData {
2191 pub status: BuildHeartbeatStatus,
2192 pub managed_environment_id: String,
2193 pub resource_group_name: String,
2194 pub managed_identity_id: Option<String>,
2195 pub resource_prefix: Option<String>,
2196 pub environment_variable_count: u32,
2197}
2198
2199#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2200#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2201#[serde(rename_all = "camelCase")]
2202pub struct KubernetesBuildHeartbeatData {
2203 pub status: BuildHeartbeatStatus,
2204 pub job_name: String,
2205 pub namespace: String,
2206 pub active: Option<i32>,
2207 pub succeeded: Option<i32>,
2208 pub failed: Option<i32>,
2209 pub start_time: Option<DateTime<Utc>>,
2210 pub completion_time: Option<DateTime<Utc>>,
2211 pub condition_count: u32,
2212 pub image_digest: Option<String>,
2213 pub events: Vec<KubernetesEventSnapshot>,
2214}
2215
2216#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2217#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2218#[serde(tag = "backend", rename_all = "camelCase")]
2219pub enum ServiceActivationHeartbeatData {
2220 GcpServiceUsage(GcpServiceUsageActivationHeartbeatData),
2221 AzureResourceProvider(AzureResourceProviderActivationHeartbeatData),
2222}
2223
2224#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2225#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2226#[serde(rename_all = "camelCase")]
2227pub struct ServiceActivationHeartbeatStatus {
2228 pub health: ObservedHealth,
2229 pub lifecycle: ProviderLifecycleState,
2230 pub message: Option<String>,
2231 pub stale: bool,
2232 pub partial: bool,
2233 pub collection_issues: Vec<HeartbeatCollectionIssue>,
2234}
2235
2236impl Default for ServiceActivationHeartbeatStatus {
2237 fn default() -> Self {
2238 Self {
2239 health: ObservedHealth::Healthy,
2240 lifecycle: ProviderLifecycleState::Running,
2241 message: None,
2242 stale: false,
2243 partial: false,
2244 collection_issues: vec![],
2245 }
2246 }
2247}
2248
2249#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2250#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2251#[serde(rename_all = "camelCase")]
2252pub struct GcpServiceUsageActivationHeartbeatData {
2253 pub status: ServiceActivationHeartbeatStatus,
2254 pub project_id: String,
2255 pub service_name: String,
2256 pub service_resource_name: Option<String>,
2257 pub title: Option<String>,
2258 pub state: Option<String>,
2259 pub enabled: bool,
2260 pub last_operation_name: Option<String>,
2261}
2262
2263#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2264#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2265#[serde(rename_all = "camelCase")]
2266pub struct AzureResourceProviderActivationHeartbeatData {
2267 pub status: ServiceActivationHeartbeatStatus,
2268 pub namespace: String,
2269 pub provider_id: Option<String>,
2270 pub registration_state: Option<String>,
2271 pub registration_policy: Option<String>,
2272 pub resource_type_count: u32,
2273 pub registered: bool,
2274}
2275
2276#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2277#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2278#[serde(rename_all = "camelCase")]
2279pub struct AzureResourceGroupHeartbeatData {
2280 pub status: AzureResourceGroupHeartbeatStatus,
2281 pub name: String,
2282 pub resource_id: Option<String>,
2283 pub location: Option<String>,
2284 pub provisioning_state: Option<String>,
2285 pub managed_tags: BTreeMap<String, String>,
2286}
2287
2288#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2289#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2290#[serde(rename_all = "camelCase")]
2291pub struct AzureResourceGroupHeartbeatStatus {
2292 pub health: ObservedHealth,
2293 pub lifecycle: ProviderLifecycleState,
2294 pub message: Option<String>,
2295 pub stale: bool,
2296 pub partial: bool,
2297 pub collection_issues: Vec<HeartbeatCollectionIssue>,
2298}
2299
2300impl Default for AzureResourceGroupHeartbeatStatus {
2301 fn default() -> Self {
2302 Self {
2303 health: ObservedHealth::Healthy,
2304 lifecycle: ProviderLifecycleState::Running,
2305 message: None,
2306 stale: false,
2307 partial: false,
2308 collection_issues: vec![],
2309 }
2310 }
2311}
2312
2313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2314#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2315#[serde(rename_all = "camelCase")]
2316pub struct AzureStorageAccountHeartbeatData {
2317 pub status: StorageHeartbeatStatus,
2318 pub name: String,
2319 pub resource_id: Option<String>,
2320 pub resource_group: Option<String>,
2321 pub location: Option<String>,
2322 pub kind: Option<String>,
2323 pub sku_name: Option<String>,
2324 pub sku_tier: Option<String>,
2325 pub provisioning_state: Option<String>,
2326 pub primary_endpoints: AzureStorageAccountEndpoints,
2327 pub secondary_endpoints: AzureStorageAccountEndpoints,
2328 pub public_network_access: Option<String>,
2329 pub allow_blob_public_access: Option<bool>,
2330 pub allow_shared_key_access: Option<bool>,
2331 pub minimum_tls_version: Option<String>,
2332 pub supports_https_traffic_only: Option<bool>,
2333 pub encryption_key_source: Option<String>,
2334 pub require_infrastructure_encryption: Option<bool>,
2335 pub network_default_action: Option<String>,
2336 pub network_bypass: Option<String>,
2337 pub network_ip_rule_count: Option<u32>,
2338 pub network_virtual_network_rule_count: Option<u32>,
2339 pub network_resource_access_rule_count: Option<u32>,
2340}
2341
2342#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
2343#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2344#[serde(rename_all = "camelCase")]
2345pub struct AzureStorageAccountEndpoints {
2346 pub blob: Option<String>,
2347 pub dfs: Option<String>,
2348 pub file: Option<String>,
2349 pub queue: Option<String>,
2350 pub table: Option<String>,
2351 pub web: Option<String>,
2352}
2353
2354#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2355#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2356#[serde(rename_all = "camelCase")]
2357pub struct AzureContainerAppsEnvironmentHeartbeatData {
2358 pub status: AzureContainerAppsEnvironmentHeartbeatStatus,
2359 pub name: String,
2360 pub resource_id: Option<String>,
2361 pub resource_group: Option<String>,
2362 pub location: Option<String>,
2363 pub kind: Option<String>,
2364 pub provisioning_state: Option<String>,
2365 pub default_domain: Option<String>,
2366 pub static_ip: Option<String>,
2367 pub custom_domain_verification_id: Option<String>,
2368 pub infrastructure_resource_group: Option<String>,
2369 pub event_stream_endpoint: Option<String>,
2370 pub zone_redundant: Option<bool>,
2371 pub workload_profile_count: u32,
2372 pub workload_profiles: Vec<AzureContainerAppsEnvironmentWorkloadProfile>,
2373}
2374
2375#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2376#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2377#[serde(rename_all = "camelCase")]
2378pub struct AzureContainerAppsEnvironmentHeartbeatStatus {
2379 pub health: ObservedHealth,
2380 pub lifecycle: ProviderLifecycleState,
2381 pub message: Option<String>,
2382 pub stale: bool,
2383 pub partial: bool,
2384 pub collection_issues: Vec<HeartbeatCollectionIssue>,
2385}
2386
2387#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2388#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2389#[serde(rename_all = "camelCase")]
2390pub struct AzureContainerAppsEnvironmentWorkloadProfile {
2391 pub name: String,
2392 pub workload_profile_type: String,
2393 pub minimum_count: Option<i32>,
2394 pub maximum_count: Option<i32>,
2395}
2396
2397#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2398#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2399#[serde(rename_all = "camelCase")]
2400pub struct AzureServiceBusNamespaceHeartbeatData {
2401 pub status: QueueHeartbeatStatus,
2402 pub name: String,
2403 pub resource_id: Option<String>,
2404 pub resource_group: Option<String>,
2405 pub location: Option<String>,
2406 pub sku_name: Option<String>,
2407 pub sku_tier: Option<String>,
2408 pub sku_capacity: Option<i32>,
2409 pub namespace_status: Option<String>,
2410 pub provisioning_state: Option<String>,
2411 pub service_bus_endpoint: Option<String>,
2412 pub metric_id: Option<String>,
2413 pub public_network_access: Option<String>,
2414 pub disable_local_auth: Option<bool>,
2415 pub minimum_tls_version: Option<String>,
2416 pub premium_messaging_partitions: Option<i32>,
2417 pub private_endpoint_connection_count: u32,
2418 pub zone_redundant: Option<bool>,
2419 pub created_at: Option<String>,
2420 pub updated_at: Option<String>,
2421}
2422
2423#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2424#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
2425#[serde(rename_all = "camelCase")]
2426pub struct NamedResourceDetail {
2427 pub name: String,
2428 pub region: Option<String>,
2429}
2430
2431#[cfg(test)]
2432mod tests {
2433 use super::*;
2434 use chrono::TimeZone as _;
2435 use serde_json::json;
2436
2437 fn observed_at() -> DateTime<Utc> {
2438 Utc.with_ymd_and_hms(2026, 5, 28, 10, 30, 0).unwrap()
2439 }
2440
2441 fn workload_status() -> WorkloadHeartbeatStatus {
2442 WorkloadHeartbeatStatus {
2443 health: ObservedHealth::Healthy,
2444 lifecycle: ProviderLifecycleState::Running,
2445 message: None,
2446 stale: false,
2447 partial: false,
2448 collection_issues: vec![],
2449 }
2450 }
2451
2452 fn workload_replicas() -> WorkloadReplicaStatus {
2453 WorkloadReplicaStatus {
2454 desired: Some(2),
2455 current: Some(2),
2456 ready: Some(1),
2457 available: Some(1),
2458 updated: Some(2),
2459 misscheduled: None,
2460 }
2461 }
2462
2463 fn heartbeat(data: ResourceHeartbeatData, resource_type: &str) -> ResourceHeartbeat {
2464 ResourceHeartbeat {
2465 deployment_id: Some("dep_123".to_string()),
2466 resource_id: "api".to_string(),
2467 resource_type: ResourceType::from(resource_type),
2468 controller_platform: Platform::Kubernetes,
2469 backend: HeartbeatBackend::Kubernetes,
2470 observed_at: observed_at(),
2471 data,
2472 raw: vec![RawHeartbeatSnippet {
2473 source: "kubernetes/apps/v1/deployments/api".to_string(),
2474 format: RawHeartbeatSnippetFormat::Json,
2475 collected_at: observed_at(),
2476 body: r#"{"readyReplicas":1}"#.to_string(),
2477 truncated: false,
2478 }],
2479 }
2480 }
2481
2482 #[test]
2483 fn resource_heartbeat_roundtrips_managed_resource_data() {
2484 let heartbeat_json = serde_json::to_value(heartbeat(
2485 ResourceHeartbeatData::Container(ContainerHeartbeatData::Kubernetes(
2486 KubernetesContainerHeartbeatData {
2487 status: workload_status(),
2488 namespace: "default".to_string(),
2489 name: "api".to_string(),
2490 workload_kind: KubernetesWorkloadKind::Deployment,
2491 replicas: workload_replicas(),
2492 restarts: None,
2493 cpu: None,
2494 memory: None,
2495 workload: None,
2496 pods: vec![],
2497 events: vec![],
2498 },
2499 )),
2500 "container",
2501 ))
2502 .unwrap();
2503
2504 let parsed: ResourceHeartbeat = serde_json::from_value(heartbeat_json).unwrap();
2505 assert_eq!(parsed.resource_id, "api");
2506 assert!(matches!(
2507 parsed.data,
2508 ResourceHeartbeatData::Container(ContainerHeartbeatData::Kubernetes(_))
2509 ));
2510 }
2511
2512 #[test]
2513 fn local_daemon_heartbeat_defaults_missing_daemon_name() {
2514 let mut value =
2515 serde_json::to_value(DaemonHeartbeatData::Local(LocalDaemonHeartbeatData {
2516 status: workload_status(),
2517 daemon_name: "agent".to_string(),
2518 runtime_id: "local-agent".to_string(),
2519 pid: None,
2520 command_supported: false,
2521 image_path_present: true,
2522 restart_count: None,
2523 exit_reason: None,
2524 daemon_instance: None,
2525 events: vec![],
2526 }))
2527 .unwrap();
2528
2529 value.as_object_mut().unwrap().remove("daemonName");
2530
2531 let parsed: DaemonHeartbeatData = serde_json::from_value(value).unwrap();
2532 match parsed {
2533 DaemonHeartbeatData::Local(data) => assert_eq!(data.daemon_name, ""),
2534 other => panic!("expected local daemon heartbeat, got {other:?}"),
2535 }
2536 }
2537
2538 #[test]
2539 fn container_heartbeat_serializes_resource_first_data() {
2540 let heartbeat = heartbeat(
2541 ResourceHeartbeatData::Container(ContainerHeartbeatData::Kubernetes(
2542 KubernetesContainerHeartbeatData {
2543 status: workload_status(),
2544 namespace: "default".to_string(),
2545 name: "api".to_string(),
2546 workload_kind: KubernetesWorkloadKind::Deployment,
2547 replicas: workload_replicas(),
2548 restarts: Some(1),
2549 cpu: Some(MetricSample {
2550 value: 0.5,
2551 unit: MetricUnit::Cores,
2552 }),
2553 memory: None,
2554 workload: None,
2555 pods: vec![],
2556 events: vec![],
2557 },
2558 )),
2559 "container",
2560 );
2561
2562 let value = serde_json::to_value(&heartbeat).unwrap();
2563
2564 assert_eq!(value["resourceType"], "container");
2565 assert_eq!(value["data"]["resourceType"], "container");
2566 assert_eq!(value["data"]["data"]["backend"], "kubernetes");
2567 assert_eq!(value["raw"][0]["body"], r#"{"readyReplicas":1}"#);
2568 assert!(value.get("collection").is_none());
2569 assert!(value["data"]["data"].get("summary").is_none());
2570 assert!(value["data"]["data"].get("detail").is_none());
2571 }
2572
2573 #[test]
2574 fn representative_workload_data_has_stable_tags() {
2575 let daemon = serde_json::to_value(ResourceHeartbeatData::Daemon(
2576 DaemonHeartbeatData::Kubernetes(KubernetesDaemonHeartbeatData {
2577 status: workload_status(),
2578 namespace: "default".to_string(),
2579 name: "agent".to_string(),
2580 replicas: workload_replicas(),
2581 restarts: Some(0),
2582 command_supported: true,
2583 cpu: None,
2584 memory: None,
2585 workload: None,
2586 pods: vec![],
2587 events: vec![],
2588 }),
2589 ))
2590 .unwrap();
2591 let worker = serde_json::to_value(ResourceHeartbeatData::Worker(
2592 WorkerHeartbeatData::AwsLambda(AwsLambdaWorkerHeartbeatData {
2593 status: workload_status(),
2594 function_name: "handler".to_string(),
2595 runtime: Some("nodejs22.x".to_string()),
2596 package_type: None,
2597 memory_size_mb: None,
2598 timeout_seconds: None,
2599 version: None,
2600 revision_id: None,
2601 last_modified: None,
2602 state: None,
2603 state_reason: None,
2604 state_reason_code: None,
2605 last_update_status: None,
2606 last_update_status_reason: None,
2607 last_update_status_reason_code: None,
2608 code_sha256: None,
2609 layer_count: 0,
2610 function_url_auth_type: None,
2611 function_url_cors_present: false,
2612 trigger_count: 0,
2613 }),
2614 ))
2615 .unwrap();
2616
2617 assert_eq!(daemon["resourceType"], "daemon");
2618 assert_eq!(daemon["data"]["backend"], "kubernetes");
2619 assert_eq!(worker["resourceType"], "worker");
2620 assert_eq!(worker["data"]["backend"], "awsLambda");
2621 }
2622
2623 #[test]
2624 fn representative_cluster_and_data_variants_have_optional_counts() {
2625 let cluster = serde_json::to_value(ResourceHeartbeatData::KubernetesCluster(
2626 KubernetesClusterHeartbeatData {
2627 status: WorkloadHeartbeatStatus {
2628 health: ObservedHealth::Healthy,
2629 lifecycle: ProviderLifecycleState::Running,
2630 message: None,
2631 stale: false,
2632 partial: false,
2633 collection_issues: vec![],
2634 },
2635 node_counts: ObservedCounts {
2636 desired: Some(3),
2637 current: Some(3),
2638 ready: None,
2639 },
2640 pod_counts: ObservedCounts {
2641 desired: None,
2642 current: Some(12),
2643 ready: Some(11),
2644 },
2645 cpu: None,
2646 memory: None,
2647 name: "prod".to_string(),
2648 region: Some("us-east-1".to_string()),
2649 namespace: None,
2650 version: Some("1.33".to_string()),
2651 node_statuses: vec![],
2652 events: vec![],
2653 },
2654 ))
2655 .unwrap();
2656 let queue = serde_json::to_value(ResourceHeartbeatData::Queue(QueueHeartbeatData::AwsSqs(
2657 AwsSqsQueueHeartbeatData {
2658 status: QueueHeartbeatStatus {
2659 health: ObservedHealth::Healthy,
2660 lifecycle: ProviderLifecycleState::Running,
2661 message: None,
2662 stale: false,
2663 partial: false,
2664 collection_issues: vec![],
2665 },
2666 name: "jobs".to_string(),
2667 region: Some("us-east-1".to_string()),
2668 queue_url: Some("https://sqs.us-east-1.amazonaws.com/123/jobs".to_string()),
2669 queue_arn: Some("arn:aws:sqs:us-east-1:123:jobs".to_string()),
2670 visibility_timeout_seconds: Some(30),
2671 message_retention_period_seconds: Some(345600),
2672 delay_seconds: Some(0),
2673 receive_message_wait_time_seconds: Some(0),
2674 maximum_message_size: Some(262144),
2675 redrive_policy: None,
2676 redrive_allow_policy: None,
2677 fifo_queue: Some(false),
2678 content_based_deduplication: None,
2679 deduplication_scope: None,
2680 fifo_throughput_limit: None,
2681 sse_enabled: Some(false),
2682 kms_master_key_id: None,
2683 kms_data_key_reuse_period_seconds: None,
2684 sqs_managed_sse_enabled: Some(false),
2685 approximate_visible_messages: Some(42),
2686 approximate_in_flight_messages: Some(1),
2687 approximate_delayed_messages: Some(0),
2688 approximate_counts: true,
2689 },
2690 )))
2691 .unwrap();
2692 let storage = serde_json::to_value(ResourceHeartbeatData::Storage(
2693 StorageHeartbeatData::AwsS3(AwsS3StorageHeartbeatData {
2694 status: StorageHeartbeatStatus {
2695 health: ObservedHealth::Healthy,
2696 lifecycle: ProviderLifecycleState::Running,
2697 message: None,
2698 stale: false,
2699 partial: false,
2700 collection_issues: vec![],
2701 },
2702 name: "assets".to_string(),
2703 region: Some("us-east-1".to_string()),
2704 bucket_location: Some("us-east-1".to_string()),
2705 versioning_status: Some("Enabled".to_string()),
2706 versioning_enabled: Some(true),
2707 lifecycle_present: false,
2708 lifecycle_rule_count: Some(0),
2709 encryption_config_present: true,
2710 encryption_enabled: Some(true),
2711 public_access_block_present: true,
2712 block_public_acls: Some(true),
2713 ignore_public_acls: Some(true),
2714 block_public_policy: Some(true),
2715 restrict_public_buckets: Some(true),
2716 bucket_policy_present: Some(false),
2717 bucket_acl_present: Some(true),
2718 }),
2719 ))
2720 .unwrap();
2721 let gcp_storage = serde_json::to_value(ResourceHeartbeatData::Storage(
2722 StorageHeartbeatData::GcpCloudStorage(GcpCloudStorageHeartbeatData {
2723 status: StorageHeartbeatStatus {
2724 health: ObservedHealth::Healthy,
2725 lifecycle: ProviderLifecycleState::Running,
2726 message: None,
2727 stale: false,
2728 partial: false,
2729 collection_issues: vec![],
2730 },
2731 name: "assets".to_string(),
2732 bucket_id: Some("project/assets".to_string()),
2733 location: Some("US".to_string()),
2734 location_type: Some("multi-region".to_string()),
2735 storage_class: Some("STANDARD".to_string()),
2736 versioning_enabled: Some(true),
2737 lifecycle_present: false,
2738 lifecycle_rule_count: Some(0),
2739 retention_policy_effective_time: None,
2740 retention_policy_is_locked: None,
2741 retention_period: None,
2742 soft_delete_retention_duration_seconds: None,
2743 soft_delete_effective_time: None,
2744 uniform_bucket_level_access_enabled: Some(true),
2745 uniform_bucket_level_access_locked_time: None,
2746 public_access_prevention: Some("enforced".to_string()),
2747 encryption_config_present: true,
2748 default_kms_key_name: Some(
2749 "projects/p/locations/l/keyRings/r/cryptoKeys/k".to_string(),
2750 ),
2751 }),
2752 ))
2753 .unwrap();
2754 let kv = serde_json::to_value(ResourceHeartbeatData::Kv(KvHeartbeatData::AwsDynamoDb(
2755 AwsDynamoDbKvHeartbeatData {
2756 status: KvHeartbeatStatus {
2757 health: ObservedHealth::Healthy,
2758 lifecycle: ProviderLifecycleState::Running,
2759 message: None,
2760 stale: false,
2761 partial: false,
2762 collection_issues: vec![],
2763 },
2764 name: "state".to_string(),
2765 region: Some("us-east-1".to_string()),
2766 table_arn: None,
2767 table_status: Some("ACTIVE".to_string()),
2768 billing_mode: Some("PAY_PER_REQUEST".to_string()),
2769 key_schema: vec![AwsDynamoDbKeySchemaElement {
2770 attribute_name: "pk".to_string(),
2771 key_type: "HASH".to_string(),
2772 }],
2773 global_secondary_index_count: Some(0),
2774 local_secondary_index_count: Some(0),
2775 item_count: None,
2776 table_size_bytes: None,
2777 stream_enabled: Some(false),
2778 stream_view_type: None,
2779 ttl_status: Some("ENABLED".to_string()),
2780 ttl_attribute_name: Some("ttl".to_string()),
2781 deletion_protection_enabled: Some(false),
2782 sse_status: Some("ENABLED".to_string()),
2783 sse_type: Some("KMS".to_string()),
2784 table_class: None,
2785 replica_count: Some(0),
2786 restore_in_progress: None,
2787 },
2788 )))
2789 .unwrap();
2790
2791 assert_eq!(cluster["resourceType"], "kubernetes-cluster");
2792 assert!(cluster["data"].get("summary").is_none());
2793 assert!(cluster["data"].get("detail").is_none());
2794 assert_eq!(cluster["data"]["name"], "prod");
2795 assert_eq!(queue["data"]["backend"], "awsSqs");
2796 assert_eq!(queue["data"]["approximateVisibleMessages"], 42);
2797 assert!(queue["data"].get("summary").is_none());
2798 assert_eq!(storage["data"]["backend"], "awsS3");
2799 assert!(storage["data"].get("summary").is_none());
2800 assert_eq!(gcp_storage["data"]["backend"], "gcpCloudStorage");
2801 assert_eq!(gcp_storage["data"]["publicAccessPrevention"], "enforced");
2802 assert_eq!(kv["data"]["backend"], "awsDynamoDb");
2803 assert!(kv["data"].get("summary").is_none());
2804 assert_eq!(kv["data"]["itemCount"], json!(null));
2805 }
2806
2807 #[test]
2808 fn ai_heartbeat_serializes_stable_tags() {
2809 let aws = serde_json::to_value(ResourceHeartbeatData::Ai(AiHeartbeatData::AwsBedrock(
2810 AwsBedrockAiHeartbeatData {
2811 status: AiHeartbeatStatus::default(),
2812 region: "us-east-1".to_string(),
2813 },
2814 )))
2815 .unwrap();
2816 let gcp =
2817 serde_json::to_value(ResourceHeartbeatData::Ai(AiHeartbeatData::GcpVertex(
2818 GcpVertexAiHeartbeatData {
2819 status: AiHeartbeatStatus::default(),
2820 project: "my-project".to_string(),
2821 location: "us-central1".to_string(),
2822 },
2823 )))
2824 .unwrap();
2825 let azure =
2826 serde_json::to_value(ResourceHeartbeatData::Ai(AiHeartbeatData::AzureFoundry(
2827 AzureFoundryAiHeartbeatData {
2828 status: AiHeartbeatStatus::default(),
2829 account_name: "my-ai-account".to_string(),
2830 endpoint: Some("https://my-ai-account.openai.azure.com/".to_string()),
2831 resource_group: Some("my-rg".to_string()),
2832 location: Some("eastus".to_string()),
2833 },
2834 )))
2835 .unwrap();
2836
2837 assert_eq!(aws["resourceType"], "ai");
2838 assert_eq!(aws["data"]["backend"], "awsBedrock");
2839 assert_eq!(aws["data"]["region"], "us-east-1");
2840 assert!(aws["data"].get("summary").is_none());
2841
2842 assert_eq!(gcp["resourceType"], "ai");
2843 assert_eq!(gcp["data"]["backend"], "gcpVertex");
2844 assert_eq!(gcp["data"]["project"], "my-project");
2845 assert_eq!(gcp["data"]["location"], "us-central1");
2846
2847 assert_eq!(azure["resourceType"], "ai");
2848 assert_eq!(azure["data"]["backend"], "azureFoundry");
2849 assert_eq!(azure["data"]["accountName"], "my-ai-account");
2850 assert_eq!(
2851 azure["data"]["endpoint"],
2852 "https://my-ai-account.openai.azure.com/"
2853 );
2854 }
2855}