Skip to content

Commit

Permalink
Added sub-selector quantifiers #1423 (#1525)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored May 7, 2023
1 parent 75b5898 commit 4b38a9c
Show file tree
Hide file tree
Showing 13 changed files with 734 additions and 222 deletions.
10 changes: 3 additions & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,14 @@
"/ps-rule.yaml"
],
"./schemas/PSRule-language.schema.json": [
"/tests/PSRule.Tests/**.Rule.yaml",
"/tests/PSRule.Tests/**/**.Rule.yaml",
"/docs/scenarios/*/*.Rule.yaml",
"/docs/expressions/**/*.Rule.yaml"
"/**/**.Rule.yaml",
"/**/docs/scenarios/baselines/Baseline.rule.yaml"
]
},
"json.schemas": [
{
"fileMatch": [
"/tests/PSRule.Tests/**.Rule.jsonc",
"/tests/PSRule.Tests/**/**.Rule.jsonc",
"/docs/expressions/**/*.Rule.jsonc"
"/**/**.Rule.jsonc"
],
"url": "./schemas/PSRule-resources.schema.json"
}
Expand Down
8 changes: 8 additions & 0 deletions docs/CHANGELOG-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

## Unreleased

What's changed since pre-release v2.9.0-B0013:

- New features:
- Added sub-selector quantifiers for `allOf` or `anyOf` operators by @BernieWhite.
[#1423](https://github.com/microsoft/PSRule/issues/1423)
- Quantifiers allow you to specify the number of matches with `count`, `less`, `lessOrEqual`, `greater`, or `greaterOrEqual`.
- See [Sub-selectors][4] for more information.

## v2.9.0-B0013 (pre-release)

What's changed since release v2.8.1:
Expand Down
8 changes: 8 additions & 0 deletions docs/concepts/PSRule/en-US/about_PSRule_Expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ The `allOf` operator is used to require all nested expressions to match.
When any nested expression does not match, `allOf` does not match.
This is similar to a logical _and_ operation.

Additionally sub-selectors can be used to modify the `allOf` operator.
Sub-selectors allow filtering and looping through arrays of objects before the `allOf` operator is applied.
See sub-selectors for more information.

Syntax:

```yaml
Expand Down Expand Up @@ -121,6 +125,10 @@ The `anyOf` operator is used to require one or more nested expressions to match.
When any nested expression matches, `allOf` matches.
This is similar to a logical _or_ operation.

Additionally sub-selectors can be used to modify the `anyOf` operator.
Sub-selectors allow filtering and looping through arrays of objects before the `anyOf` operator is applied.
See sub-selectors for more information.

Syntax:

```yaml
Expand Down
6 changes: 6 additions & 0 deletions docs/expressions/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,9 @@ spec:
- string: '-'
- path: name
```
## Recommended content
- [Create a standalone rule](../quickstart/standalone-rule.md)
- [Expressions](../concepts/PSRule/en-US/about_PSRule_Expressions.md)
- [Sub-selectors](sub-selectors.md)
85 changes: 84 additions & 1 deletion docs/expressions/sub-selectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ In the example:

### When there are no results

Given the example, is important to understand what happens if:
Given the example, is important to understand what happens by default if:

- The `resources` property doesn't exist. **OR**
- The `resources` property doesn't contain any items that match the sub-selector condition.
Expand All @@ -196,6 +196,7 @@ 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` / `anyOf` operator.

For example:

Expand Down Expand Up @@ -270,3 +271,85 @@ In the example:
- If the `resources` property exists but has 0 items of type `Microsoft.Web/sites/config`, the rule fails.
- If the `resources` property exists and has any items of type `Microsoft.Web/sites/config` but any fail, the rule fails.
- If the `resources` property exists and has any items of type `Microsoft.Web/sites/config` and 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:

=== "YAML"

```yaml hl_lines="13"
---
# Synopsis: A rule with a sub-selector quantifier.
apiVersion: github.com/microsoft/PSRule/v1
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
```

=== "JSON"

```json hl_lines="15"
{
// Synopsis: A rule with a sub-selector quantifier.
"apiVersion": "github.com/microsoft/PSRule/v1",
"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 `resources` exists, any items with a type of `Microsoft.Web/sites/config` are evaluated.
- Each item must have the `properties.detailedErrorLoggingEnabled` property set to `true` to pass.
- The number of items that pass must be greater or equal to `1`.
- If the `resources` property does not exist or is empty, the number of items is `0` which fails greater or equal to `1`.

## Recommended content

- [Create a standalone rule](../quickstart/standalone-rule.md)
- [Functions](functions.md)
- [Expressions](../concepts/PSRule/en-US/about_PSRule_Expressions.md)
Loading

0 comments on commit 4b38a9c

Please sign in to comment.