Skip to content

Commit

Permalink
Merge branch 'main' into refactor-input-options
Browse files Browse the repository at this point in the history
  • Loading branch information
tgauth authored Feb 6, 2024
2 parents a0ba478 + fc38869 commit 5a87b6c
Show file tree
Hide file tree
Showing 19 changed files with 403 additions and 105 deletions.
25 changes: 22 additions & 3 deletions dsc/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ pub struct Args {
/// The subcommand to run
#[clap(subcommand)]
pub subcommand: SubCommand,
/// The output format to use
#[clap(short = 'o', long)]
pub format: Option<OutputFormat>,
#[clap(short = 'l', long, help = "Trace level to use", value_enum, default_value = "warning")]
pub trace_level: TraceLevel,
#[clap(short = 'f', long, help = "Trace format to use", value_enum, default_value = "default")]
Expand Down Expand Up @@ -67,6 +64,8 @@ pub enum SubCommand {
Schema {
#[clap(name = "type", short, long, help = "The type of DSC schema to get")]
dsc_type: DscType,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
}

Expand All @@ -78,20 +77,26 @@ pub enum ConfigSubCommand {
document: Option<String>,
#[clap(short = 'p', long, help = "The path to a file used as input to the configuration or resource", conflicts_with = "document")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "set", about = "Set the current configuration")]
Set {
#[clap(short = 'd', long, help = "The document to pass to the configuration or resource", conflicts_with = "path")]
document: Option<String>,
#[clap(short = 'p', long, help = "The path to a file used as input to the configuration or resource", conflicts_with = "document")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "test", about = "Test the current configuration")]
Test {
#[clap(short = 'd', long, help = "The document to pass to the configuration or resource", conflicts_with = "path")]
document: Option<String>,
#[clap(short = 'p', long, help = "The path to a file used as input to the configuration or resource", conflicts_with = "document")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "validate", about = "Validate the current configuration", hide = true)]
Validate {
Expand All @@ -106,6 +111,8 @@ pub enum ConfigSubCommand {
document: Option<String>,
#[clap(short = 'p', long, help = "The path to a file used as input to the configuration or resource", conflicts_with = "document")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
}
}

Expand All @@ -119,6 +126,8 @@ pub enum ResourceSubCommand {
description: Option<String>,
#[clap(short, long, help = "Tag to search for in the resource tags")]
tags: Option<Vec<String>>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "get", about = "Invoke the get operation to a resource", arg_required_else_help = true)]
Get {
Expand All @@ -130,6 +139,8 @@ pub enum ResourceSubCommand {
input: Option<String>,
#[clap(short = 'p', long, help = "The path to a JSON or YAML file used as input to the configuration or resource", conflicts_with = "input")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "set", about = "Invoke the set operation to a resource", arg_required_else_help = true)]
Set {
Expand All @@ -139,6 +150,8 @@ pub enum ResourceSubCommand {
input: Option<String>,
#[clap(short = 'p', long, help = "The path to a JSON or YAML file used as input to the configuration or resource", conflicts_with = "input")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "test", about = "Invoke the test operation to a resource", arg_required_else_help = true)]
Test {
Expand All @@ -148,16 +161,22 @@ pub enum ResourceSubCommand {
input: Option<String>,
#[clap(short = 'p', long, help = "The path to a JSON or YAML file used as input to the configuration or resource", conflicts_with = "input")]
path: Option<String>,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "schema", about = "Get the JSON schema for a resource", arg_required_else_help = true)]
Schema {
#[clap(short, long, help = "The name of the resource to get the JSON schema")]
resource: String,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
#[clap(name = "export", about = "Retrieve all resource instances", arg_required_else_help = true)]
Export {
#[clap(short, long, help = "The name or DscResource JSON of the resource to invoke `export` on")]
resource: String,
#[clap(short = 'f', long, help = "The output format to use")]
format: Option<OutputFormat>,
},
}

Expand Down
10 changes: 5 additions & 5 deletions dsc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,21 @@ fn main() {
if let Some(file_name) = parameters_file {
info!("Reading parameters from file {}", file_name);
match std::fs::read_to_string(file_name) {
Ok(parameters) => subcommand::config(&subcommand, &Some(parameters), &args.format, &input),
Ok(parameters) => subcommand::config(&subcommand, &Some(parameters), &input),
Err(err) => {
error!("Error: Failed to read parameters file: {err}");
exit(util::EXIT_INVALID_INPUT);
}
}
}
else {
subcommand::config(&subcommand, &parameters, &args.format, &input);
subcommand::config(&subcommand, &parameters, &input);
}
},
SubCommand::Resource { subcommand } => {
subcommand::resource(&subcommand, &args.format, &input);
subcommand::resource(&subcommand, &input);
},
SubCommand::Schema { dsc_type } => {
SubCommand::Schema { dsc_type , format } => {
let schema = util::get_schema(dsc_type);
let json = match serde_json::to_string(&schema) {
Ok(json) => json,
Expand All @@ -91,7 +91,7 @@ fn main() {
exit(util::EXIT_JSON_ERROR);
}
};
util::write_output(&json, &args.format);
util::write_output(&json, &format);
},
}

Expand Down
30 changes: 27 additions & 3 deletions dsc/src/resource_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,24 @@ pub fn get(dsc: &DscManager, resource_type: &str, mut input: String, format: &Op
}

pub fn get_all(dsc: &DscManager, resource_type: &str, format: &Option<OutputFormat>) {
let Some(resource) = get_resource(dsc, resource_type) else {
let mut input = String::new() ;
let Some(mut resource) = get_resource(dsc, resource_type) else {
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
return
};

debug!("resource.type_name - {} implemented_as - {:?}", resource.type_name, resource.implemented_as);
let export_result = match resource.export() {
if let Some(requires) = &resource.requires {
input = add_type_name_to_json(input, resource.type_name.clone());
if let Some(pr) = get_resource(dsc, requires) {
resource = pr;
} else {
error!("Provider '{}' not found", requires);
return;
};
}

let export_result = match resource.export(&input) {
Ok(export) => { export }
Err(err) => {
error!("Error: {err}");
Expand Down Expand Up @@ -198,14 +210,26 @@ pub fn schema(dsc: &DscManager, resource_type: &str, format: &Option<OutputForma
}

pub fn export(dsc: &mut DscManager, resource_type: &str, format: &Option<OutputFormat>) {
let mut input = String::new();
let Some(dsc_resource) = get_resource(dsc, resource_type) else {
error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string());
return
};

let mut provider_resource: Option<&DscResource> = None;
if let Some(requires) = &dsc_resource.requires {
input = add_type_name_to_json(input, dsc_resource.type_name.clone());
if let Some(pr) = get_resource(dsc, requires) {
provider_resource = Some(pr);
} else {
error!("Provider '{}' not found", requires);
return;
};
}

let mut conf = Configuration::new();

if let Err(err) = add_resource_export_results_to_configuration(dsc_resource, &mut conf) {
if let Err(err) = add_resource_export_results_to_configuration(dsc_resource, provider_resource, &mut conf, &input) {
error!("Error: {err}");
exit(EXIT_DSC_ERROR);
}
Expand Down
44 changes: 21 additions & 23 deletions dsc/src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,24 +162,24 @@ pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, format
};

if let Err(err) = configurator.set_parameters(&parameters) {
error!("Error: Paramter input failure: {err}");
error!("Error: Parameter input failure: {err}");
exit(EXIT_INVALID_INPUT);
}

match subcommand {
ConfigSubCommand::Get { .. } => {
ConfigSubCommand::Get { format } => {
config_get(&mut configurator, format);
},
ConfigSubCommand::Set { ..} => {
ConfigSubCommand::Set { format } => {
config_set(&mut configurator, format);
},
ConfigSubCommand::Test { .. } => {
ConfigSubCommand::Test { format } => {
config_test(&mut configurator, format);
},
ConfigSubCommand::Validate { .. } => {
validate_config(&json_string);
},
ConfigSubCommand::Export { .. }=> {
ConfigSubCommand::Export { format } => {
config_export(&mut configurator, format);
}
}
Expand Down Expand Up @@ -307,7 +307,7 @@ pub fn validate_config(config: &str) {
exit(EXIT_SUCCESS);
}

pub fn resource(subcommand: &ResourceSubCommand, format: &Option<OutputFormat>, stdin: &Option<String>) {
pub fn resource(subcommand: &ResourceSubCommand, stdin: &Option<String>) {
let mut dsc = match DscManager::new() {
Ok(dsc) => dsc,
Err(err) => {
Expand All @@ -317,7 +317,7 @@ pub fn resource(subcommand: &ResourceSubCommand, format: &Option<OutputFormat>,
};

match subcommand {
ResourceSubCommand::List { resource_name, description, tags } => {
ResourceSubCommand::List { resource_name, description, tags, format } => {

let mut write_table = false;
let mut table = Table::new(&["Type", "Version", "Requires", "Description"]);
Expand Down Expand Up @@ -392,31 +392,29 @@ pub fn resource(subcommand: &ResourceSubCommand, format: &Option<OutputFormat>,

if write_table { table.print(); }
},
ResourceSubCommand::Schema { resource } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
resource_command::schema(&dsc, resource, format);
},
ResourceSubCommand::Export { resource} => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
resource_command::export(&mut dsc, resource, format);
},
ResourceSubCommand::Get { resource, input, path, all } => {

ResourceSubCommand::Get { resource, input, all, format } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
if *all { resource_command::get_all(&dsc, resource, format); }
else {
let parsed_input = get_input(input, stdin, path);
resource_command::get(&dsc, resource, parsed_input, format);
};
let parsed_input = get_input(input, stdin, path);
resource_command::get(&dsc, resource, parsed_input, format);
},
ResourceSubCommand::Set { resource, input, path } => {
ResourceSubCommand::Set { resource, input, format } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
let parsed_input = get_input(input, stdin, path);
resource_command::set(&dsc, resource, parsed_input, format);
},
ResourceSubCommand::Test { resource, input, path } => {
ResourceSubCommand::Test { resource, input, format } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
let parsed_input = get_input(input, stdin, path);
resource_command::test(&dsc, resource, parsed_input, format);
},
ResourceSubCommand::Schema { resource , format } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
resource_command::schema(&dsc, resource, format);
},
ResourceSubCommand::Export { resource, format } => {
dsc.discover_resources(&[resource.to_lowercase().to_string()]);
resource_command::export(&mut dsc, resource, format);
},
}
}
2 changes: 1 addition & 1 deletion dsc/tests/dsc_args.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ actualState:
) {
param($format, $expected)

$out = dsc --format $format resource get -r Test/Hello | Out-String
$out = dsc resource get -r Test/Hello --format $format | Out-String
$LASTEXITCODE | Should -Be 0
$out.Trim() | Should -BeExactly $expected
}
Expand Down
13 changes: 13 additions & 0 deletions dsc/tests/dsc_config_get.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,17 @@ Describe 'dsc config get tests' {
$null = $config | dsc config get | ConvertFrom-Json
$LASTEXITCODE | Should -Be 2
}

It 'can accept the use of --format as a subcommand' {
$config_yaml = @"
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/10/config/document.json
resources:
- name: Echo
type: Test/Echo
properties:
text: hello
"@
$null = $config_yaml | dsc config get --format pretty-json | Out-String
$LASTEXITCODE | Should -Be 0
}
}
30 changes: 29 additions & 1 deletion dsc/tests/dsc_export.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License.

Describe 'resource export tests' {

It 'Export can be called on individual resource' {

$out = dsc resource export -r Microsoft/Process
Expand Down Expand Up @@ -74,4 +74,32 @@ Describe 'resource export tests' {
$LASTEXITCODE | Should -Be 2
$out | out-string | Should -BeLike '*specified multiple times*'
}

It 'Export can be called on individual resource with the use of --format as a subcommand' {

$out = dsc resource export -r Microsoft/Process -f pretty-json
$LASTEXITCODE | Should -Be 0
$config_with_process_list = $out | ConvertFrom-Json
$config_with_process_list.'$schema' | Should -BeExactly 'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json'
$config_with_process_list.'resources' | Should -Not -BeNullOrEmpty
$config_with_process_list.resources.count | Should -BeGreaterThan 1
}

It 'Export can be called on a configuration with the use of --format as a subcommand' {

$yaml = @'
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/10/config/document.json
resources:
- name: Processes
type: Microsoft/Process
properties:
pid: 0
'@
$out = $yaml | dsc config export -f pretty-json
$LASTEXITCODE | Should -Be 0
$config_with_process_list = $out | ConvertFrom-Json
$config_with_process_list.'$schema' | Should -BeExactly 'https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json'
$config_with_process_list.'resources' | Should -Not -BeNullOrEmpty
$config_with_process_list.resources.count | Should -BeGreaterThan 1
}
}
11 changes: 11 additions & 0 deletions dsc/tests/dsc_resource_list.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,15 @@ Describe 'Tests for listing resources' {
$resources.type | Should -BeExactly $expectedType
}
}

It 'can accept the use of --format as a subcommand' {
$expectedCount = 1
$expectedType = 'Microsoft/OSInfo'
$resources = dsc resource list --description "operating system" --format pretty-json | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$resources.Count | Should -Be $expectedCount
if ($expectedCount -gt 0) {
$resources.type | Should -BeExactly $expectedType
}
}
}
10 changes: 9 additions & 1 deletion dsc/tests/dsc_schema.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,12 @@ Describe 'config schema tests' {
$schema = $schema | ConvertFrom-Json
$schema.'$schema' | Should -BeExactly 'http://json-schema.org/draft-07/schema#'
}
}

It 'can accept the use of --format as a subcommand' {
$schema = dsc resource schema -r Test/Echo -f pretty-json
$LASTEXITCODE | Should -Be 0
$schema | Should -Not -BeNullOrEmpty
$schema = $schema | ConvertFrom-Json
$schema.'$schema' | Should -BeExactly 'http://json-schema.org/draft-07/schema#'
}
}
Loading

0 comments on commit 5a87b6c

Please sign in to comment.