Sub-selectors#
Abstract
This topic covers sub-selectors which are a PSRule language feature specific to YAML and JSON expressions. They are useful for filtering out objects that you do not want to evaluate. Sub-selectors don't apply to script expressions because PowerShell already has rich support for filtering.
Experimental
Sub-selectors are a work in progress and subject to change. We hope to add broader support, and more detailed documentation in the future. Join or start a discussion to let us know how we can improve this feature going forward.
Sub-selectors cover two (2) main scenarios:
- Pre-conditions — you want to filtering out objects before a rule is run.
- Object filtering — you want to limit a condition to specific elements in a list of items.
Pre-conditions#
PSRule can process many different types of objects. Rules however, are normally written to test a specific property or type of object. So it is important that rules only run on objects that you want to evaluate. Pre-condition sub-selectors are one way you can determine if a rule should be run.
To use a sub-selector as a pre-condition, use the where property, directly under the spec.
The expressions in the sub-selector follow the same form that you can use in rules.
For example:
In the example:
- The
whereproperty is the start of a sub-selector. - The sub-selector checks if the
kindproperty equalsapi.
The rule does not run if the:
- The object does not have a
kindproperty. OR - The value of the
kindproperty is notapi.
Tip
Other types of pre-conditions also exist that allow you to filter based on type or by a shared selector.
Object filter#
When you are evaluating an object, you can use sub-selectors to limit the condition. This is helpful when dealing with properties that are a list of items. Properties that contain a list of items may contain a sub-set of items that you want to evaluate.
For example, the object may look like this:
A rule to test if any sub-resources with the detailedErrorLoggingEnabled set to true exist might look like this:
---
# Synopsis: A rule with a sub-selector filter.
apiVersion: github.com/microsoft/PSRule/2025-01-01
kind: Rule
metadata:
name: Yaml.Subselector.Filter
spec:
condition:
field: resources
where:
type: '.'
equals: 'Microsoft.Web/sites/config'
allOf:
- field: properties.detailedErrorLoggingEnabled
equals: true
{
// Synopsis: A rule with a sub-selector filter.
"apiVersion": "github.com/microsoft/PSRule/2025-01-01",
"kind": "Rule",
"metadata": {
"name": "Json.Subselector.Filter"
},
"spec": {
"condition": {
"field": "resources",
"where": {
"type": ".",
"equals": "Microsoft.Web/sites/config"
},
"allOf": [
{
"field": "properties.detailedErrorLoggingEnabled",
"equals": true
}
]
}
}
}
In the example:
- If the array property
resourcesexists, any items with a type ofMicrosoft.Web/sites/configare evaluated.- Each item must have the
properties.detailedErrorLoggingEnabledproperty set totrueto pass. - Items without the
properties.detailedErrorLoggingEnabledproperty fail. - Items with the
properties.detailedErrorLoggingEnabledproperty set to a value other thentruefail.
- Each item must have the
- If the
resourcesproperty does not exist, the rule fails. - If the
resourcesproperty exists but has 0 items of typeMicrosoft.Web/sites/config, the rule fails. - If the
resourcesproperty exists and has any items of typeMicrosoft.Web/sites/configbut any fail, the rule fails. - If the
resourcesproperty exists and has any items of typeMicrosoft.Web/sites/configand all pass, the rule passes.
When there are no results#
Given the example, is important to understand what happens by default if:
- The
resourcesproperty doesn't exist. OR - The
resourcesproperty doesn't contain any items that match the sub-selector condition.
In either of these two cases, the sub-selector will return false and fail the rule.
The rule fails because there is no secondary conditions that could be used instead.
If this was not the desired behavior, you could:
- Use a pre-condition to avoid running the rule.
- Group the sub-selector into a
anyOf, and provide a secondary condition. - Use a quantifier to determine how many items must match sub-selector and match the
allOf/anyOfoperator.
For example:
---
# Synopsis: A rule with a sub-selector filter.
apiVersion: github.com/microsoft/PSRule/2025-01-01
kind: Rule
metadata:
name: Yaml.Subselector.FilterOr
spec:
condition:
anyOf:
- field: resources
where:
type: '.'
equals: 'Microsoft.Web/sites/config'
allOf:
- field: properties.detailedErrorLoggingEnabled
equals: true
- field: resources
exists: false
{
// Synopsis: A rule with a sub-selector filter.
"apiVersion": "github.com/microsoft/PSRule/2025-01-01",
"kind": "Rule",
"metadata": {
"name": "Json.Subselector.FilterOr"
},
"spec": {
"condition": {
"anyOf": [
{
"field": "resources",
"where": {
"type": ".",
"equals": "Microsoft.Web/sites/config"
},
"allOf": [
{
"field": "properties.detailedErrorLoggingEnabled",
"equals": true
}
]
},
{
"field": "resources",
"exists": false
}
]
}
}
}
In the example:
- If the array property
resourcesexists, any items with a type ofMicrosoft.Web/sites/configare evaluated.- Each item must have the
properties.detailedErrorLoggingEnabledproperty set totrueto pass. - Items without the
properties.detailedErrorLoggingEnabledproperty fail. - Items with the
properties.detailedErrorLoggingEnabledproperty set to a value other thentruefail.
- Each item must have the
- If the
resourcesproperty does not exist, the rule passes. - If the
resourcesproperty exists but has 0 items of typeMicrosoft.Web/sites/config, the rule fails. - If the
resourcesproperty exists and has any items of typeMicrosoft.Web/sites/configbut any fail, the rule fails. - If the
resourcesproperty exists and has any items of typeMicrosoft.Web/sites/configand all pass, the rule passes.
Using a quantifier with sub-selectors#
When iterating over a list of items, you may want to determine how many items must match. A quantifier determines how many items in the list match. Matching items must be:
- Selected by the sub-selector.
- Match the condition of the operator.
Supported quantifiers are:
count— The number of items must equal then the specified value.less— The number of items must less then the specified value.lessOrEqual— The number of items must less or equal to the specified value.greater— The number of items must greater then the specified value.greaterOrEqual— The number of items must greater or equal to the specified value.
For example:
---
# Synopsis: A rule with a sub-selector quantifier.
apiVersion: github.com/microsoft/PSRule/2025-01-01
kind: Rule
metadata:
name: Yaml.Subselector.Quantifier
spec:
condition:
field: resources
where:
type: '.'
equals: 'Microsoft.Web/sites/config'
greaterOrEqual: 1
allOf:
- field: properties.detailedErrorLoggingEnabled
equals: true
{
// Synopsis: A rule with a sub-selector quantifier.
"apiVersion": "github.com/microsoft/PSRule/2025-01-01",
"kind": "Rule",
"metadata": {
"name": "Json.Subselector.Quantifier"
},
"spec": {
"condition": {
"field": "resources",
"where": {
"type": ".",
"equals": "Microsoft.Web/sites/config"
},
"greaterOrEqual": 1,
"allOf": [
{
"field": "properties.detailedErrorLoggingEnabled",
"equals": true
}
]
}
}
}
In the example:
- If the array property
resourcesexists, any items with a type ofMicrosoft.Web/sites/configare evaluated.- Each item must have the
properties.detailedErrorLoggingEnabledproperty set totrueto pass. - The number of items that pass must be greater or equal to
1.
- Each item must have the
- If the
resourcesproperty does not exist or is empty, the number of items is0which fails greater or equal to1.