Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Assert-RequiredCommandParameter and Test-AccountRequirePassword #94

Merged
merged 7 commits into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,14 @@
"[markdown]": {
"files.trimTrailingWhitespace": true,
"files.encoding": "utf8"
}
},
"powershell.pester.useLegacyCodeLens": false,
"pester.testFilePath": [
"[tT]ests/[uU]nit/*.[tT]ests.[pP][sS]1",
"[tT]ests/[uU]nit/**/*.[tT]ests.[pP][sS]1"
],
"pester.runTestsInNewProcess": false,
"pester.pesterModulePath": "./output/RequiredModules/Pester",
"powershell.pester.codeLens": true,
"pester.suppressCodeLensNotice": true
}
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Added private function `Assert-RequiredCommandParameter` that throws an
exception if a specified parameter is not assigned a value, and optionally
throws only if a specific parameter is passed. - [Issue #92](https://github.com/dsccommunity/DscResource.Common/issues/92)
- Related to SqlServerDsc [Issue #1796](https://github.com/dsccommunity/SqlServerDsc/issues/1796).
- Added public function `Test-AccountRequirePassword` that returns true or
false whether an account need a password to be passed - [Issue #93](https://github.com/dsccommunity/DscResource.Common/issues/93)
- Related to SqlServerDsc [Issue #1794](https://github.com/dsccommunity/SqlServerDsc/issues/1794).

### Changed

- DscResource.Common
- Updated Visual Studio Code project settings to configure testing for Pester 5.
- `Assert-BoundParameter`
- Now has a new parameter set that calls `Assert-RequiredCommandParameter`
which will throw an exception if a specified parameter is not assigned
a value, and optionally throws only if a specific parameter is passed.

### Fixed

- Fixed unit tests for `Assert-ElevatedUser` and `Test-IsNumericType` so
the public function is tested correctly using the exported function.

## [0.13.1] - 2022-12-18

### Changed
Expand Down
76 changes: 71 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,29 @@ functions.

### `Assert-BoundParameter`

This command asserts passed parameters. It takes a hashtable, normally
`$PSBoundParameters`. There are two parameter sets for this command.

#### Mutually exclusive parameters are not set

Asserts that a specified set of parameters are not passed together with
another set of parameters.
There is no built in logic to validate against parameters sets for DSC
so this can be used instead to validate the parameters that were set in
the configuration.

>There is no built in logic to validate against parameters sets for DSC
>so this can be used instead to validate the parameters that were set in
>the configuration.

#### Required parameter is set

Assert that required parameters has been specified, and throws an exception if not.

#### Syntax

<!-- markdownlint-disable MD013 - Line length -->
```plaintext
Assert-BoundParameter [-BoundParameterList] <hashtable> [-MutuallyExclusiveList1] <string[]>
[-MutuallyExclusiveList2] <string[]> [<CommonParameters>]
Assert-BoundParameter -BoundParameterList <hashtable> -MutuallyExclusiveList1 <string[]> -MutuallyExclusiveList2 <string[]> [<CommonParameters>]

Assert-BoundParameter -BoundParameterList <hashtable> -RequiredParameter <string[]> [-IfParameterPresent <string[]>] [<CommonParameters>]
```
<!-- markdownlint-enable MD013 - Line length -->

Expand All @@ -75,6 +86,23 @@ Assert-BoundParameter @assertBoundParameterParameters
This example throws an exception if `$PSBoundParameters` contains both
the parameters `Parameter1` and `Parameter2`.

<!-- markdownlint-disable MD013 - Line length -->
```powershell
Assert-RequiredCommandParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('PBStartPortRange', 'PBEndPortRange')
```
<!-- markdownlint-enable MD013 - Line length -->

Throws an exception if either of the two parameters are not specified.

<!-- markdownlint-disable MD013 - Line length -->
```powershell
Assert-RequiredCommandParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('Property2', 'Property3') -IfParameterPresent @('Property1')
```
<!-- markdownlint-enable MD013 - Line length -->

Throws an exception if the parameter 'Property1' is specified and either
of the required parameters are not.

### `Assert-ElevatedUser`

Assert that the user has elevated the PowerShell session.
Expand Down Expand Up @@ -843,6 +871,44 @@ Set-PSModulePath -Path '<Path 1>;<Path 2>' -Machine
Sets the machine environment variable `PSModulePath` to the specified path
or paths (separated with semi-colons).

### `Test-AccountRequirePassword`

Returns whether the specified account require a password to be provided.
If the account is a (global) managed service account, virtual account, or a
built-in account then there is no need to provide a password.

#### Syntax

<!-- markdownlint-disable MD013 - Line length -->
```plaintext
Test-AccountRequirePassword [-Name] <string> [<CommonParameters>]
```
<!-- markdownlint-enable MD013 - Line length -->

#### Outputs

None.

#### Example

```powershell
Test-AccountRequirePassword -Name 'DOMAIN\MySqlUser'
```

Returns $true as a user account need a password.

```powershell
Test-AccountRequirePassword -Name 'DOMAIN\MyMSA$'
```

Returns $false as a manged service account does not need a password.

```powershell
Test-AccountRequirePassword -Name 'NT SERVICE\MSSQL$PAYROLL'
```

Returns $false as a virtual account does not need a password.

### `Test-DscParameterState`

This function is used to compare the values in the current state against
Expand Down
89 changes: 89 additions & 0 deletions source/Private/Assert-RequiredCommandParameter.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<#
.SYNOPSIS
Assert that required parameters has been specified.

.DESCRIPTION
Assert that required parameters has been specified, and throws an exception if not.

.PARAMETER BoundParameterList
A hashtable containing the parameters to evaluate. Normally this is set to
$PSBoundParameters.

.PARAMETER RequiredParameter
One or more parameter names that is required to have been specified.

.PARAMETER IfParameterPresent
One or more parameter names that if specified will trigger the evaluation.
If neither of the parameter names has been specified the evaluation of required
parameters are not made.

.EXAMPLE
Assert-RequiredCommandParameter -BoundParameter $PSBoundParameters -RequiredParameter @('PBStartPortRange', 'PBEndPortRange')

Throws an exception if either of the two parameters are not specified.

.EXAMPLE
Assert-RequiredCommandParameter -BoundParameter $PSBoundParameters -RequiredParameter @('Property2', 'Property3') -IfParameterPresent @('Property1')

Throws an exception if the parameter 'Property1' is specified and either of the required parameters are not.

.OUTPUTS
None.
#>
function Assert-RequiredCommandParameter
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.Collections.Hashtable]
$BoundParameterList,

[Parameter(Mandatory = $true)]
[System.String[]]
$RequiredParameter,

[Parameter()]
[System.String[]]
$IfParameterPresent
)

$evaluateRequiredParameter = $true

if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
{
$hasIfParameterPresent = $BoundParameterList.Keys.Where( { $_ -in $IfParameterPresent } )

if (-not $hasIfParameterPresent)
{
$evaluateRequiredParameter = $false
}
}

if ($evaluateRequiredParameter)
{
foreach ($parameter in $RequiredParameter)
{
if ($parameter -notin $BoundParameterList.Keys)
{
$errorMessage = if ($PSBoundParameters.ContainsKey('IfParameterPresent'))
{
$script:localizedData.RequiredCommandParameter_SpecificParametersMustAllBeSetWhenParameterExist -f ($RequiredParameter -join ''', '''), ($IfParameterPresent -join ''', ''')
}
else
{
$script:localizedData.RequiredCommandParameter_SpecificParametersMustAllBeSet -f ($RequiredParameter -join ''', ''')
}

$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
$errorMessage,
'ARCP0001', # cspell: disable-line
[System.Management.Automation.ErrorCategory]::InvalidOperation,
'Command parameters'
)
)
}
}
}
}
63 changes: 52 additions & 11 deletions source/Public/Assert-BoundParameter.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
An array of parameter names that are not allowed to be bound at the
same time as those in MutuallyExclusiveList1.

.PARAMETER RequiredParameter
One or more parameter names that is required to have been specified.

.PARAMETER IfParameterPresent
One or more parameter names that if specified will trigger the evaluation.
If neither of the parameter names has been specified the evaluation of required
parameters are not made.

.EXAMPLE
$assertBoundParameterParameters = @{
BoundParameterList = $PSBoundParameters
Expand All @@ -35,6 +43,16 @@

This example throws an exception if `$PSBoundParameters` contains both
the parameters `Parameter1` and `Parameter2`.

.EXAMPLE
Assert-BoundParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('PBStartPortRange', 'PBEndPortRange')

Throws an exception if either of the two parameters are not specified.

.EXAMPLE
Assert-BoundParameter -BoundParameterList $PSBoundParameters -RequiredParameter @('Property2', 'Property3') -IfParameterPresent @('Property1')

Throws an exception if the parameter 'Property1' is specified and either of the required parameters are not.
#>
function Assert-BoundParameter
{
Expand All @@ -46,24 +64,47 @@ function Assert-BoundParameter
[System.Collections.Hashtable]
$BoundParameterList,

[Parameter(Mandatory = $true)]
[Parameter(ParameterSetName = 'MutuallyExclusiveParameters', Mandatory = $true)]
[System.String[]]
$MutuallyExclusiveList1,

[Parameter(Mandatory = $true)]
[Parameter(ParameterSetName = 'MutuallyExclusiveParameters', Mandatory = $true)]
[System.String[]]
$MutuallyExclusiveList2
)
$MutuallyExclusiveList2,

$itemFoundFromList1 = $BoundParameterList.Keys.Where({ $_ -in $MutuallyExclusiveList1 })
$itemFoundFromList2 = $BoundParameterList.Keys.Where({ $_ -in $MutuallyExclusiveList2 })
[Parameter(ParameterSetName = 'RequiredParameter', Mandatory = $true)]
[System.String[]]
$RequiredParameter,

if ($itemFoundFromList1.Count -gt 0 -and $itemFoundFromList2.Count -gt 0)
[Parameter(ParameterSetName = 'RequiredParameter')]
[System.String[]]
$IfParameterPresent
)

switch ($PSCmdlet.ParameterSetName)
{
$errorMessage = `
$script:localizedData.ParameterUsageWrong `
-f ($MutuallyExclusiveList1 -join "','"), ($MutuallyExclusiveList2 -join "','")
'MutuallyExclusiveParameters'
{
$itemFoundFromList1 = $BoundParameterList.Keys.Where({ $_ -in $MutuallyExclusiveList1 })
$itemFoundFromList2 = $BoundParameterList.Keys.Where({ $_ -in $MutuallyExclusiveList2 })

if ($itemFoundFromList1.Count -gt 0 -and $itemFoundFromList2.Count -gt 0)
{
$errorMessage = `
$script:localizedData.ParameterUsageWrong `
-f ($MutuallyExclusiveList1 -join "','"), ($MutuallyExclusiveList2 -join "','")

New-InvalidArgumentException -ArgumentName 'Parameters' -Message $errorMessage
New-InvalidArgumentException -ArgumentName 'Parameters' -Message $errorMessage
}

break
}

'RequiredParameter'
{
Assert-RequiredCommandParameter @PSBoundParameters

break
}
}
}
Loading