greentic_operator/
config_gate.rs1use std::env;
2use std::fmt;
3
4use crate::domains::{self, Domain};
5
6#[derive(Clone, Copy, Debug)]
7pub enum ConfigValueSource {
8 Argument(&'static str),
9 Platform(&'static str),
10 Derived(&'static str),
11}
12
13impl fmt::Display for ConfigValueSource {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 match self {
16 Self::Argument(detail) => write!(f, "arg({detail})"),
17 Self::Platform(detail) => write!(f, "platform({detail})"),
18 Self::Derived(detail) => write!(f, "derived({detail})"),
19 }
20 }
21}
22
23pub struct ConfigGateItem {
24 pub name: String,
25 pub value: Option<String>,
26 pub required: bool,
27 pub source: ConfigValueSource,
28}
29
30impl ConfigGateItem {
31 pub fn new(
32 name: impl Into<String>,
33 value: Option<String>,
34 source: ConfigValueSource,
35 required: bool,
36 ) -> Self {
37 Self {
38 name: name.into(),
39 value,
40 required,
41 source,
42 }
43 }
44}
45
46pub fn log_config_gate(
47 domain: Domain,
48 tenant: &str,
49 team: Option<&str>,
50 env: &str,
51 items: &[ConfigGateItem],
52) {
53 if !debug_enabled() || items.is_empty() {
54 return;
55 }
56 let team_label = team.unwrap_or("default");
57 eprintln!(
58 "config_gate::domain={} tenant={} team={} env={} items:",
59 domains::domain_name(domain),
60 tenant,
61 team_label,
62 env
63 );
64 for item in items {
65 let value = item.value.as_deref().unwrap_or("<missing>");
66 let required = if item.required {
67 "required"
68 } else {
69 "optional"
70 };
71 eprintln!(
72 "config_gate:: - {}={} [{}] {}",
73 item.name, value, item.source, required
74 );
75 }
76}
77
78fn debug_enabled() -> bool {
79 matches!(
80 env::var("GREENTIC_OPERATOR_DEMO_DEBUG").as_deref(),
81 Ok("1") | Ok("true") | Ok("yes")
82 )
83}