greentic_deploy_spec/
environment_runtime.rs1use crate::capability_slot::PackDescriptor;
7use crate::version::SchemaVersion;
8use chrono::{DateTime, Utc};
9use greentic_types::EnvId;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use std::collections::BTreeMap;
13
14pub type RuntimeDiscoveryValue = Value;
18
19#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
20pub struct EnvironmentRuntime {
21 pub schema: SchemaVersion,
22 pub environment_id: EnvId,
23 #[serde(default)]
24 pub discovered: BTreeMap<String, RuntimeDiscoveryValue>,
25 pub generated_at: DateTime<Utc>,
26 pub generated_by: PackDescriptor,
27 pub generation: u64,
29}
30
31impl EnvironmentRuntime {
32 pub fn schema_str() -> &'static str {
33 SchemaVersion::ENVIRONMENT_RUNTIME_V1
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use std::str::FromStr;
41
42 fn sample() -> EnvironmentRuntime {
43 let mut discovered = BTreeMap::new();
44 discovered.insert(
45 "alb_dns".into(),
46 serde_json::Value::String("a.example.com".into()),
47 );
48 EnvironmentRuntime {
49 schema: SchemaVersion::new(SchemaVersion::ENVIRONMENT_RUNTIME_V1),
50 environment_id: greentic_types::EnvId::from_str("local").unwrap(),
51 discovered,
52 generated_at: Utc::now(),
53 generated_by: PackDescriptor::try_new("greentic.deployer.local-process@1.0.0").unwrap(),
54 generation: 1,
55 }
56 }
57
58 #[test]
59 fn schema_str_matches_constant() {
60 assert_eq!(
61 EnvironmentRuntime::schema_str(),
62 SchemaVersion::ENVIRONMENT_RUNTIME_V1
63 );
64 }
65
66 #[test]
67 fn json_round_trip() {
68 let original = sample();
69 let json = serde_json::to_string(&original).unwrap();
70 let back: EnvironmentRuntime = serde_json::from_str(&json).unwrap();
71 assert_eq!(original, back);
72 }
73
74 #[test]
75 fn discovered_defaults_to_empty() {
76 let json = serde_json::json!({
77 "schema": SchemaVersion::ENVIRONMENT_RUNTIME_V1,
78 "environment_id": "local",
79 "generated_at": "2026-01-01T00:00:00Z",
80 "generated_by": "greentic.deployer.local-process@1.0.0",
81 "generation": 1
82 });
83 let rt: EnvironmentRuntime = serde_json::from_value(json).unwrap();
84 assert!(rt.discovered.is_empty());
85 }
86}