diff --git a/dsc/src/args.rs b/dsc/src/args.rs index fcd9010b..622391dd 100644 --- a/dsc/src/args.rs +++ b/dsc/src/args.rs @@ -213,6 +213,10 @@ pub enum ResourceSubCommand { Export { #[clap(short, long, help = t!("args.resource").to_string())] resource: String, + #[clap(short, long, help = t!("args.input").to_string(), conflicts_with = "file")] + input: Option<String>, + #[clap(short = 'f', long, help = t!("args.file").to_string(), conflicts_with = "input")] + file: Option<String>, #[clap(short = 'o', long, help = t!("args.outputFormat").to_string())] output_format: Option<OutputFormat>, }, diff --git a/dsc/src/resource_command.rs b/dsc/src/resource_command.rs index a7c0219b..d33df5b8 100644 --- a/dsc/src/resource_command.rs +++ b/dsc/src/resource_command.rs @@ -259,8 +259,7 @@ 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(); +pub fn export(dsc: &mut DscManager, resource_type: &str, mut input: String, format: Option<&OutputFormat>) { let Some(dsc_resource) = get_resource(dsc, resource_type) else { error!("{}", DscError::ResourceNotFound(resource_type.to_string()).to_string()); exit(EXIT_DSC_RESOURCE_NOT_FOUND); diff --git a/dsc/src/subcommand.rs b/dsc/src/subcommand.rs index a516ae80..c271ff0f 100644 --- a/dsc/src/subcommand.rs +++ b/dsc/src/subcommand.rs @@ -545,9 +545,10 @@ pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat dsc.find_resources(&[resource.to_string()], progress_format); resource_command::schema(&dsc, resource, output_format.as_ref()); }, - ResourceSubCommand::Export { resource, output_format } => { + ResourceSubCommand::Export { resource, input, file, output_format } => { dsc.find_resources(&[resource.to_string()], progress_format); - resource_command::export(&mut dsc, resource, output_format.as_ref()); + let parsed_input = get_input(input.as_ref(), file.as_ref()); + resource_command::export(&mut dsc, resource, parsed_input, output_format.as_ref()); }, ResourceSubCommand::Get { resource, input, file: path, all, output_format } => { dsc.find_resources(&[resource.to_string()], progress_format); diff --git a/dsc/tests/dsc_export.tests.ps1 b/dsc/tests/dsc_export.tests.ps1 index 2924d4bc..16b04616 100644 --- a/dsc/tests/dsc_export.tests.ps1 +++ b/dsc/tests/dsc_export.tests.ps1 @@ -88,6 +88,18 @@ Describe 'resource export tests' { $config_with_process_list.resources.count | Should -BeGreaterThan 1 } + It 'Export can be called on resource with input' { + $out = '{"count":3}' | dsc resource export -r Test/Export -f - | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 + $out.resources.count | Should -Be 3 + $out.resources[0].type | Should -BeExactly 'Test/Export' + $out.resources[0].properties.count | Should -Be 0 + $out.resources[1].type | Should -BeExactly 'Test/Export' + $out.resources[1].properties.count | Should -Be 1 + $out.resources[2].type | Should -BeExactly 'Test/Export' + $out.resources[2].properties.count | Should -Be 2 + } + It 'Export can be called on a configuration with the use of --output-format as a subcommand' { $yaml = @' diff --git a/tools/dsctest/dscexport.dsc.resource.json b/tools/dsctest/dscexport.dsc.resource.json new file mode 100644 index 00000000..f9752546 --- /dev/null +++ b/tools/dsctest/dscexport.dsc.resource.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", + "type": "Test/Export", + "version": "0.1.0", + "export": { + "executable": "dsctest", + "args": [ + "export", + { + "jsonInputArg": "--input", + "mandatory": true + } + ] + }, + "schema": { + "command": { + "executable": "dsctest", + "args": [ + "schema", + "-s", + "export" + ] + } + } +} diff --git a/tools/dsctest/src/args.rs b/tools/dsctest/src/args.rs index 7b4e3f26..8e4908ba 100644 --- a/tools/dsctest/src/args.rs +++ b/tools/dsctest/src/args.rs @@ -9,6 +9,7 @@ pub enum Schemas { Exist, ExitCode, InDesiredState, + Export, Sleep, Trace, WhatIf, @@ -47,6 +48,11 @@ pub enum SubCommand { #[clap(name = "input", short, long, help = "The input to the in desired state command as JSON")] input: String, }, + #[clap(name = "export", about = "Export instances")] + Export { + #[clap(name = "input", short, long, help = "The input to the export command as JSON")] + input: String, + }, #[clap(name = "schema", about = "Get the JSON schema for a subcommand")] Schema { diff --git a/tools/dsctest/src/export.rs b/tools/dsctest/src/export.rs new file mode 100644 index 00000000..328b0d94 --- /dev/null +++ b/tools/dsctest/src/export.rs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct Export { + /// Number of instances to return + pub count: u64, +} diff --git a/tools/dsctest/src/main.rs b/tools/dsctest/src/main.rs index d9f85a0b..c1b3f8d5 100644 --- a/tools/dsctest/src/main.rs +++ b/tools/dsctest/src/main.rs @@ -6,6 +6,7 @@ mod delete; mod exist; mod exit_code; mod in_desired_state; +mod export; mod sleep; mod trace; mod whatif; @@ -17,6 +18,7 @@ use crate::delete::Delete; use crate::exist::{Exist, State}; use crate::exit_code::ExitCode; use crate::in_desired_state::InDesiredState; +use crate::export::Export; use crate::sleep::Sleep; use crate::trace::Trace; use crate::whatif::WhatIf; @@ -79,6 +81,22 @@ fn main() { in_desired_state.value_two = 2; serde_json::to_string(&in_desired_state).unwrap() }, + SubCommand::Export { input } => { + let export = match serde_json::from_str::<Export>(&input) { + Ok(export) => export, + Err(err) => { + eprintln!("Error JSON does not match schema: {err}"); + std::process::exit(1); + } + }; + for i in 0..export.count { + let instance = Export { + count: i + }; + println!("{}", serde_json::to_string(&instance).unwrap()); + } + String::new() + }, SubCommand::Schema { subcommand } => { let schema = match subcommand { Schemas::Delete => { @@ -93,6 +111,9 @@ fn main() { Schemas::InDesiredState => { schema_for!(InDesiredState) }, + Schemas::Export => { + schema_for!(Export) + }, Schemas::Sleep => { schema_for!(Sleep) }, @@ -137,5 +158,7 @@ fn main() { }, }; - println!("{json}"); + if !json.is_empty() { + println!("{json}"); + } }