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

add metadata to configuration result output #405

Merged
merged 8 commits into from
Apr 15, 2024
Merged
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
2 changes: 1 addition & 1 deletion dsc/examples/require_admin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
metadata:
Microsoft.DSC:
requiredSecurityContext: Elevated
securityContext: Elevated
resources:
- name: os
type: Microsoft/OSInfo
Expand Down
2 changes: 1 addition & 1 deletion dsc/examples/require_nonadmin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
metadata:
Microsoft.DSC:
requiredSecurityContext: Restricted
securityContext: Restricted
resources:
- name: os
type: Microsoft/OSInfo
Expand Down
14 changes: 13 additions & 1 deletion dsc/tests/dsc_config_get.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,19 @@ Describe 'dsc config get tests' {
properties:
output: hello
"@
$null = $config_yaml | dsc config get --format pretty-json | Out-String
$result = $config_yaml | dsc config get --format pretty-json | ConvertFrom-Json
$result.hadErrors | Should -BeFalse
$result.results.Count | Should -Be 1
$result.results[0].Name | Should -Be 'Echo'
$result.results[0].type | Should -BeExactly 'Test/Echo'
$result.results[0].result.actualState.output | Should -Be 'hello'
$result.metadata.'Microsoft.DSC'.version | Should -BeLike '3.*'
$result.metadata.'Microsoft.DSC'.operation | Should -BeExactly 'Get'
$result.metadata.'Microsoft.DSC'.executionType | Should -BeExactly 'Actual'
$result.metadata.'Microsoft.DSC'.startDatetime | Should -Not -BeNullOrEmpty
$result.metadata.'Microsoft.DSC'.endDatetime | Should -Not -BeNullOrEmpty
$result.metadata.'Microsoft.DSC'.duration | Should -Not -BeNullOrEmpty
$result.metadata.'Microsoft.DSC'.securityContext | Should -Not -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}
}
10 changes: 10 additions & 0 deletions dsc/tests/dsc_config_set.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Describe 'dsc config set tests' {
"@
$out = $config_yaml | dsc config set | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.hadErrors | Should -BeFalse
$out.results.Count | Should -Be 2
$out.results[0].type | Should -BeExactly 'Test/Exist'
$out.results[0].result.beforeState._exist | Should -BeFalse
$out.results[0].result.afterState.state | Should -BeExactly 'Absent'
Expand All @@ -26,5 +28,13 @@ Describe 'dsc config set tests' {
$out.results[1].result.beforeState._exist | Should -BeFalse
$out.results[1].result.afterState.deleteCalled | Should -BeTrue
$out.results[1].result.afterState._exist | Should -BeFalse
$out.metadata.'Microsoft.DSC'.version | Should -BeLike '3.*'
$out.metadata.'Microsoft.DSC'.operation | Should -BeExactly 'Set'
$out.metadata.'Microsoft.DSC'.executionType | Should -BeExactly 'Actual'
$out.metadata.'Microsoft.DSC'.startDatetime | Should -Not -BeNullOrEmpty
$out.metadata.'Microsoft.DSC'.endDatetime | Should -Not -BeNullOrEmpty
$out.metadata.'Microsoft.DSC'.duration | Should -Not -BeNullOrEmpty
$out.metadata.'Microsoft.DSC'.securityContext | Should -Not -BeNullOrEmpty

}
}
1 change: 1 addition & 0 deletions dsc/tests/dsc_export.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Describe 'resource export tests' {
$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
$config_with_process_list.metadata.'Microsoft.DSC'.operation | Should -BeExactly 'Export'
}

It 'Configuration Export can be piped to configuration Set' -Skip:(!$IsWindows) {
Expand Down
48 changes: 39 additions & 9 deletions dsc/tests/dsc_group.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,68 @@ Describe 'Group resource tests' {
It 'Nested groups should work for get' {
$out = (dsc config get -p $PSScriptRoot/../examples/groups.dsc.yaml -f yaml | Out-String).Trim()
$LASTEXITCODE | Should -Be 0
$out | Should -BeExactly @'
$out | Should -BeLike @'
metadata:
Microsoft.DSC:
version: 3*
operation: Get
executionType: Actual
startDatetime: *
endDatetime: *
duration: PT*S
securityContext: *
results:
- name: First Group
- metadata:
Microsoft.DSC:
duration: *
name: First Group
type: Microsoft.DSC/Group
result:
- name: First
- metadata:
Microsoft.DSC:
duration: *
name: First
type: Test/Echo
result:
actualState:
output: First
- name: Nested Group
- metadata:
Microsoft.DSC:
duration: *
name: Nested Group
type: Microsoft.DSC/Group
result:
- name: Nested First
- metadata:
Microsoft.DSC:
duration: *
name: Nested First
type: Test/Echo
result:
actualState:
output: Nested First
- name: Nested Second
- metadata:
Microsoft.DSC:
duration: *
name: Nested Second
type: Test/Echo
result:
actualState:
output: Nested Second
- name: Last Group
- metadata:
Microsoft.DSC:
duration: *
name: Last Group
type: Microsoft.DSC/Group
result:
- name: Last
- metadata:
Microsoft.DSC:
duration: *
name: Last
type: Test/Echo
result:
actualState:
output: Last
messages: []
messages: `[`]
hadErrors: false
'@
}
Expand Down
2 changes: 1 addition & 1 deletion dsc_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"

[dependencies]
base64 = "0.22"
chrono = "0.4.26"
chrono = { version = "0.4.26" }
derive_builder ="0.20"
indicatif = { version = "0.17" }
jsonschema = "0.17"
Expand Down
38 changes: 36 additions & 2 deletions dsc_lib/src/configure/config_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,45 @@ pub enum SecurityContextKind {
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
pub enum Operation {
Get,
Set,
Test,
Export,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
pub enum ExecutionKind {
Actual,
WhatIf,
}

#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
pub struct MicrosoftDscMetadata {
/// Version of DSC
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
/// The operation being performed
#[serde(skip_serializing_if = "Option::is_none")]
pub operation: Option<Operation>,
/// The type of execution
#[serde(rename = "executionType", skip_serializing_if = "Option::is_none")]
pub execution_type: Option<ExecutionKind>,
/// The start time of the configuration operation
#[serde(rename = "startDatetime", skip_serializing_if = "Option::is_none")]
pub start_datetime: Option<String>,
/// The end time of the configuration operation
#[serde(rename = "endDatetime", skip_serializing_if = "Option::is_none")]
pub end_datetime: Option<String>,
/// The duration of the configuration operation
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<String>,
/// The security context of the configuration operation, can be specified to be required
#[serde(rename = "securityContext", skip_serializing_if = "Option::is_none")]
pub security_context: Option<SecurityContextKind>,
/// Identifies if the operation is part of a configuration
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<ContextKind>,
#[serde(rename = "requiredSecurityContext", skip_serializing_if = "Option::is_none")]
pub required_security_context: Option<SecurityContextKind>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
Expand Down
20 changes: 18 additions & 2 deletions dsc_lib/src/configure/config_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::dscresources::invoke_result::{GetResult, SetResult, TestResult};
use crate::configure::config_doc;
use crate::configure::config_doc::{Configuration, Metadata};

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
pub enum MessageLevel {
Expand All @@ -26,6 +26,8 @@ pub struct ResourceMessage {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ResourceGetResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
pub name: String,
#[serde(rename="type")]
pub resource_type: String,
Expand All @@ -35,6 +37,7 @@ pub struct ResourceGetResult {
impl From<ResourceTestResult> for ResourceGetResult {
fn from(test_result: ResourceTestResult) -> Self {
Self {
metadata: None,
name: test_result.name,
resource_type: test_result.resource_type,
result: test_result.result.into(),
Expand All @@ -45,6 +48,7 @@ impl From<ResourceTestResult> for ResourceGetResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ConfigurationGetResult {
pub metadata: Option<Metadata>,
pub results: Vec<ResourceGetResult>,
pub messages: Vec<ResourceMessage>,
#[serde(rename = "hadErrors")]
Expand All @@ -55,6 +59,7 @@ impl ConfigurationGetResult {
#[must_use]
pub fn new() -> Self {
Self {
metadata: None,
results: Vec::new(),
messages: Vec::new(),
had_errors: false,
Expand All @@ -75,6 +80,7 @@ impl From<ConfigurationTestResult> for ConfigurationGetResult {
results.push(result.into());
}
Self {
metadata: None,
results,
messages: test_result.messages,
had_errors: test_result.had_errors,
Expand All @@ -85,6 +91,8 @@ impl From<ConfigurationTestResult> for ConfigurationGetResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ResourceSetResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
pub name: String,
#[serde(rename="type")]
pub resource_type: String,
Expand Down Expand Up @@ -115,6 +123,7 @@ impl Default for GroupResourceSetResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ConfigurationSetResult {
pub metadata: Option<Metadata>,
pub results: Vec<ResourceSetResult>,
pub messages: Vec<ResourceMessage>,
#[serde(rename = "hadErrors")]
Expand All @@ -125,6 +134,7 @@ impl ConfigurationSetResult {
#[must_use]
pub fn new() -> Self {
Self {
metadata: None,
results: Vec::new(),
messages: Vec::new(),
had_errors: false,
Expand All @@ -141,6 +151,8 @@ impl Default for ConfigurationSetResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ResourceTestResult {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
pub name: String,
#[serde(rename="type")]
pub resource_type: String,
Expand Down Expand Up @@ -171,6 +183,7 @@ impl Default for GroupResourceTestResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ConfigurationTestResult {
pub metadata: Option<Metadata>,
pub results: Vec<ResourceTestResult>,
pub messages: Vec<ResourceMessage>,
#[serde(rename = "hadErrors")]
Expand All @@ -181,6 +194,7 @@ impl ConfigurationTestResult {
#[must_use]
pub fn new() -> Self {
Self {
metadata: None,
results: Vec::new(),
messages: Vec::new(),
had_errors: false,
Expand All @@ -197,7 +211,8 @@ impl Default for ConfigurationTestResult {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ConfigurationExportResult {
pub result: Option<config_doc::Configuration>,
pub metadata: Option<Metadata>,
pub result: Option<Configuration>,
pub messages: Vec<ResourceMessage>,
#[serde(rename = "hadErrors")]
pub had_errors: bool,
Expand All @@ -207,6 +222,7 @@ impl ConfigurationExportResult {
#[must_use]
pub fn new() -> Self {
Self {
metadata: None,
result: None,
messages: Vec::new(),
had_errors: false,
Expand Down
19 changes: 16 additions & 3 deletions dsc_lib/src/configure/context.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use chrono::{DateTime, Local};
use crate::configure::config_doc::ExecutionKind;
use security_context_lib::{get_security_context, SecurityContext};
use serde_json::Value;
use std::collections::HashMap;

use super::config_doc::DataType;
use super::config_doc::{DataType, SecurityContextKind};

pub struct Context {
pub execution_type: ExecutionKind,
pub outputs: HashMap<String, Value>, // this is used by the `reference()` function to retrieve output
pub parameters: HashMap<String, (Value, DataType)>,
pub security_context: SecurityContextKind,
_variables: HashMap<String, Value>,
pub outputs: HashMap<String, Value>, // this is used by the `reference()` function to retrieve output

pub start_datetime: DateTime<Local>,
}

impl Context {
#[must_use]
pub fn new() -> Self {
Self {
execution_type: ExecutionKind::Actual,
outputs: HashMap::new(),
parameters: HashMap::new(),
security_context: match get_security_context() {
SecurityContext::Admin => SecurityContextKind::Elevated,
SecurityContext::User => SecurityContextKind::Restricted,
},
_variables: HashMap::new(),
outputs: HashMap::new(),
start_datetime: chrono::Local::now(),
}
}
}
Expand Down
Loading
Loading