Skip to content
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
70 changes: 70 additions & 0 deletions dsc/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions dsc/tests/dsc_functions.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,80 @@ Describe 'tests for function expressions' {
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
($out.results[0].result.actualState.output | Out-String) | Should -BeExactly ($expected | Out-String)
}

It 'utcNow function works for: utcNow(<format>)' -TestCases @(
@{ format = $null}
@{ format = "yyyy-MM-dd"}
@{ format = "yyyy-MM-ddTHH"}
@{ format = "yyyy-MM-ddTHHZ"}
@{ format = "MMM dd, yyyy HH"}
@{ format = "yy-MMMM-dddd tt H" }
@{ format = "MMM ddd zzz" }
@{ format = "YY YYYY MM MMM MMMM" }
) {
param($format)

if ($null -eq $format) {
$expected = (Get-Date -AsUTC).ToString("o")
} else {
$expected = (Get-Date -AsUTC).ToString($format)
$format = "'$format'"
}

$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
parameters:
test:
type: string
defaultValue: "[utcNow($format)]"
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: "[parameters('test')]"
"@
$out = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
# ConvertFrom-Json will convert the date to a DateTime object, so we use regex to capture the string
$out -match '"output":"(?<date>.*?)"' | Should -BeTrue -Because "Output should contain a date"
$actual = $matches['date']
# since the datetimes might slightly differ, we remove the seconds and milliseconds
$expected = $expected -replace ':\d+\.\d+Z$', 'Z'
$actual = $actual -replace ':\d+\.\d+Z$', 'Z'
$actual | Should -BeExactly $expected -Because "Expected: '$expected', Actual: '$actual'"
}

It 'utcNow errors if used not as a parameter default' {
$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: "[utcNow()]"
"@
$out = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.log -Raw)
(Get-Content $TestDrive/error.log -Raw) | Should -Match 'utcNow function can only be used as a parameter default'
}

It 'uniqueString function works for: <expression>' -TestCases @(
@{ expression = "[uniqueString('a')]" ; expected = 'cfvwxu6sc4lqo' }
@{ expression = "[uniqueString('a', 'b', 'c')]" ; expected = 'bhw7m6t6ntwd6' }
@{ expression = "[uniqueString('a', 'b', 'c', 'd')]" ; expected = 'yxzg7ur4qetcy' }
) {
param($expression, $expected)

$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Echo
type: Microsoft.DSC.Debug/Echo
properties:
output: "$expression"
"@
$out = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
$out.results[0].result.actualState.output | Should -BeExactly $expected
}
}
70 changes: 70 additions & 0 deletions dsc_lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion dsc_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ split-debuginfo = "packed" # generates a seperate *.dwp/*.dSYM so the binary ca
strip = "symbols" # See split-debuginfo - allows us to drop the size by ~65%

[dependencies]
base32 = "0.5"
base64 = "0.22"
chrono = "0.4"
chrono = { version = "0.4", features = ["alloc"] }
clap = { version = "4.5", features = ["derive"] }
derive_builder ="0.20"
indicatif = "0.18"
jsonschema = { version = "0.30", default-features = false }
linked-hash-map = "0.5"
murmurhash64 = "0.3"
num-traits = "0.2"
path-absolutize = { version = "3.1" }
regex = "1.11"
Expand Down
17 changes: 17 additions & 0 deletions dsc_lib/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ description = "Checks if an array, object, or string is empty"
invoked = "empty function"
invalidArgType = "Invalid argument type, argument must be an array, object, or string"

[functions.endsWith]
description = "Checks if a string ends with a specific suffix"
invoked = "endsWith function"

[functions.envvar]
description = "Retrieves the value of an environment variable"
notFound = "Environment variable not found"
Expand Down Expand Up @@ -381,6 +385,10 @@ extensionReturnedError = "Extension '%{extension}': %{error}"
noExtensions = "No extensions supporting secrets was found"
secretNotFound = "Secret '%{name}' not found"

[functions.startsWith]
description = "Checks if a string starts with a specific prefix"
invoked = "startsWith function"

[functions.sub]
description = "Subtracts the second number from the first"
invoked = "sub function"
Expand All @@ -398,6 +406,15 @@ description = "Returns a single array or object with all elements from the param
invoked = "union function"
invalidArgType = "All arguments must either be arrays or objects"

[functions.uniqueString]
description = "Returns a deterministic unique string from the given strings"
invoked = "uniqueString function"

[functions.utcNow]
description = "Returns the current UTC time"
invoked = "utcNow function"
onlyUsedAsParameterDefault = "utcNow function can only be used as a parameter default"

[functions.variables]
description = "Retrieves the value of a variable"
invoked = "variables function"
Expand Down
2 changes: 2 additions & 0 deletions dsc_lib/src/configure/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct Context {
pub start_datetime: DateTime<Local>,
pub restart_required: Option<Vec<RestartRequired>>,
pub process_expressions: bool,
pub processing_parameter_defaults: bool,
}

impl Context {
Expand All @@ -39,6 +40,7 @@ impl Context {
start_datetime: chrono::Local::now(),
restart_required: None,
process_expressions: true,
processing_parameter_defaults: false,
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion dsc_lib/src/configure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,10 @@ impl Configurator {
// default values can be expressions
let value = if default_value.is_string() {
if let Some(value) = default_value.as_str() {
self.statement_parser.parse_and_execute(value, &self.context)?
self.context.processing_parameter_defaults = true;
let result = self.statement_parser.parse_and_execute(value, &self.context)?;
self.context.processing_parameter_defaults = false;
result
} else {
return Err(DscError::Parser(t!("configure.mod.defaultStringNotDefined").to_string()));
}
Expand Down
Loading
Loading