Skip to content

Commit d9f140c

Browse files
author
Steve Lee (POWERSHELL HE/HIM) (from Dev Box)
committed
Fix tool and add tests
1 parent 274eb46 commit d9f140c

File tree

6 files changed

+132
-4
lines changed

6 files changed

+132
-4
lines changed

dsc/src/mcp/invoke_dsc_resource.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize};
2222
use tokio::task;
2323

2424
#[derive(Deserialize, JsonSchema)]
25-
#[serde(rename_all = "lowercase", untagged)]
25+
#[serde(rename_all = "lowercase")]
2626
pub enum DscOperation {
2727
Get,
2828
Set,

dsc/tests/dsc_mcp.tests.ps1

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ Describe 'Tests for MCP server' {
2020
while ($mcp.StandardOutput.Peek() -eq -1) {
2121
Start-Sleep -Milliseconds 100
2222
}
23-
while ($mcp.StandardError.Peek() -ne -1) {
24-
$stderr = $mcp.StandardError.ReadLine()
25-
}
2623
$stdout = $mcp.StandardOutput.ReadLine()
2724
return ($stdout | ConvertFrom-Json -Depth 30)
2825
}
@@ -302,4 +299,38 @@ Describe 'Tests for MCP server' {
302299
$response.result.structuredContent.functions.Count | Should -Be 0
303300
$response.result.structuredContent.functions | Should -BeNullOrEmpty
304301
}
302+
303+
It 'Calling invoke_dsc_resource for operation: <operation>' -TestCases @(
304+
@{ operation = 'get'; property = 'actualState' }
305+
@{ operation = 'set'; property = 'beforeState' }
306+
@{ operation = 'test'; property = 'desiredState' }
307+
@{ operation = 'export'; property = 'actualState' }
308+
) {
309+
param($operation)
310+
311+
$mcpRequest = @{
312+
jsonrpc = "2.0"
313+
id = 12
314+
method = "tools/call"
315+
params = @{
316+
name = "invoke_dsc_resource"
317+
arguments = @{
318+
type = 'Test/Operation'
319+
operation = $operation
320+
resource_type = 'Test/Operation'
321+
properties_json = (@{
322+
hello = "World"
323+
action = $operation
324+
} | ConvertTo-Json -Depth 20)
325+
}
326+
}
327+
}
328+
329+
$response = Send-McpRequest -request $mcpRequest
330+
$response.id | Should -Be 12
331+
$because = ($response | ConvertTo-Json -Depth 20 | Out-String)
332+
($response.result.structuredContent.psobject.properties | Measure-Object).Count | Should -Be 1 -Because $because
333+
$response.result.structuredContent.result.$property.action | Should -BeExactly $operation -Because $because
334+
$response.result.structuredContent.result.$property.hello | Should -BeExactly "World" -Because $because
335+
}
305336
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
3+
"type": "Test/Operation",
4+
"version": "0.1.0",
5+
"get": {
6+
"executable": "dsctest",
7+
"args": [
8+
"operation",
9+
"--operation",
10+
"get",
11+
{
12+
"jsonInputArg": "--input"
13+
}
14+
]
15+
},
16+
"set": {
17+
"executable": "dsctest",
18+
"args": [
19+
"operation",
20+
"--operation",
21+
"set",
22+
{
23+
"jsonInputArg": "--input"
24+
}
25+
]
26+
},
27+
"test": {
28+
"executable": "dsctest",
29+
"args": [
30+
"operation",
31+
"--operation",
32+
"trace",
33+
{
34+
"jsonInputArg": "--input"
35+
}
36+
]
37+
},
38+
"export": {
39+
"executable": "dsctest",
40+
"args": [
41+
"operation",
42+
"--operation",
43+
"export",
44+
{
45+
"jsonInputArg": "--input"
46+
}
47+
]
48+
},
49+
"schema": {
50+
"command": {
51+
"executable": "dsctest",
52+
"args": [
53+
"schema",
54+
"-s",
55+
"operation"
56+
]
57+
}
58+
}
59+
}

tools/dsctest/src/args.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub enum Schemas {
1414
Get,
1515
InDesiredState,
1616
Metadata,
17+
Operation,
1718
Sleep,
1819
Trace,
1920
Version,
@@ -100,6 +101,14 @@ pub enum SubCommand {
100101
export: bool,
101102
},
102103

104+
#[clap(name = "operation", about = "Perform an operation")]
105+
Operation {
106+
#[clap(name = "operation", short, long, help = "The name of the operation to perform")]
107+
operation: String,
108+
#[clap(name = "input", short, long, help = "The input to the operation command as JSON")]
109+
input: String,
110+
},
111+
103112
#[clap(name = "schema", about = "Get the JSON schema for a subcommand")]
104113
Schema {
105114
#[clap(name = "subcommand", short, long, help = "The subcommand to get the schema for")]

tools/dsctest/src/main.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod exporter;
1010
mod get;
1111
mod in_desired_state;
1212
mod metadata;
13+
mod operation;
1314
mod adapter;
1415
mod sleep;
1516
mod trace;
@@ -28,6 +29,7 @@ use crate::exporter::{Exporter, Resource};
2829
use crate::get::Get;
2930
use crate::in_desired_state::InDesiredState;
3031
use crate::metadata::Metadata;
32+
use crate::operation::Operation;
3133
use crate::sleep::Sleep;
3234
use crate::trace::Trace;
3335
use crate::version::Version;
@@ -209,6 +211,17 @@ fn main() {
209211
}
210212
String::new()
211213
},
214+
SubCommand::Operation { operation, input } => {
215+
let mut operation_result = match serde_json::from_str::<Operation>(&input) {
216+
Ok(op) => op,
217+
Err(err) => {
218+
eprintln!("Error JSON does not match schema: {err}");
219+
std::process::exit(1);
220+
}
221+
};
222+
operation_result.operation = Some(operation.to_lowercase());
223+
serde_json::to_string(&operation_result).unwrap()
224+
},
212225
SubCommand::Schema { subcommand } => {
213226
let schema = match subcommand {
214227
Schemas::Adapter => {
@@ -238,6 +251,9 @@ fn main() {
238251
Schemas::Metadata => {
239252
schema_for!(Metadata)
240253
},
254+
Schemas::Operation => {
255+
schema_for!(Operation)
256+
},
241257
Schemas::Sleep => {
242258
schema_for!(Sleep)
243259
},

tools/dsctest/src/operation.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use schemars::JsonSchema;
5+
use serde::{Deserialize, Serialize};
6+
use serde_json::{Map, Value};
7+
8+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
9+
pub struct Operation {
10+
pub operation: Option<String>,
11+
#[serde(flatten)]
12+
pub params: Map<String, Value>,
13+
}

0 commit comments

Comments
 (0)