Skip to content

Commit c89f5dd

Browse files
committed
Add last() function
1 parent b4f0fb2 commit c89f5dd

File tree

5 files changed

+392
-0
lines changed

5 files changed

+392
-0
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
---
2+
description: Reference for the 'last' DSC configuration document function
3+
ms.date: 01/25/2025
4+
ms.topic: reference
5+
title: last
6+
---
7+
8+
## Synopsis
9+
10+
Returns the last element of an array, or the last character of a string.
11+
12+
## Syntax
13+
14+
```Syntax
15+
last(arg)
16+
```
17+
18+
## Description
19+
20+
The `last()` function returns the final element from an array or the final
21+
character from a string. This is useful when you need to access the most recent
22+
item in a sequence, the final stage in a deployment pipeline, or the last
23+
character in a configuration value.
24+
25+
For arrays, it returns the element at index `length - 1`. For strings, it
26+
returns the last character as a string. If the input is empty, an error is
27+
returned.
28+
29+
## Examples
30+
31+
### Example 1 - Extract the final deployment stage (array of strings)
32+
33+
Use `last()` to retrieve the final stage in a multi-stage deployment pipeline.
34+
This helps you identify which environment or phase should receive special
35+
handling, such as extended health checks or manual approval gates. This example
36+
uses [`createArray()`][01] to build the deployment stages.
37+
38+
```yaml
39+
# last.example.1.dsc.config.yaml
40+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
41+
resources:
42+
- name: Deployment Pipeline
43+
type: Microsoft.DSC.Debug/Echo
44+
properties:
45+
output:
46+
finalStage: "[last(createArray('dev', 'test', 'staging', 'production'))]"
47+
requiresApproval: true
48+
```
49+
50+
```bash
51+
dsc config get --file last.example.1.dsc.config.yaml
52+
```
53+
54+
```yaml
55+
results:
56+
- name: Deployment Pipeline
57+
type: Microsoft.DSC.Debug/Echo
58+
result:
59+
actualState:
60+
output:
61+
finalStage: production
62+
requiresApproval: true
63+
messages: []
64+
hadErrors: false
65+
```
66+
67+
This identifies `production` as the final stage, allowing you to apply
68+
production-specific policies or validations.
69+
70+
### Example 2 - Get the last character of a configuration string
71+
72+
Use `last()` to extract the final character from a string value. This is useful
73+
for parsing identifiers, checking suffixes, or validating format conventions
74+
like version numbers or region codes.
75+
76+
```yaml
77+
# last.example.2.dsc.config.yaml
78+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
79+
resources:
80+
- name: Region Identifier
81+
type: Microsoft.DSC.Debug/Echo
82+
properties:
83+
output:
84+
regionCode: us-west-2
85+
zoneSuffix: "[last('us-west-2')]"
86+
description: "Zone suffix extracted from region code"
87+
```
88+
89+
```bash
90+
dsc config get --file last.example.2.dsc.config.yaml
91+
```
92+
93+
```yaml
94+
results:
95+
- name: Region Identifier
96+
type: Microsoft.DSC.Debug/Echo
97+
result:
98+
actualState:
99+
output:
100+
regionCode: us-west-2
101+
zoneSuffix: '2'
102+
description: Zone suffix extracted from region code
103+
messages: []
104+
hadErrors: false
105+
```
106+
107+
The function returns `'2'` as a single-character string, representing the zone
108+
suffix in the region identifier.
109+
110+
### Example 3 - Identify the most recent backup (array of numbers)
111+
112+
Use `last()` with numerical arrays to find the most recent timestamp or version
113+
number. This example shows how to select the latest backup from a sorted list
114+
of timestamps. This example uses [`createArray()`][01] to build the backup
115+
timestamps.
116+
117+
```yaml
118+
# last.example.3.dsc.config.yaml
119+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
120+
resources:
121+
- name: Backup Selection
122+
type: Microsoft.DSC.Debug/Echo
123+
properties:
124+
output:
125+
availableBackups: "[createArray(1704067200, 1704153600, 1704240000, 1704326400)]"
126+
latestBackup: "[last(createArray(1704067200, 1704153600, 1704240000, 1704326400))]"
127+
description: "Most recent backup timestamp (Unix epoch)"
128+
```
129+
130+
```bash
131+
dsc config get --file last.example.3.dsc.config.yaml
132+
```
133+
134+
```yaml
135+
results:
136+
- name: Backup Selection
137+
type: Microsoft.DSC.Debug/Echo
138+
result:
139+
actualState:
140+
output:
141+
availableBackups:
142+
- 1704067200
143+
- 1704153600
144+
- 1704240000
145+
- 1704326400
146+
latestBackup: 1704326400
147+
description: Most recent backup timestamp (Unix epoch)
148+
messages: []
149+
hadErrors: false
150+
```
151+
152+
The function returns `1704326400`, which represents the most recent backup in
153+
the chronologically sorted array.
154+
155+
### Example 4 - Combine with other functions for complex logic
156+
157+
Use `last()` together with [`split()`][02] to extract file extensions or path
158+
components. This example demonstrates parsing a filename to get its extension.
159+
160+
```yaml
161+
# last.example.4.dsc.config.yaml
162+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
163+
resources:
164+
- name: File Extension Parser
165+
type: Microsoft.DSC.Debug/Echo
166+
properties:
167+
output:
168+
filename: config.production.yaml
169+
extension: "[last(split('config.production.yaml', '.'))]"
170+
```
171+
172+
```bash
173+
dsc config get --file last.example.4.dsc.config.yaml
174+
```
175+
176+
```yaml
177+
results:
178+
- name: File Extension Parser
179+
type: Microsoft.DSC.Debug/Echo
180+
result:
181+
actualState:
182+
output:
183+
filename: config.production.yaml
184+
extension: yaml
185+
messages: []
186+
hadErrors: false
187+
```
188+
189+
By combining `split()` and `last()`, you can extract the `yaml` extension from
190+
the full filename.
191+
192+
## Parameters
193+
194+
### arg
195+
196+
The array or string to get the last element or character from. Required.
197+
198+
```yaml
199+
Type: array | string
200+
Required: true
201+
Position: 1
202+
```
203+
204+
## Output
205+
206+
Returns the last element of the array (preserving its original type) or the
207+
last character as a string. For arrays, the return type matches the element
208+
type. For strings, returns a single-character string.
209+
210+
```yaml
211+
Type: any | string
212+
```
213+
214+
## Errors
215+
216+
The function returns an error in the following cases:
217+
218+
- **Empty array**: The input array has no elements
219+
- **Empty string**: The input string has no characters
220+
- **Invalid type**: The argument is not an array or string
221+
222+
## Related functions
223+
224+
- [`first()`][00] - Returns the first element of an array or character of a string
225+
- [`split()`][02] - Splits a string into an array
226+
- [`createArray()`][01] - Creates an array from provided values
227+
228+
<!-- Link reference definitions -->
229+
[00]: ./first.md
230+
[01]: ./createArray.md
231+
[02]: ./split.md

dsc/tests/dsc_functions.tests.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,28 @@ Describe 'tests for function expressions' {
504504
($out.results[0].result.actualState.output | Out-String) | Should -BeExactly ($expected | Out-String)
505505
}
506506

507+
It 'last function works for: <expression>' -TestCases @(
508+
@{ expression = "[last(createArray('hello', 'world'))]"; expected = 'world' }
509+
@{ expression = "[last(createArray(1, 2, 3))]"; expected = 3 }
510+
@{ expression = "[last('hello')]"; expected = 'o' }
511+
@{ expression = "[last('a')]"; expected = 'a' }
512+
@{ expression = "[last(array('mixed'))]"; expected = 'mixed' }
513+
) {
514+
param($expression, $expected)
515+
516+
$config_yaml = @"
517+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
518+
resources:
519+
- name: Echo
520+
type: Microsoft.DSC.Debug/Echo
521+
properties:
522+
output: "$expression"
523+
"@
524+
$out = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log | ConvertFrom-Json
525+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
526+
($out.results[0].result.actualState.output | Out-String) | Should -BeExactly ($expected | Out-String)
527+
}
528+
507529
It 'indexOf function works for: <expression>' -TestCases @(
508530
@{ expression = "[indexOf(createArray('apple', 'banana', 'cherry'), 'banana')]"; expected = 1 }
509531
@{ expression = "[indexOf(createArray('apple', 'banana', 'cherry'), 'cherry')]"; expected = 2 }

lib/dsc-lib/locales/en-us.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,13 @@ emptyArray = "Cannot get first element of empty array"
343343
emptyString = "Cannot get first character of empty string"
344344
invalidArgType = "Invalid argument type, argument must be an array or string"
345345

346+
[functions.last]
347+
description = "Returns the last element of an array or last character of a string"
348+
invoked = "last function"
349+
emptyArray = "Cannot get last element of empty array"
350+
emptyString = "Cannot get last character of empty string"
351+
invalidArgType = "Invalid argument type, argument must be an array or string"
352+
346353
[functions.greater]
347354
description = "Evaluates if the first value is greater than the second value"
348355
invoked = "greater function"

0 commit comments

Comments
 (0)