Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support writing progress as JSON #614

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dsc/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ _version = 1
about = "Apply configuration or invoke specific DSC resources"
traceFormat = "Trace format to use"
traceLevel = "Trace level to use"
progressFormat = "Progress format to use"
completer = "Generate a shell completion script"
configAbout = "Apply a configuration document"
parameters = "Parameters to pass to the configuration as JSON or YAML"
Expand Down
3 changes: 3 additions & 0 deletions dsc/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use clap::{Parser, Subcommand, ValueEnum};
use clap_complete::Shell;
use dsc_lib::dscresources::command_resource::TraceLevel;
use dsc_lib::util::ProgressFormat;
use rust_i18n::t;
use serde::Deserialize;

Expand Down Expand Up @@ -33,6 +34,8 @@ pub struct Args {
pub trace_level: Option<TraceLevel>,
#[clap(short = 't', long, help = t!("args.traceFormat").to_string(), value_enum)]
pub trace_format: Option<TraceFormat>,
#[clap(short = 'p', long, help = t!("args.progressFormat").to_string(), value_enum)]
pub progress_format: Option<ProgressFormat>,
}

#[derive(Debug, PartialEq, Eq, Subcommand)]
Expand Down
9 changes: 6 additions & 3 deletions dsc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rust_i18n::{i18n, t};
use std::{io, process::exit};
use sysinfo::{Process, RefreshKind, System, get_current_pid, ProcessRefreshKind};
use tracing::{error, info, warn, debug};
use dsc_lib::util::ProgressFormat;

#[cfg(debug_assertions)]
use crossterm::event;
Expand Down Expand Up @@ -40,6 +41,8 @@ fn main() {

debug!("{}: {}", t!("main.usingDscVersion"), env!("CARGO_PKG_VERSION"));

let progress_format = args.progress_format.unwrap_or( ProgressFormat::Default );

match args.subcommand {
SubCommand::Completer { shell } => {
info!("{} {:?}", t!("main.generatingCompleter"), shell);
Expand All @@ -50,19 +53,19 @@ fn main() {
if let Some(file_name) = parameters_file {
info!("{}: {file_name}", t!("main.readingParametersFile"));
match std::fs::read_to_string(&file_name) {
Ok(parameters) => subcommand::config(&subcommand, &Some(parameters), system_root.as_ref(), &as_group, &as_include),
Ok(parameters) => subcommand::config(&subcommand, &Some(parameters), system_root.as_ref(), &as_group, &as_include, progress_format),
Err(err) => {
error!("{} '{file_name}': {err}", t!("main.failedToReadParametersFile"));
exit(util::EXIT_INVALID_INPUT);
}
}
}
else {
subcommand::config(&subcommand, &parameters, system_root.as_ref(), &as_group, &as_include);
subcommand::config(&subcommand, &parameters, system_root.as_ref(), &as_group, &as_include, progress_format);
}
},
SubCommand::Resource { subcommand } => {
subcommand::resource(&subcommand);
subcommand::resource(&subcommand, progress_format);
},
SubCommand::Schema { dsc_type , output_format } => {
let schema = util::get_schema(dsc_type);
Expand Down
31 changes: 17 additions & 14 deletions dsc/src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use dsc_lib::{
},
dscresources::dscresource::{Capability, ImplementedAs, Invoke},
dscresources::resource_manifest::{import_manifest, ResourceManifest},
util::ProgressFormat,
};
use rust_i18n::t;
use std::{
Expand Down Expand Up @@ -251,7 +252,7 @@ fn initialize_config_root(path: Option<&String>) -> Option<String> {
}

#[allow(clippy::too_many_lines)]
pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounted_path: Option<&String>, as_group: &bool, as_include: &bool) {
pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounted_path: Option<&String>, as_group: &bool, as_include: &bool, progress_format: ProgressFormat) {
let (new_parameters, json_string) = match subcommand {
ConfigSubCommand::Get { input, file, .. } |
ConfigSubCommand::Set { input, file, .. } |
Expand Down Expand Up @@ -295,6 +296,8 @@ pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounte
}
};

configurator.set_progress_format(progress_format);

if let ConfigSubCommand::Set { what_if , .. } = subcommand {
if *what_if {
configurator.context.execution_type = ExecutionKind::WhatIf;
Expand Down Expand Up @@ -382,7 +385,7 @@ pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounte
}
}
} else {
match validate_config(configurator.get_config()) {
match validate_config(configurator.get_config(), progress_format) {
Ok(()) => {
// valid, so do nothing
},
Expand Down Expand Up @@ -450,7 +453,7 @@ pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounte
/// # Errors
///
/// * `DscError` - The error that occurred.
pub fn validate_config(config: &Configuration) -> Result<(), DscError> {
pub fn validate_config(config: &Configuration, progress_format: ProgressFormat) -> Result<(), DscError> {
// first validate against the config schema
debug!("{}", t!("subcommand.validatingConfiguration"));
let schema = serde_json::to_value(get_schema(DscType::Configuration))?;
Expand All @@ -476,7 +479,7 @@ pub fn validate_config(config: &Configuration) -> Result<(), DscError> {

resource_types.push(type_name.to_lowercase().to_string());
}
dsc.find_resources(&resource_types);
dsc.find_resources(&resource_types, progress_format);

for resource_block in resources {
let Some(type_name) = resource_block["type"].as_str() else {
Expand Down Expand Up @@ -527,7 +530,7 @@ pub fn validate_config(config: &Configuration) -> Result<(), DscError> {
}

#[allow(clippy::too_many_lines)]
pub fn resource(subcommand: &ResourceSubCommand) {
pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat) {
let mut dsc = match DscManager::new() {
Ok(dsc) => dsc,
Err(err) => {
Expand All @@ -538,43 +541,43 @@ pub fn resource(subcommand: &ResourceSubCommand) {

match subcommand {
ResourceSubCommand::List { resource_name, adapter_name, description, tags, output_format } => {
list_resources(&mut dsc, resource_name.as_ref(), adapter_name.as_ref(), description.as_ref(), tags.as_ref(), output_format.as_ref());
list_resources(&mut dsc, resource_name.as_ref(), adapter_name.as_ref(), description.as_ref(), tags.as_ref(), output_format.as_ref(), progress_format);
},
ResourceSubCommand::Schema { resource , output_format } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
resource_command::schema(&dsc, resource, output_format.as_ref());
},
ResourceSubCommand::Export { resource, output_format } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
resource_command::export(&mut dsc, resource, output_format.as_ref());
},
ResourceSubCommand::Get { resource, input, file: path, all, output_format } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
if *all { resource_command::get_all(&dsc, resource, output_format.as_ref()); }
else {
let parsed_input = get_input(input.as_ref(), path.as_ref());
resource_command::get(&dsc, resource, parsed_input, output_format.as_ref());
}
},
ResourceSubCommand::Set { resource, input, file: path, output_format } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
let parsed_input = get_input(input.as_ref(), path.as_ref());
resource_command::set(&dsc, resource, parsed_input, output_format.as_ref());
},
ResourceSubCommand::Test { resource, input, file: path, output_format } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
let parsed_input = get_input(input.as_ref(), path.as_ref());
resource_command::test(&dsc, resource, parsed_input, output_format.as_ref());
},
ResourceSubCommand::Delete { resource, input, file: path } => {
dsc.find_resources(&[resource.to_string()]);
dsc.find_resources(&[resource.to_string()], progress_format);
let parsed_input = get_input(input.as_ref(), path.as_ref());
resource_command::delete(&dsc, resource, parsed_input);
},
}
}

fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adapter_name: Option<&String>, description: Option<&String>, tags: Option<&Vec<String>>, format: Option<&OutputFormat>) {
fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adapter_name: Option<&String>, description: Option<&String>, tags: Option<&Vec<String>>, format: Option<&OutputFormat>, progress_format: ProgressFormat) {
let mut write_table = false;
let mut table = Table::new(&[
t!("subcommand.tableHeader_type").to_string().as_ref(),
Expand All @@ -588,7 +591,7 @@ fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adapter_
// write as table if format is not specified and interactive
write_table = true;
}
for resource in dsc.list_available_resources(resource_name.unwrap_or(&String::from("*")), adapter_name.unwrap_or(&String::new())) {
for resource in dsc.list_available_resources(resource_name.unwrap_or(&String::from("*")), adapter_name.unwrap_or(&String::new()), progress_format) {
let mut capabilities = "--------".to_string();
let capability_types = [
(Capability::Get, "g"),
Expand Down
23 changes: 23 additions & 0 deletions dsc/tests/dsc_config_get.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,29 @@ Describe 'dsc config get tests' {
$LASTEXITCODE | Should -Be 0
}

It 'json progress for config subcommand' {
$config_yaml = @"
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: hello
"@
$config_yaml | dsc --progress-format json config get -f - 2> $TestDrive/ErrorStream.txt
$LASTEXITCODE | Should -Be 0
$lines = Get-Content $TestDrive/ErrorStream.txt
$ProgressMessagesFound = $False
foreach ($line in $lines) {
anmenaga marked this conversation as resolved.
Show resolved Hide resolved
$jp = $line | ConvertFrom-Json
if ($jp.activity) { # if line is a progress message
$jp.percent_complete | Should -BeIn (0..100)
$ProgressMessagesFound = $True
}
}
$ProgressMessagesFound | Should -BeTrue
}

It 'contentVersion is ignored' {
$config_yaml = @"
`$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
Expand Down
15 changes: 15 additions & 0 deletions dsc/tests/dsc_resource_list.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ Describe 'Tests for listing resources' {
}
}

It 'json progress for resource subcommand' {
dsc -t json -p json resource list -a '*' 2> $TestDrive/ErrorStream.txt
$LASTEXITCODE | Should -Be 0
$lines = Get-Content $TestDrive/ErrorStream.txt
$ProgressMessagesFound = $False
foreach ($line in $lines) {
$jp = $line | ConvertFrom-Json
if ($jp.activity) { # if line is a progress message
$jp.percent_complete | Should -BeIn (0..100)
$ProgressMessagesFound = $True
}
}
$ProgressMessagesFound | Should -BeTrue
}

It 'Capabilities are returned' {
$resource = dsc resource list Microsoft/OSInfo | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
Expand Down
Loading
Loading