Skip to content

Commit

Permalink
Improve field support and add type binding #82 #86 #87 (#88)
Browse files Browse the repository at this point in the history
- Added object type binding and dynamic filtering for rules #82
- Added support for indexed and quoted field names #86
- Added support for case-sensitive binding operations #87
  • Loading branch information
BernieWhite authored Feb 19, 2019
1 parent 5eb05ab commit 2c7c293
Show file tree
Hide file tree
Showing 39 changed files with 1,037 additions and 269 deletions.
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
## Unreleased

- Export variables to improve authoring experience [#83](https://github.com/BernieWhite/PSRule/issues/83)
- Support for packaging rules in modules [#16](https://github.com/BernieWhite/PSRule/issues/16)
- **Breaking change** - Removed `-TargetName` parameter of the `Hint` keyword [#81](https://github.com/BernieWhite/PSRule/issues/81)
- Added support for packaging rules in modules [#16](https://github.com/BernieWhite/PSRule/issues/16)
- Added support for indexed and quoted field names [#86](https://github.com/BernieWhite/PSRule/issues/86)
- Added object type binding and dynamic filtering for rules [#82](https://github.com/BernieWhite/PSRule/issues/82)
- Added support for case-sensitive binding operations [#87](https://github.com/BernieWhite/PSRule/issues/87)
- Binding is ignores case by default. Set option `Binding.CaseSensitive` to `true` to enable case-sensitivity.
- **Breaking change** - The `-TargetName` parameter of the `Hint` keyword has been deprecated [#81](https://github.com/BernieWhite/PSRule/issues/81)
- `-TargetName` parameter not longer sets the pipeline object _TargetName_ and generates a warning instead.
- The `-TargetName` will be completely removed in **v0.4.0**, at which time using the parameter will generate an error.

## v0.3.0-B190208 (pre-release)

Expand All @@ -27,7 +33,7 @@ What's changed since v0.1.0:
- Objects that are unable to bind a _TargetName_ will use a SHA1 object hash for _TargetName_ [#44](https://github.com/BernieWhite/PSRule/issues/44)
- Added `Test-PSRuleTarget` command to return an overall `$True` or `$False` after evaluating rules for an object [#30](https://github.com/BernieWhite/PSRule/issues/30)
- Improve reporting of inconclusive results and objects that are not processed by any rule [#46](https://github.com/BernieWhite/PSRule/issues/46)
- Inconclusive results and objects not processed will return a warning
- Inconclusive results and objects not processed will return a warning by default.
- Fix propagation of informational messages to host from rule scripts and definitions [#48](https://github.com/BernieWhite/PSRule/issues/48)
- Fix Get-PSRule generates exception when no .rule.ps1 scripts exist in path [#53](https://github.com/BernieWhite/PSRule/issues/53)
- Fix LocalizedData.PathNotFound warning when no .rule.ps1 scripts exist in path [#54](https://github.com/BernieWhite/PSRule/issues/54)
Expand Down Expand Up @@ -56,7 +62,7 @@ What's changed since pre-release v0.2.0-B190121
- Objects that are unable to bind a _TargetName_ will use a SHA1 object hash for _TargetName_ [#44](https://github.com/BernieWhite/PSRule/issues/44)
- Added `Test-PSRule` command to return an overall `$True` or `$False` after evaluating rules for an object [#30](https://github.com/BernieWhite/PSRule/issues/30)
- Improve reporting of inconclusive results and objects that are not processed by any rule [#46](https://github.com/BernieWhite/PSRule/issues/46)
- Inconclusive results and objects not processed will return a warning
- Inconclusive results and objects not processed will return a warning by default.
- Fix propagation of informational messages to host from rule scripts and definitions [#48](https://github.com/BernieWhite/PSRule/issues/48)
- Added support for cross-platform environments (Windows, Linux and macOS) [#49](https://github.com/BernieWhite/PSRule/issues/49)

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ The following conceptual topics exist in the `PSRule` module:
- [Baseline.RuleName](docs/concepts/PSRule/en-US/about_PSRule_Options.md#baselinerulename)
- [Baseline.Exclude](docs/concepts/PSRule/en-US/about_PSRule_Options.md#baselineexclude)
- [Baseline.Configuration](docs/concepts/PSRule/en-US/about_PSRule_Options.md#baselineconfiguration)
- [Binding.TargetName](docs/concepts/PSRule/en-US/about_PSRule_Options.md#targetname-binding)
- [Binding.IgnoreCase](docs/concepts/PSRule/en-US/about_PSRule_Options.md#bindingignorecase)
- [Binding.TargetName](docs/concepts/PSRule/en-US/about_PSRule_Options.md#bindingtargetname)
- [Binding.TargetType](docs/concepts/PSRule/en-US/about_PSRule_Options.md#bindingtargettype)
- [Execution.LanguageMode](docs/concepts/PSRule/en-US/about_PSRule_Options.md#executionlanguagemode)
- [Execution.InconclusiveWarning](docs/concepts/PSRule/en-US/about_PSRule_Options.md#inconclusive-warning)
- [Execution.NotProcessedWarning](docs/concepts/PSRule/en-US/about_PSRule_Options.md#not-processed-warning)
Expand Down
22 changes: 20 additions & 2 deletions docs/commands/PSRule/en-US/New-PSRuleOption.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Create options to configure PSRule execution.

```text
New-PSRuleOption [[-Option] <PSRuleOption>] [-BaselineConfiguration <BaselineConfiguration>]
[-SuppressTargetName <SuppressionOption>] [-BindTargetName <BindTargetName[]>] [[-Path] <String>]
[<CommonParameters>]
[-SuppressTargetName <SuppressionOption>] [-BindTargetName <BindTargetName[]>]
[-BindTargetType <BindTargetName[]>] [[-Path] <String>] [<CommonParameters>]
```

## DESCRIPTION
Expand Down Expand Up @@ -162,6 +162,24 @@ Accept pipeline input: False
Accept wildcard characters: False
```
### -BindTargetType
Configures a custom function to use to bind TargetType of an object.
For more information on PSRule options see about_PSRule_Options.
```yaml
Type: BindTargetName[]
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
Expand Down
97 changes: 91 additions & 6 deletions docs/concepts/PSRule/en-US/about_PSRule_Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ The following options are available for use:
- [Baseline.RuleName](#baselinerulename)
- [Baseline.Exclude](#baselineexclude)
- [Baseline.Configuration](#baselineconfiguration)
- [Binding.TargetName](#targetname-binding)
- [Binding.IgnoreCase](#bindingignorecase)
- [Binding.TargetName](#bindingtargetname)
- [Binding.TargetType](#bindingtargettype)
- [Execution.LanguageMode](#executionlanguagemode)
- [Execution.InconclusiveWarning](#inconclusive-warning)
- [Execution.NotProcessedWarning](#not-processed-warning)
Expand Down Expand Up @@ -118,20 +120,43 @@ baseline:
appServiceMinInstanceCount: 2
```

### TargetName binding
### Binding.IgnoreCase

When evaluating an object, PSRule extracts a few key properties from the object to help filter rules and display output results. The process of extract these key properties is called _binding_. The properties that PSRule uses for binding can be customized by providing a order list of alternative properties to use. See [`Binding.TargetName`](#bindingtargetname) and [`Binding.TargetType`](#bindingtargettype) for these options.

- By default, custom property binding finds the first matching property by name regardless of case. i.e. `Binding.IgnoreCase` is `true`
- To change the default, set the `Binding.IgnoreCase` option to `false` and a case sensitive match will be used.
- Changing this option will affect all custom property bindings, including _TargetName_ and _TargetType_.
- PSRule also has binding defaults, and an option to use a custom script. Setting this option has no affect on binding defaults or custom scripts.

This option can be specified using:

```powershell
# PowerShell: Using the Binding.IgnoreCase hashtable key
$option = New-PSRuleOption -Option @{ 'Binding.IgnoreCase' = $False };
```

```yaml
# YAML: Using the binding/ignoreCase property
binding:
ignoreCase: false
```

### Binding.TargetName

When an object is passed from the pipeline, PSRule assigns the object a _TargetName_. _TargetName_ is used in output results to identify one object from another. Many objects could be passed down the pipeline at the same time, so using a _TargetName_ that is meaningful is important. _TargetName_ is also used for advanced features such as rule suppression.

The value that PSRule uses for _TargetName_ is configurable. PSRule uses the following logic to determine what _TargetName_ should be used:

- By default PSRule will:
- Use `TargetName` or `Name` properties on the object.
- Use `TargetName` or `Name` properties on the object. These property names are case insensitive.
- If both `TargetName` and `Name` properties exist, `TargetName` will take precedence over `Name`.
- If neither `TargetName` or `Name` properties exist, a SHA1 hash of the object will be used as _TargetName_.
- If custom _TargetName_ binding properties are configured, the property names specified will override the defaults.
- If **none** of the configured property names exist, PSRule will revert back to `TargetName` then `Name`.
- If more then one property name is configured, the order they are specified in the configuration determines precedence.
- i.e. The first configured property name will take precedence over the second property name.
- By default the property name will be matched ignoring case sensitivity. To use a case sensitive match, configure the [`Binding.IgnoreCase`](#bindingignorecase) option.
- If a custom _TargetName_ binding function is specified, the function will be evaluated first before any other option.
- If the function returns `$Null` then custom properties, `TargetName` and `Name` properties will be used.
- The custom binding function is executed outside the PSRule engine, so PSRule keywords and variables will not be available.
Expand Down Expand Up @@ -172,6 +197,59 @@ $bindFn = {
$option = New-PSRuleOption -BindTargetName $bindFn;
```

### Binding.TargetType

When an object is passed from the pipeline, PSRule assigns the object a _TargetType_. _TargetType_ is used to filter rules based on object type and appears in output results.

The value that PSRule uses for _TargetType_ is configurable. PSRule uses the following logic to determine what _TargetType_ should be used:

- By default PSRule will:
- Use the default type presented by PowerShell from `TypeNames`. i.e. `.PSObject.TypeNames[0]`
- If custom _TargetType_ binding properties are configured, the property names specified will override the defaults.
- If **none** of the configured property names exist, PSRule will revert back to the type presented by PowerShell.
- If more then one property name is configured, the order they are specified in the configuration determines precedence.
- i.e. The first configured property name will take precedence over the second property name.
- By default the property name will be matched ignoring case sensitivity. To use a case sensitive match, configure the [`Binding.IgnoreCase`](#bindingignorecase) option.
- If a custom _TargetType_ binding function is specified, the function will be evaluated first before any other option.
- If the function returns `$Null` then custom properties, or the type presented by PowerShell will be used in order instead.
- The custom binding function is executed outside the PSRule engine, so PSRule keywords and variables will not be available.
- Custom binding functions are blocked in constrained language mode is used. See [language mode](#language-mode) for more information.

Custom property names to use for binding can be specified using:

```powershell
# PowerShell: Using the Binding.TargetType hashtable key
$option = New-PSRuleOption -Option @{ 'Binding.TargetType' = 'ResourceType', 'kind' };
```

```yaml
# YAML: Using the binding/targetType property
binding:
targetType:
- ResourceType
- kind
```

To specify a custom binding function use:

```powershell
# Create a custom function that returns a TargetType string
$bindFn = {
param ($TargetObject)
$otherType = $TargetObject.PSObject.Properties['OtherType'];
if ($otherType -eq $Null) {
return $Null
}
return $otherType.Value;
}
# Specify the binding function script block code to execute
$option = New-PSRuleOption -BindTargetType $bindFn;
```

### Execution.LanguageMode

Unless PowerShell has been constrained, full language features of PowerShell are available to use within rule definitions. In locked down environments, a reduced set of language features may be desired.
Expand Down Expand Up @@ -250,7 +328,7 @@ execution:

### Input.Format

Configures the input format for when a string is passed in as a target object. By default, strings are just treated as raw text. However when set strings can be read as YAML or JSON and converted to an object.
Configures the input format for when a string is passed in as a target object. By default, strings are just treated as raw text. However, when set strings can be read as YAML or JSON and converted to an object.

When using `Invoke-PSRule` and `Test-PSRuleTarget` the `-Format` parameter will override any value set in configuration.

Expand All @@ -277,7 +355,7 @@ input:

The object path to a property to use instead of the pipeline object.

By default, PSRule processes objects passed from the pipeline against selected rules. When this option is set, instead of evaluating the pipeline object, PSRule looks for a property of the pipeline object specified by `ObjectPath` and uses that instead. If the property specified by `ObjectPath` is a collection/ array then each item is evaluated separately.
By default, PSRule processes objects passed from the pipeline against selected rules. When this option is set, instead of evaluating the pipeline object, PSRule looks for a property of the pipeline object specified by `ObjectPath` and uses that instead. If the property specified by `ObjectPath` is a collection/ array, then each item is evaluated separately.

If the property specified by `ObjectPath` does not exist, PSRule skips the object.

Expand All @@ -300,7 +378,7 @@ input:

In certain circumstances it may be necessary to exclude or suppress rules from processing objects that are in a known failed state.

PSRule allows objects to be suppressed for a rule by TargetName. Objects that are suppressed are not processed by the rule at all, but will continue to be processed by other rules.
PSRule allows objects to be suppressed for a rule by TargetName. Objects that are suppressed are not processed by the rule at all but will continue to be processed by other rules.

Rule suppression complements pre-filtering and pre-conditions.

Expand Down Expand Up @@ -376,9 +454,13 @@ baseline:
# Configure TargetName binding
binding:
ignoreCase: false
targetName:
- ResourceName
- AlternateName
targetType:
- ResourceType
- kind
# Configure execution options
execution:
Expand Down Expand Up @@ -416,9 +498,12 @@ baseline:
# Configure TargetName binding
binding:
ignoreCase: true
targetName:
- TargetName
- Name
targetType:
- PSObject.TypeNames[0]
# Configure execution options
execution:
Expand Down
3 changes: 2 additions & 1 deletion docs/concepts/PSRule/en-US/about_PSRule_Variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ The following section properties are available for public read access:
- `RuleName` - The name of the rule.
- `RuleId` - A unique identifier for the rule.
- `TargetObject` - The object currently being processed on the pipeline.
- `TargetName` - The name of the object currently being processed on the pipeline. This property will automatically bind to `TargetName` or `Name` properties of the object if they exist.
- `TargetName` - The name of the object currently being processed on the pipeline. This property will automatically default to `TargetName` or `Name` properties of the object if they exist.
- `TargetType` - The type of the object currently being processed on the pipeline. This property will automatically bind to `PSObject.TypeNames[0]` by default.

Syntax:

Expand Down
12 changes: 12 additions & 0 deletions schemas/PSRule-options-0.3.0.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,24 @@
"type": "object",
"description": "Configure property/ object binding options.",
"properties": {
"ignoreCase": {
"type": "boolean",
"description": "Determines if custom binding uses ignores case when matching properties.",
"default": true
},
"targetName": {
"type": "array",
"description": "Specifies one or more property names to bind TargetName to.",
"items": {
"type": "string"
}
},
"targetType": {
"type": "array",
"description": "Specifies one or more property names to bind TargetType to.",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
Expand Down
8 changes: 6 additions & 2 deletions src/PSRule.Benchmark/Benchmark.Rule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

# Description: A rule for testing PSRule performance
Rule 'Benchmark' {
1 -eq 1;
1 -eq 1;
}

# Description: A rule for testing PSRule performance
Rule 'BenchmarkIf' -If { 1 -eq 1 } {
1 -eq 1;
1 -eq 1;
}

Rule 'BenchmarkType' -Type 'PSRule.Benchmark.TargetObject' {
1 -eq 1;
}

# Description: A rule for testing PSRule performance
Expand Down
Loading

0 comments on commit 2c7c293

Please sign in to comment.