Skip to content

Commit 78ebef5

Browse files
author
Andrew
committed
metaconfig 4
1 parent fa16c3e commit 78ebef5

File tree

7 files changed

+137
-41
lines changed

7 files changed

+137
-41
lines changed

dsc/default_settings.v1.dsc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
"allow_env_override": true,
44
"append_env_path": true,
55
"directories": []
6+
},
7+
"tracing": {
8+
"level": "WARN",
9+
"format": "Default",
10+
"allow_override": true
611
}
712
}

dsc/settings.dsc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
"allow_env_override": true,
44
"append_env_path": true,
55
"directories": []
6+
},
7+
"tracing": {
8+
"level": "WARN",
9+
"format": "Default",
10+
"allow_override": true
611
}
712
}

dsc/src/args.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use clap::{Parser, Subcommand, ValueEnum};
55
use clap_complete::Shell;
66
use dsc_lib::dscresources::command_resource::TraceLevel;
7+
use serde::Deserialize;
78

89
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum)]
910
pub enum OutputFormat {
@@ -12,7 +13,7 @@ pub enum OutputFormat {
1213
Yaml,
1314
}
1415

15-
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum)]
16+
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum, Deserialize)]
1617
pub enum TraceFormat {
1718
Default,
1819
Plaintext,
@@ -29,8 +30,8 @@ pub struct Args {
2930
pub subcommand: SubCommand,
3031
#[clap(short = 'l', long, help = "Trace level to use", value_enum)]
3132
pub trace_level: Option<TraceLevel>,
32-
#[clap(short = 'f', long, help = "Trace format to use", value_enum, default_value = "default")]
33-
pub trace_format: TraceFormat,
33+
#[clap(short = 'f', long, help = "Trace format to use", value_enum)]
34+
pub trace_format: Option<TraceFormat>,
3435
}
3536

3637
#[derive(Debug, PartialEq, Eq, Subcommand)]

dsc/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn main() {
3434

3535
let args = Args::parse();
3636

37-
util::enable_tracing(&args.trace_level, &args.trace_format);
37+
util::enable_tracing(args.trace_level, args.trace_format);
3838

3939
debug!("Running dsc {}", env!("CARGO_PKG_VERSION"));
4040

dsc/src/util.rs

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ use dsc_lib::{
2323
}, resource_manifest::ResourceManifest
2424
},
2525
util::parse_input_to_json,
26+
util::get_setting,
2627
};
2728
use jsonschema::Validator;
2829
use path_absolutize::Absolutize;
2930
use schemars::{schema_for, schema::RootSchema};
31+
use serde::Deserialize;
3032
use serde_json::Value;
3133
use std::collections::HashMap;
3234
use std::env;
@@ -55,6 +57,23 @@ pub const EXIT_DSC_RESOURCE_NOT_FOUND: i32 = 7;
5557
pub const DSC_CONFIG_ROOT: &str = "DSC_CONFIG_ROOT";
5658
pub const DSC_TRACE_LEVEL: &str = "DSC_TRACE_LEVEL";
5759

60+
#[derive(Deserialize)]
61+
pub struct TracingSetting {
62+
level: TraceLevel,
63+
format: TraceFormat,
64+
allow_override: bool
65+
}
66+
67+
impl Default for TracingSetting {
68+
fn default() -> TracingSetting {
69+
TracingSetting {
70+
level: TraceLevel::Warn,
71+
format: TraceFormat::Default,
72+
allow_override: true,
73+
}
74+
}
75+
}
76+
5877
/// Get string representation of JSON value.
5978
///
6079
/// # Arguments
@@ -268,46 +287,81 @@ pub fn write_output(json: &str, format: &Option<OutputFormat>) {
268287
}
269288
}
270289

271-
pub fn enable_tracing(trace_level: &Option<TraceLevel>, trace_format: &TraceFormat) {
272-
let tracing_level = match trace_level {
273-
Some(level) => level,
274-
None => {
275-
// use DSC_TRACE_LEVEL env var if set
276-
match env::var(DSC_TRACE_LEVEL) {
277-
Ok(level) => {
278-
match level.to_ascii_uppercase().as_str() {
279-
"ERROR" => &TraceLevel::Error,
280-
"WARN" => &TraceLevel::Warn,
281-
"INFO" => &TraceLevel::Info,
282-
"DEBUG" => &TraceLevel::Debug,
283-
"TRACE" => &TraceLevel::Trace,
284-
_ => {
285-
warn!("Invalid DSC_TRACE_LEVEL value '{level}', defaulting to 'warn'");
286-
&TraceLevel::Warn
287-
},
288-
}
290+
pub fn enable_tracing(trace_level_arg: Option<TraceLevel>, trace_format_arg: Option<TraceFormat>) {
291+
292+
let mut policy_is_used = false;
293+
let mut tracing_setting = TracingSetting::default();
294+
295+
// read setting/policy from files
296+
if let Ok(v) = get_setting("tracing") {
297+
if v.policy != serde_json::Value::Null {
298+
match serde_json::from_value::<TracingSetting>(v.policy) {
299+
Ok(v) => {
300+
tracing_setting = v;
301+
policy_is_used = true;
289302
},
290-
Err(_) => &TraceLevel::Warn,
303+
Err(e) => { println!("{}", format!("{e}")); }
304+
}
305+
} else if v.setting != serde_json::Value::Null {
306+
match serde_json::from_value::<TracingSetting>(v.setting) {
307+
Ok(v) => {
308+
tracing_setting = v;
309+
},
310+
Err(e) => { println!("{}", format!("{e}")); }
291311
}
292312
}
313+
} else {
314+
println!("Could not read 'tracing' setting");
315+
}
316+
317+
// override with DSC_TRACE_LEVEL env var if permitted
318+
if tracing_setting.allow_override {
319+
match env::var(DSC_TRACE_LEVEL) {
320+
Ok(level) => {
321+
tracing_setting.level = match level.to_ascii_uppercase().as_str() {
322+
"ERROR" => TraceLevel::Error,
323+
"WARN" => TraceLevel::Warn,
324+
"INFO" => TraceLevel::Info,
325+
"DEBUG" => TraceLevel::Debug,
326+
"TRACE" => TraceLevel::Trace,
327+
_ => {
328+
warn!("Invalid DSC_TRACE_LEVEL value '{level}', defaulting to 'warn'");
329+
TraceLevel::Warn
330+
}
331+
}
332+
},
333+
Err(_) => {},
334+
}
335+
}
336+
337+
// command-line args override setting value, but not policy
338+
if !policy_is_used {
339+
if let Some(v) = trace_level_arg {
340+
tracing_setting.level = v.clone();
341+
};
342+
if let Some(v) = trace_format_arg {
343+
tracing_setting.format = v.clone();
344+
};
293345
};
294346

295-
let tracing_level = match tracing_level {
347+
// convert to 'tracing' crate type
348+
let tracing_level = match tracing_setting.level {
296349
TraceLevel::Error => Level::ERROR,
297350
TraceLevel::Warn => Level::WARN,
298351
TraceLevel::Info => Level::INFO,
299352
TraceLevel::Debug => Level::DEBUG,
300353
TraceLevel::Trace => Level::TRACE,
301354
};
302355

356+
// enable tracing
303357
let filter = EnvFilter::try_from_default_env()
304358
.or_else(|_| EnvFilter::try_new("warning"))
305359
.unwrap_or_default()
306360
.add_directive(tracing_level.into());
307361
let indicatif_layer = IndicatifLayer::new();
308362
let layer = tracing_subscriber::fmt::Layer::default().with_writer(indicatif_layer.get_stderr_writer());
309363
let with_source = tracing_level == Level::DEBUG || tracing_level == Level::TRACE;
310-
let fmt = match trace_format {
364+
let fmt = match tracing_setting.format {
311365
TraceFormat::Default => {
312366
layer
313367
.with_ansi(true)

dsc_lib/src/discovery/command_discovery.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,38 @@ impl CommandDiscovery {
6161
fn get_resource_path_setting() -> Result<ResourcePathSetting, DscError>
6262
{
6363
if let Ok(v) = get_setting("resource_path") {
64-
if let Ok(resource_path_setting) = serde_json::from_value(v) {
65-
return Ok(resource_path_setting);
64+
// if there is a policy value defined - use it; otherwise use setting value
65+
if v.policy != serde_json::Value::Null {
66+
match serde_json::from_value::<ResourcePathSetting>(v.policy) {
67+
Ok(v) => {
68+
return Ok(v);
69+
},
70+
Err(e) => { return Err(DscError::Operation(format!("{}", e))); }
71+
}
72+
} else if v.setting != serde_json::Value::Null {
73+
match serde_json::from_value::<ResourcePathSetting>(v.setting) {
74+
Ok(v) => {
75+
return Ok(v);
76+
},
77+
Err(e) => { return Err(DscError::Operation(format!("{}", e))); }
78+
}
6679
}
6780
}
6881

69-
Err(DscError::Operation("Could not read resource_path setting".to_string()))
82+
Err(DscError::Operation("Could not read 'resource_path' setting".to_string()))
7083
}
7184

7285
fn get_resource_paths() -> Result<Vec<PathBuf>, DscError>
7386
{
7487
let mut resource_path_setting = ResourcePathSetting::default();
75-
if let Ok(v) = Self::get_resource_path_setting() {
76-
resource_path_setting = v;
77-
} else {
78-
debug!("Could not read resource_path setting");
88+
89+
match Self::get_resource_path_setting() {
90+
Ok(v) => {
91+
resource_path_setting = v;
92+
},
93+
Err(e) => {
94+
debug!("{e}");
95+
}
7996
}
8097

8198
let mut using_custom_path = false;

dsc_lib/src/util.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ use std::path::Path;
1010
use std::env;
1111
use tracing::debug;
1212

13+
pub struct DscSettingValue {
14+
pub setting: serde_json::Value,
15+
pub policy: serde_json::Value,
16+
}
17+
18+
impl Default for DscSettingValue {
19+
fn default() -> DscSettingValue {
20+
DscSettingValue {
21+
setting: serde_json::Value::Null,
22+
policy: serde_json::Value::Null,
23+
}
24+
}
25+
}
26+
1327
/// Return JSON string whether the input is JSON or YAML
1428
///
1529
/// # Arguments
@@ -53,30 +67,29 @@ pub fn parse_input_to_json(value: &str) -> Result<String, DscError> {
5367
/// # Errors
5468
///
5569
/// Will return `Err` if could not find requested setting.
56-
pub fn get_setting(value_name: &str) -> Result<serde_json::Value, DscError> {
70+
pub fn get_setting(value_name: &str) -> Result<DscSettingValue, DscError> {
5771

5872
const SETTINGS_FILE_NAME: &str = "settings.dsc.json";
5973
// Note that default settings file name has a version that is specific to this version of dsc
6074
const DEFAULT_SETTINGS_FILE_NAME: &str = "default_settings.v1.dsc.json";
6175

62-
let mut result:serde_json::Value = serde_json::Value::Null;
76+
let mut result: DscSettingValue = DscSettingValue::default();
6377
let mut settings_file_path : PathBuf;
6478

6579
if let Some(exe_home) = env::current_exe()?.parent() {
66-
6780
// First, get setting from the default settings file
6881
settings_file_path = exe_home.join(DEFAULT_SETTINGS_FILE_NAME);
6982
if let Ok(v) = load_value_from_json(&settings_file_path, value_name) {
70-
result = v;
83+
result.setting = v;
7184
debug!("Found setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
7285
} else {
7386
debug!("Did not find setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
7487
}
7588

76-
// Second, get setting from the active settings file overwriting previous value
89+
// Second, get setting from the active settings file overwriting previous value
7790
settings_file_path = exe_home.join(SETTINGS_FILE_NAME);
7891
if let Ok(v) = load_value_from_json(&settings_file_path, value_name) {
79-
result = v;
92+
result.setting = v;
8093
debug!("Found setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
8194
} else {
8295
debug!("Did not find setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
@@ -85,16 +98,17 @@ pub fn get_setting(value_name: &str) -> Result<serde_json::Value, DscError> {
8598
debug!("Can't get dsc executable path");
8699
}
87100

88-
// Third, get setting from the policy settings file overwriting previous value
101+
// Third, get setting from the policy
89102
settings_file_path = PathBuf::from(get_settings_policy_file_path());
90103
if let Ok(v) = load_value_from_json(&settings_file_path, value_name) {
91-
result = v;
104+
result.policy = v;
92105
debug!("Found setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
93106
} else {
94107
debug!("Did not find setting '{}' in {}", &value_name, settings_file_path.to_string_lossy());
95108
}
96109

97-
if result == serde_json::Value::Null {
110+
if (result.setting == serde_json::Value::Null) &&
111+
(result.policy == serde_json::Value::Null) {
98112
return Err(DscError::NotSupported(format!("Could not find '{value_name}' in settings").to_string()));
99113
}
100114

0 commit comments

Comments
 (0)