Skip to content

Commit 0ec3d7c

Browse files
authored
Merge pull request #1138 from Gijsreyn/gh-57/main/add-intersection-function
Add `intersection()` function
2 parents f3abfc1 + 5bcd204 commit 0ec3d7c

File tree

5 files changed

+515
-0
lines changed

5 files changed

+515
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
---
2+
description: Reference for the 'intersection' DSC configuration document function
3+
ms.date: 09/26/2025
4+
ms.topic: reference
5+
title: intersection
6+
---
7+
8+
## Synopsis
9+
10+
Returns a single array or object with the common elements from the parameters.
11+
12+
## Syntax
13+
14+
```Syntax
15+
intersection(value1, value2, ...)
16+
```
17+
18+
## Description
19+
20+
The `intersection()` function takes two or more arrays or objects and returns
21+
only the elements that exist in all of them. For arrays, it returns elements
22+
that appear in every array. For objects, it returns key-value pairs where both
23+
the key and value match across all objects.
24+
25+
All parameters must be the same type - either all arrays or all objects.
26+
Results are deduplicated, meaning each element appears only once in the output.
27+
28+
Supported types:
29+
30+
- Arrays (elements compared by value)
31+
- Objects (key-value pairs compared by deep equality)
32+
33+
## Examples
34+
35+
### Example 1 - Find common security groups across environments (arrays)
36+
37+
Use `intersection()` to identify security groups that are consistently applied
38+
across development, staging, and production environments. This helps ensure
39+
security policies are uniformly enforced. This example uses
40+
[`createArray()`][01] to build the security group lists.
41+
42+
```yaml
43+
# intersection.example.1.dsc.config.yaml
44+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
45+
resources:
46+
- name: Common Security Groups
47+
type: Microsoft.DSC.Debug/Echo
48+
properties:
49+
output:
50+
commonGroups: "[intersection(createArray('admin-access', 'monitoring', 'backup'), createArray('monitoring', 'backup', 'web-access'), createArray('backup', 'monitoring', 'database'))]"
51+
twoEnvCommon: "[intersection(createArray('admin-access', 'monitoring'), createArray('monitoring', 'audit-log'))]"
52+
```
53+
54+
```bash
55+
dsc config get --file intersection.example.1.dsc.config.yaml
56+
```
57+
58+
```yaml
59+
results:
60+
- name: Common Security Groups
61+
type: Microsoft.DSC.Debug/Echo
62+
result:
63+
actualState:
64+
output:
65+
commonGroups:
66+
- monitoring
67+
- backup
68+
twoEnvCommon:
69+
- monitoring
70+
messages: []
71+
hadErrors: false
72+
```
73+
74+
### Example 2 - Identify shared configuration properties (objects)
75+
76+
Find configuration settings that are identical across multiple service
77+
instances. This is useful for extracting common configuration into shared
78+
templates or validating consistency. This example uses [`createObject()`][02]
79+
to build configuration objects.
80+
81+
```yaml
82+
# intersection.example.2.dsc.config.yaml
83+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
84+
resources:
85+
- name: Shared Config Properties
86+
type: Microsoft.DSC.Debug/Echo
87+
properties:
88+
output:
89+
commonSettings: "[intersection(createObject('timeout', 30, 'retries', 3, 'region', 'us-east'), createObject('retries', 3, 'ssl', true, 'region', 'us-east'), createObject('region', 'us-east', 'retries', 3, 'logging', 'info'))]"
90+
```
91+
92+
```bash
93+
dsc config get --file intersection.example.2.dsc.config.yaml
94+
```
95+
96+
```yaml
97+
results:
98+
- name: Shared Config Properties
99+
type: Microsoft.DSC.Debug/Echo
100+
result:
101+
actualState:
102+
output:
103+
commonSettings:
104+
region: us-east
105+
retries: 3
106+
messages: []
107+
hadErrors: false
108+
```
109+
110+
### Example 3 - Find overlapping server capabilities (arrays with no matches)
111+
112+
Sometimes environments have no common elements, which is valuable information
113+
for infrastructure planning. This example shows how `intersection()` handles
114+
arrays with no shared elements.
115+
116+
```yaml
117+
# intersection.example.3.dsc.config.yaml
118+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
119+
resources:
120+
- name: Server Capabilities
121+
type: Microsoft.DSC.Debug/Echo
122+
properties:
123+
output:
124+
noOverlap: "[intersection(createArray('windows-iis', 'dotnet-core'), createArray('linux-apache', 'php', 'mysql'))]"
125+
someOverlap: "[intersection(createArray('docker', 'kubernetes', 'monitoring'), createArray('monitoring', 'logging', 'docker'))]"
126+
```
127+
128+
```bash
129+
dsc config get --file intersection.example.3.dsc.config.yaml
130+
```
131+
132+
```yaml
133+
results:
134+
- name: Server Capabilities
135+
type: Microsoft.DSC.Debug/Echo
136+
result:
137+
actualState:
138+
output:
139+
noOverlap: []
140+
someOverlap:
141+
- docker
142+
- monitoring
143+
messages: []
144+
hadErrors: false
145+
```
146+
147+
### Example 4 - Validate compliance across teams (objects)
148+
149+
Use `intersection()` to verify that critical compliance settings are identical
150+
across different team configurations. Only settings with matching values will
151+
appear in the result.
152+
153+
```yaml
154+
# intersection.example.4.dsc.config.yaml
155+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
156+
resources:
157+
- name: Compliance Check
158+
type: Microsoft.DSC.Debug/Echo
159+
properties:
160+
output:
161+
sharedCompliance: "[intersection(createObject('encryption', true, 'backup', 'daily', 'audit', true), createObject('audit', true, 'encryption', true, 'access', 'restricted'), createObject('encryption', true, 'audit', true, 'monitoring', 'enabled'))]"
162+
```
163+
164+
```bash
165+
dsc config get --file intersection.example.4.dsc.config.yaml
166+
```
167+
168+
```yaml
169+
results:
170+
- name: Compliance Check
171+
type: Microsoft.DSC.Debug/Echo
172+
result:
173+
actualState:
174+
output:
175+
sharedCompliance:
176+
audit: true
177+
encryption: true
178+
messages: []
179+
hadErrors: false
180+
```
181+
182+
## Parameters
183+
184+
### value1
185+
186+
The first array or object to compare. Required.
187+
188+
```yaml
189+
Type: array | object
190+
Required: true
191+
Position: 1
192+
```
193+
194+
### value2
195+
196+
The second array or object to compare. Must be the same type as value1.
197+
Required.
198+
199+
```yaml
200+
Type: array | object
201+
Required: true
202+
Position: 2
203+
```
204+
205+
### Additional values
206+
207+
Additional arrays or objects to include in the intersection. All must be the
208+
same type. Optional.
209+
210+
```yaml
211+
Type: array | object
212+
Required: false
213+
Position: 3+
214+
```
215+
216+
## Output
217+
218+
Returns an array or object containing only the common elements. The return type
219+
matches the input type.
220+
221+
```yaml
222+
Type: array | object
223+
```
224+
225+
## Related functions
226+
227+
- [`union()`][00] - Combines all elements from multiple arrays or objects
228+
- [`contains()`][03] - Checks for presence in arrays/objects/strings
229+
- [`createArray()`][01] - Creates an array from individual values
230+
- [`createObject()`][02] - Creates an object from key-value pairs
231+
232+
<!-- Link reference definitions -->
233+
[00]: ./union.md
234+
[01]: ./createArray.md
235+
[02]: ./createObject.md
236+
[03]: ./contains.md

dsc/tests/dsc_functions.tests.ps1

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,125 @@ Describe 'tests for function expressions' {
111111
}
112112
}
113113

114+
It 'intersection function works for: <expression>' -TestCases @(
115+
@{ expression = "[intersection(parameters('firstArray'), parameters('secondArray'))]"; expected = @('cd') }
116+
@{ expression = "[intersection(parameters('firstObject'), parameters('secondObject'))]"; expected = [pscustomobject]@{ two = 'b' } }
117+
@{ expression = "[intersection(parameters('thirdArray'), parameters('fourthArray'))]"; expected = @('ef', 'gh') }
118+
@{ expression = "[intersection(parameters('thirdObject'), parameters('fourthObject'))]"; expected = [pscustomobject]@{ three = 'd' } }
119+
@{ expression = "[intersection(parameters('firstArray'), parameters('thirdArray'))]"; expected = @() }
120+
@{ expression = "[intersection(parameters('firstObject'), parameters('firstArray'))]"; isError = $true }
121+
@{ expression = "[intersection(parameters('firstArray'), parameters('secondArray'), parameters('fifthArray'))]"; expected = @('cd') }
122+
@{ expression = "[intersection(parameters('firstObject'), parameters('secondObject'), parameters('sixthObject'))]"; expected = [pscustomobject]@{ two = 'b' } }
123+
@{ expression = "[intersection(parameters('nestedObject1'), parameters('nestedObject2'))]"; expected = [pscustomobject]@{
124+
shared = [pscustomobject]@{ value = 42; flag = $true }
125+
level = 1
126+
} }
127+
@{ expression = "[intersection(parameters('nestedObject1'), parameters('nestedObject3'))]"; expected = [pscustomobject]@{ level = 1 } }
128+
@{ expression = "[intersection(parameters('nestedObject1'), parameters('nestedObject2'), parameters('nestedObject4'))]"; expected = [pscustomobject]@{ level = 1 } }
129+
) {
130+
param($expression, $expected, $isError)
131+
132+
$config_yaml = @"
133+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
134+
parameters:
135+
firstObject:
136+
type: object
137+
defaultValue:
138+
one: a
139+
two: b
140+
secondObject:
141+
type: object
142+
defaultValue:
143+
two: b
144+
three: d
145+
thirdObject:
146+
type: object
147+
defaultValue:
148+
two: c
149+
three: d
150+
fourthObject:
151+
type: object
152+
defaultValue:
153+
three: d
154+
four: e
155+
sixthObject:
156+
type: object
157+
defaultValue:
158+
two: b
159+
five: f
160+
nestedObject1:
161+
type: object
162+
defaultValue:
163+
shared:
164+
value: 42
165+
flag: true
166+
level: 1
167+
unique1: test
168+
nestedObject2:
169+
type: object
170+
defaultValue:
171+
shared:
172+
value: 42
173+
flag: true
174+
level: 1
175+
unique2: test
176+
nestedObject3:
177+
type: object
178+
defaultValue:
179+
shared:
180+
value: 24
181+
flag: true
182+
level: 1
183+
unique3: test
184+
nestedObject4:
185+
type: object
186+
defaultValue:
187+
level: 1
188+
different:
189+
value: 100
190+
flag: false
191+
firstArray:
192+
type: array
193+
defaultValue:
194+
- ab
195+
- cd
196+
secondArray:
197+
type: array
198+
defaultValue:
199+
- cd
200+
- ef
201+
thirdArray:
202+
type: array
203+
defaultValue:
204+
- ef
205+
- gh
206+
fourthArray:
207+
type: array
208+
defaultValue:
209+
- gh
210+
- ef
211+
- ij
212+
fifthArray:
213+
type: array
214+
defaultValue:
215+
- cd
216+
- kl
217+
resources:
218+
- name: Echo
219+
type: Microsoft.DSC.Debug/Echo
220+
properties:
221+
output: "$expression"
222+
"@
223+
$out = dsc -l trace config get -i $config_yaml 2>$TestDrive/error.log | ConvertFrom-Json
224+
if ($isError) {
225+
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.log -Raw)
226+
(Get-Content $TestDrive/error.log -Raw) | Should -Match 'All arguments must either be arrays or objects'
227+
} else {
228+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw)
229+
($out.results[0].result.actualState.output | Out-String) | Should -BeExactly ($expected | Out-String)
230+
}
231+
}
232+
114233
It 'contain function works for: <expression>' -TestCases @(
115234
@{ expression = "[contains(parameters('array'), 'a')]" ; expected = $true }
116235
@{ expression = "[contains(parameters('array'), 2)]" ; expected = $false }

dsc_lib/locales/en-us.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,11 @@ parseStringError = "unable to parse string to int"
353353
castError = "unable to cast to int"
354354
parseNumError = "unable to parse number to int"
355355

356+
[functions.intersection]
357+
description = "Returns a single array or object with the common elements from the parameters"
358+
invoked = "intersection function"
359+
invalidArgType = "All arguments must either be arrays or objects"
360+
356361
[functions.indexOf]
357362
description = "Returns the index of the first occurrence of an item in an array"
358363
invoked = "indexOf function"

0 commit comments

Comments
 (0)