mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
win_dsc - Add argument validation and other fixes (#53093)
* win_dsc - Add argument validation and other fixes * Fix doc issues
This commit is contained in:
parent
853a65eead
commit
6b294eab4d
27 changed files with 1585 additions and 990 deletions
4
changelogs/fragments/win_dsc-validation.yaml
Normal file
4
changelogs/fragments/win_dsc-validation.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
minor_changes:
|
||||||
|
- win_dsc - The win_dsc module will now fail if an invalid DSC property is set.
|
||||||
|
- win_dsc - The module invocation and possible options will be displayed when running with ``-vvv``.
|
||||||
|
- win_dsc - The Verbose logs will be returned when running with ``-vvv``.
|
|
@ -208,6 +208,8 @@ PowerShell module options and option choices are currently case insensitive to w
|
||||||
specification. This behaviour is deprecated and a warning displayed to the user if a case insensitive match was found.
|
specification. This behaviour is deprecated and a warning displayed to the user if a case insensitive match was found.
|
||||||
A future release of Ansible will make these checks case sensitive.
|
A future release of Ansible will make these checks case sensitive.
|
||||||
|
|
||||||
|
The ``win_dsc`` module will now validate the input options for a DSC resource. In previous versions invalid options would be ignored but are now not.
|
||||||
|
|
||||||
Modules removed
|
Modules removed
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,67 @@ This is what the Ansible task version of the above DSC Registry resource would l
|
||||||
ValueName: TestValue
|
ValueName: TestValue
|
||||||
ValueData: TestData
|
ValueData: TestData
|
||||||
|
|
||||||
|
Starting in Ansible 2.8, the ``win_dsc`` module automatically validates the
|
||||||
|
input options from Ansible with the DSC definition. This means Ansible will
|
||||||
|
fail if the option name is incorrect, a mandatory option is not set, or the
|
||||||
|
value is not a valid choice. When running Ansible with a verbosity level of 3
|
||||||
|
or more (``-vvv``), the return value will contain the possible invocation
|
||||||
|
options based on the ``resource_name`` specified. Here is an example of the
|
||||||
|
invocation output for the above ``Registry`` task::
|
||||||
|
|
||||||
|
changed: [2016] => {
|
||||||
|
"changed": true,
|
||||||
|
"invocation": {
|
||||||
|
"module_args": {
|
||||||
|
"DependsOn": null,
|
||||||
|
"Ensure": "Present",
|
||||||
|
"Force": null,
|
||||||
|
"Hex": null,
|
||||||
|
"Key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\ExampleKey",
|
||||||
|
"PsDscRunAsCredential_password": null,
|
||||||
|
"PsDscRunAsCredential_username": null,
|
||||||
|
"ValueData": [
|
||||||
|
"TestData"
|
||||||
|
],
|
||||||
|
"ValueName": "TestValue",
|
||||||
|
"ValueType": null,
|
||||||
|
"module_version": "latest",
|
||||||
|
"resource_name": "Registry"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module_version": "1.1",
|
||||||
|
"reboot_required": false,
|
||||||
|
"verbose_set": [
|
||||||
|
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceSet,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
|
||||||
|
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
|
||||||
|
"[SERVER2016]: LCM: [ Start Set ] [[Registry]DirectResourceAccess]",
|
||||||
|
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Create registry key 'HKLM:\\SOFTWARE\\ExampleKey'",
|
||||||
|
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Set registry key value 'HKLM:\\SOFTWARE\\ExampleKey\\TestValue' to 'TestData' of type 'String'",
|
||||||
|
"[SERVER2016]: LCM: [ End Set ] [[Registry]DirectResourceAccess] in 0.1930 seconds.",
|
||||||
|
"[SERVER2016]: LCM: [ End Set ] in 0.2720 seconds.",
|
||||||
|
"Operation 'Invoke CimMethod' complete.",
|
||||||
|
"Time taken for configuration job to complete is 0.402 seconds"
|
||||||
|
],
|
||||||
|
"verbose_test": [
|
||||||
|
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceTest,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
|
||||||
|
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
|
||||||
|
"[SERVER2016]: LCM: [ Start Test ] [[Registry]DirectResourceAccess]",
|
||||||
|
"[SERVER2016]: [[Registry]DirectResourceAccess] Registry key 'HKLM:\\SOFTWARE\\ExampleKey' does not exist",
|
||||||
|
"[SERVER2016]: LCM: [ End Test ] [[Registry]DirectResourceAccess] False in 0.2510 seconds.",
|
||||||
|
"[SERVER2016]: LCM: [ End Set ] in 0.3310 seconds.",
|
||||||
|
"Operation 'Invoke CimMethod' complete.",
|
||||||
|
"Time taken for configuration job to complete is 0.475 seconds"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``invocation.module_args`` key shows the actual values that were set as
|
||||||
|
well as other possible values that were not set. Unfortunately this will not
|
||||||
|
show the default value for a DSC property, only what was set from the Ansible
|
||||||
|
task. Any ``*_password`` option will be masked in the output for security
|
||||||
|
reasons, if there are any other sensitive module options, set ``no_log: True``
|
||||||
|
on the task to stop all task output from being logged.
|
||||||
|
|
||||||
|
|
||||||
Property Types
|
Property Types
|
||||||
--------------
|
--------------
|
||||||
Each DSC resource property has a type that is associated with it. Ansible
|
Each DSC resource property has a type that is associated with it. Ansible
|
||||||
|
@ -123,9 +184,12 @@ For example:
|
||||||
SourceCredential_username: AdminUser
|
SourceCredential_username: AdminUser
|
||||||
SourceCredential_password: PasswordForAdminUser
|
SourceCredential_password: PasswordForAdminUser
|
||||||
|
|
||||||
.. Note:: You should set ``no_log: yes`` on the task definition in
|
.. Note:: On versions of Ansible older than 2.8, you should set ``no_log: yes``
|
||||||
Ansible to ensure any credentials used are not stored in any log file or
|
on the task definition in Ansible to ensure any credentials used are not
|
||||||
console output.
|
stored in any log file or console output.
|
||||||
|
|
||||||
|
A ``[PSCredential]`` is defined with ``EmbeddedInstance("MSFT_Credential")`` in
|
||||||
|
a DSC resource MOF definition.
|
||||||
|
|
||||||
CimInstance Type
|
CimInstance Type
|
||||||
++++++++++++++++
|
++++++++++++++++
|
||||||
|
@ -144,13 +208,20 @@ For example, to define a ``[CimInstance]`` value in Ansible:
|
||||||
Windows: yes
|
Windows: yes
|
||||||
|
|
||||||
In the above example, the CIM instance is a representation of the class
|
In the above example, the CIM instance is a representation of the class
|
||||||
``MSFT_xWebAuthenticationInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof>``_.
|
`MSFT_xWebAuthenticationInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof>`_.
|
||||||
This class accepts four boolean variables, ``Anonymous``, ``Basic``,
|
This class accepts four boolean variables, ``Anonymous``, ``Basic``,
|
||||||
``Digest``, and ``Windows``. The keys to use in a ``[CimInstance]`` depend on
|
``Digest``, and ``Windows``. The keys to use in a ``[CimInstance]`` depend on
|
||||||
the class it represents. Please read through the documentation of the resource
|
the class it represents. Please read through the documentation of the resource
|
||||||
to determine the keys that can be used and the types of each key value. The
|
to determine the keys that can be used and the types of each key value. The
|
||||||
class definition is typically located in the ``<resource name>.schema.mof``.
|
class definition is typically located in the ``<resource name>.schema.mof``.
|
||||||
|
|
||||||
|
HashTable Type
|
||||||
|
++++++++++++++
|
||||||
|
A ``[HashTable]`` object is also a dictionary but does not have a strict set of
|
||||||
|
keys that can/need to be defined. Like a ``[CimInstance]``, define it like a
|
||||||
|
normal dictionary value in YAML. A ``[HashTable]]`` is defined with
|
||||||
|
``EmbeddedInstance("MSFT_KeyValuePair")`` in a DSC resource MOF definition.
|
||||||
|
|
||||||
Arrays
|
Arrays
|
||||||
++++++
|
++++++
|
||||||
Simple type arrays like ``[string[]]`` or ``[UInt32[]]`` are defined as a list
|
Simple type arrays like ``[string[]]`` or ``[UInt32[]]`` are defined as a list
|
||||||
|
@ -192,17 +263,39 @@ like this example:
|
||||||
Port: 80
|
Port: 80
|
||||||
IPAddress: '*'
|
IPAddress: '*'
|
||||||
|
|
||||||
The above example, is an array with two values of the class ``MSFT_xWebBindingInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof>``_.
|
The above example, is an array with two values of the class `MSFT_xWebBindingInformation <https://github.com/PowerShell/xWebAdministration/blob/dev/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof>`_.
|
||||||
When defining a ``[CimInstance[]]``, be sure to read the resource documentation
|
When defining a ``[CimInstance[]]``, be sure to read the resource documentation
|
||||||
to find out what keys to use in the definition.
|
to find out what keys to use in the definition.
|
||||||
|
|
||||||
|
DateTime
|
||||||
|
++++++++
|
||||||
|
A ``[DateTime]`` object is a DateTime string representing the date and time in
|
||||||
|
the `ISO 8601 <https://www.w3.org/TR/NOTE-datetime>`_ date time format. The
|
||||||
|
value for a ``[DateTime]`` field should be quoted in YAML to ensure the string
|
||||||
|
is properly serialized to the Windows host. Here is an example of how to define
|
||||||
|
a ``[DateTime]`` value in Ansible:
|
||||||
|
|
||||||
|
.. code-block:: yaml+jinja
|
||||||
|
|
||||||
|
# As UTC-0 (No timezone)
|
||||||
|
DateTime: '2019-02-22T13:57:31.2311892+00:00'
|
||||||
|
|
||||||
|
# As UTC+4
|
||||||
|
DateTime: '2019-02-22T17:57:31.2311892+04:00'
|
||||||
|
|
||||||
|
# As UTC-4
|
||||||
|
DateTime: '2019-02-22T09:57:31.2311892-04:00'
|
||||||
|
|
||||||
|
All the values above are equal to a UTC date time of February 22nd 2019 at
|
||||||
|
1:57pm with 31 seconds and 2311892 milliseconds.
|
||||||
|
|
||||||
Run As Another User
|
Run As Another User
|
||||||
-------------------
|
-------------------
|
||||||
By default, DSC runs each resource as the SYSTEM account and not the account
|
By default, DSC runs each resource as the SYSTEM account and not the account
|
||||||
that Ansible use to run the module. This means that resources that are dynamically
|
that Ansible use to run the module. This means that resources that are dynamically
|
||||||
loaded based on a user profile, like the ``HKEY_CURRENT_USER`` registry hive,
|
loaded based on a user profile, like the ``HKEY_CURRENT_USER`` registry hive,
|
||||||
will be loaded under the ``SYSTEM`` profile. The parameter
|
will be loaded under the ``SYSTEM`` profile. The parameter
|
||||||
`PsDscRunAsCredential`` is a parameter that can be set for every DSC resource
|
``PsDscRunAsCredential`` is a parameter that can be set for every DSC resource
|
||||||
force the DSC engine to run under a different account. As
|
force the DSC engine to run under a different account. As
|
||||||
``PsDscRunAsCredential`` has a type of ``PSCredential``, it is defined with the
|
``PsDscRunAsCredential`` has a type of ``PSCredential``, it is defined with the
|
||||||
``_username`` and ``_password`` suffix.
|
``_username`` and ``_password`` suffix.
|
||||||
|
|
|
@ -4,272 +4,400 @@
|
||||||
# Copyright: (c) 2017, Ansible Project
|
# Copyright: (c) 2017, Ansible Project
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
#Requires -Module Ansible.ModuleUtils.Legacy
|
#AnsibleRequires -CSharpUtil Ansible.Basic
|
||||||
#Requires -Version 5
|
#Requires -Version 5
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
Function ConvertTo-ArgSpecType {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Converts the DSC parameter type to the arg spec type required for Ansible.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$CimType
|
||||||
|
)
|
||||||
|
|
||||||
$params = Parse-Args $args -supports_check_mode $true
|
$arg_type = switch($CimType) {
|
||||||
$result = @{
|
Boolean { "bool" }
|
||||||
changed = $false
|
Char16 { [Func[[Object], [Char]]]{ [System.Char]::Parse($args[0].ToString()) } }
|
||||||
|
DateTime { [Func[[Object], [DateTime]]]{
|
||||||
|
# o == ISO 8601 format
|
||||||
|
[System.DateTime]::ParseExact($args[0].ToString(), "o", [CultureInfo]::InvariantCulture,
|
||||||
|
[System.Globalization.DateTimeStyles]::None)
|
||||||
|
}}
|
||||||
|
Instance { "dict" }
|
||||||
|
Real32 { "float" }
|
||||||
|
Real64 { [Func[[Object], [Double]]]{ [System.Double]::Parse($args[0].ToString()) } }
|
||||||
|
Reference { "dict" }
|
||||||
|
SInt16 { [Func[[Object], [Int16]]]{ [System.Int16]::Parse($args[0].ToString()) } }
|
||||||
|
SInt32 { "int" }
|
||||||
|
SInt64 { [Func[[Object], [Int64]]]{ [System.Int64]::Parse($args[0].ToString()) } }
|
||||||
|
SInt8 { [Func[[Object], [SByte]]]{ [System.SByte]::Parse($args[0].ToString()) } }
|
||||||
|
String { "str" }
|
||||||
|
UInt16 { [Func[[Object], [UInt16]]]{ [System.UInt16]::Parse($args[0].ToString()) } }
|
||||||
|
UInt32 { [Func[[Object], [UInt32]]]{ [System.UInt32]::Parse($args[0].ToString()) } }
|
||||||
|
UInt64 { [Func[[Object], [UInt64]]]{ [System.UInt64]::Parse($args[0].ToString()) } }
|
||||||
|
UInt8 { [Func[[Object], [Byte]]]{ [System.Byte]::Parse($args[0].ToString()) } }
|
||||||
|
Unknown { "raw" }
|
||||||
|
default { "raw" }
|
||||||
|
}
|
||||||
|
return $arg_type
|
||||||
}
|
}
|
||||||
|
|
||||||
Function Cast-ToCimInstance($name, $value, $className)
|
Function Get-DscCimClassProperties {
|
||||||
{
|
<#
|
||||||
# this converts a hashtable to a CimInstance
|
.SYNOPSIS
|
||||||
|
Get's a list of CimProperties of a CIM Class. It filters out any magic or
|
||||||
|
read only properties that we don't need to know about.
|
||||||
|
#>
|
||||||
|
param([Parameter(Mandatory=$true)][String]$ClassName)
|
||||||
|
|
||||||
$valueType = $value.GetType()
|
$resource = Get-CimClass -ClassName $ClassName -Namespace root\Microsoft\Windows\DesiredStateConfiguration
|
||||||
if ($valueType -ne [hashtable])
|
|
||||||
{
|
# Filter out any magic properties that are used internally on an OMI_BaseResource
|
||||||
Fail-Json -obj $result -message "CimInstance value for property $name must be a hashtable, was $($valueType.FullName)"
|
# https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/DscSupport/CimDSCParser.cs#L1203
|
||||||
|
$magic_properties = @("ResourceId", "SourceInfo", "ModuleName", "ModuleVersion", "ConfigurationName")
|
||||||
|
$properties = $resource.CimClassProperties | Where-Object {
|
||||||
|
|
||||||
|
($resource.CimSuperClassName -ne "OMI_BaseResource" -or $_.Name -notin $magic_properties) -and
|
||||||
|
-not $_.Flags.HasFlag([Microsoft.Management.Infrastructure.CimFlags]::ReadOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
return ,$properties
|
||||||
{
|
|
||||||
$cim = New-CimInstance -ClassName $className -Property $value -ClientOnly
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message "Failed to convert hashtable to CimInstance of $($className): $($_.Exception.Message)"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ,$cim
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Function Cast-Value($value, $type, $typeString, $name)
|
Function Add-PropertyOption {
|
||||||
{
|
<#
|
||||||
if ($type -eq [CimInstance])
|
.SYNOPSIS
|
||||||
{
|
Adds the spec for the property type to the existing module specification.
|
||||||
$newValue = Cast-ToCimInstance -name $name -value $value -className $typeString
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][Hashtable]$Spec,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[Microsoft.Management.Infrastructure.CimPropertyDeclaration]$Property
|
||||||
|
)
|
||||||
|
|
||||||
|
$option = @{
|
||||||
|
required = $false
|
||||||
}
|
}
|
||||||
ElseIf ($type -eq [CimInstance[]])
|
$property_name = $Property.Name
|
||||||
{
|
$property_type = $Property.CimType.ToString()
|
||||||
if ($value -isnot [array])
|
|
||||||
{
|
if ($Property.Flags.HasFlag([Microsoft.Management.Infrastructure.CimFlags]::Key) -or
|
||||||
$value = @($value)
|
$Property.Flags.HasFlag([Microsoft.Management.Infrastructure.CimFlags]::Required)) {
|
||||||
}
|
$option.required = $true
|
||||||
[CimInstance[]]$newValue = @()
|
|
||||||
$baseTypeString = $typeString.Substring(0, $typeString.Length - 2)
|
|
||||||
foreach ($cim in $value)
|
|
||||||
{
|
|
||||||
$newValue += Cast-ToCimInstance -name $name -value $cim -className $baseTypeString
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Else
|
|
||||||
{
|
if ($null -ne $Property.Qualifiers['Values']) {
|
||||||
$originalType = $value.GetType()
|
$option.choices = [System.Collections.Generic.List`1[Object]]$Property.Qualifiers['Values'].Value
|
||||||
if ($originalType -eq $type)
|
}
|
||||||
{
|
|
||||||
$newValue = $value
|
if ($property_name -eq "Name") {
|
||||||
|
# For backwards compatibility we support specifying the Name DSC property as item_name
|
||||||
|
$option.aliases = @("item_name")
|
||||||
|
} elseif ($property_name -ceq "key") {
|
||||||
|
# There seems to be a bug in the CIM property parsing when the property name is 'Key'. The CIM instance will
|
||||||
|
# think the name is 'key' when the MOF actually defines it as 'Key'. We set the proper casing so the module arg
|
||||||
|
# validator won't fire a case sensitive warning
|
||||||
|
$property_name = "Key"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Property.ReferenceClassName -eq "MSFT_Credential") {
|
||||||
|
# Special handling for the MSFT_Credential type (PSCredential), we handle this with having 2 options that
|
||||||
|
# have the suffix _username and _password.
|
||||||
|
$option_spec_pass = @{
|
||||||
|
type = "str"
|
||||||
|
required = $option.required
|
||||||
|
no_log = $true
|
||||||
}
|
}
|
||||||
Else
|
$Spec.options."$($property_name)_password" = $option_spec_pass
|
||||||
{
|
$Spec.required_together.Add(@("$($property_name)_username", "$($property_name)_password")) > $null
|
||||||
$newValue = $value -as $type
|
|
||||||
if ($newValue -eq $null)
|
$property_name = "$($property_name)_username"
|
||||||
{
|
$option.type = "str"
|
||||||
Add-Warning -obj $result -message "failed to cast property $name from '$value' of type $($originalType.FullName) to type $($type.FullName), the DSC engine may ignore this property with an invalid cast"
|
} elseif ($Property.ReferenceClassName -eq "MSFT_KeyValuePair") {
|
||||||
$newValue = $value
|
$option.type = "dict"
|
||||||
|
} elseif ($property_type.EndsWith("Array")) {
|
||||||
|
$option.type = "list"
|
||||||
|
$option.elements = ConvertTo-ArgSpecType -CimType $property_type.Substring(0, $property_type.Length - 5)
|
||||||
|
} else {
|
||||||
|
$option.type = ConvertTo-ArgSpecType -CimType $property_type
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($option.type -eq "dict" -or ($option.type -eq "list" -and $option.elements -eq "dict")) -and
|
||||||
|
$Property.ReferenceClassName -ne "MSFT_KeyValuePair") {
|
||||||
|
# Get the sub spec if the type is a Instance (CimInstance/dict)
|
||||||
|
$sub_option_spec = Get-OptionSpec -ClassName $Property.ReferenceClassName
|
||||||
|
$option += $sub_option_spec
|
||||||
|
}
|
||||||
|
|
||||||
|
$Spec.options.$property_name = $option
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-OptionSpec {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Generates the specifiec used in AnsibleModule for a CIM MOF resource name.
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
This won't be able to retrieve the default values for an option as that is not defined in the MOF for a resource.
|
||||||
|
Default values are still preserved in the DSC engine if we don't pass in the property at all, we just can't report
|
||||||
|
on what they are automatically.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ClassName
|
||||||
|
)
|
||||||
|
|
||||||
|
$spec = @{
|
||||||
|
options = @{}
|
||||||
|
required_together = [System.Collections.ArrayList]@()
|
||||||
|
}
|
||||||
|
$properties = Get-DscCimClassProperties -ClassName $ClassName
|
||||||
|
foreach ($property in $properties) {
|
||||||
|
Add-PropertyOption -Spec $spec -Property $property
|
||||||
|
}
|
||||||
|
|
||||||
|
return $spec
|
||||||
|
}
|
||||||
|
|
||||||
|
Function ConvertTo-CimInstance {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Converts a dict to a CimInstance of the specified Class. Also provides a
|
||||||
|
better error message if this fails that contains the option name that failed.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$Name,
|
||||||
|
[Parameter(Mandatory=$true)][String]$ClassName,
|
||||||
|
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Value,
|
||||||
|
[Parameter(Mandatory=$true)][Ansible.Basic.AnsibleModule]$Module,
|
||||||
|
[Switch]$Recurse
|
||||||
|
)
|
||||||
|
|
||||||
|
$properties = @{}
|
||||||
|
foreach ($value_info in $Value.GetEnumerator()) {
|
||||||
|
# Need to remove all null values from existing dict so the conversion works
|
||||||
|
if ($null -eq $value_info.Value) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$properties.($value_info.Key) = $value_info.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Recurse) {
|
||||||
|
# We want to validate and convert and values to what's required by DSC
|
||||||
|
$properties = ConvertTo-DscProperty -ClassName $ClassName -Params $properties -Module $Module
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (New-CimInstance -ClassName $ClassName -Property $properties -ClientOnly)
|
||||||
|
} catch {
|
||||||
|
# New-CimInstance raises a poor error message, make sure we mention what option it is for
|
||||||
|
$Module.FailJson("Failed to cast dict value for option '$Name' to a CimInstance: $($_.Exception.Message)", $_)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function ConvertTo-DscProperty {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Converts the input module parameters that have been validated and casted
|
||||||
|
into the types expected by the DSC engine. This is mostly done to deal with
|
||||||
|
types like PSCredential and Dictionaries.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][String]$ClassName,
|
||||||
|
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Params,
|
||||||
|
[Parameter(Mandatory=$true)][Ansible.Basic.AnsibleModule]$Module
|
||||||
|
)
|
||||||
|
$properties = Get-DscCimClassProperties -ClassName $ClassName
|
||||||
|
|
||||||
|
$dsc_properties = @{}
|
||||||
|
foreach ($property in $properties) {
|
||||||
|
$property_name = $property.Name
|
||||||
|
$property_type = $property.CimType.ToString()
|
||||||
|
|
||||||
|
if ($property.ReferenceClassName -eq "MSFT_Credential") {
|
||||||
|
$username = $Params."$($property_name)_username"
|
||||||
|
$password = $Params."$($property_name)_password"
|
||||||
|
|
||||||
|
# No user set == No option set in playbook, skip this property
|
||||||
|
if ($null -eq $username) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$sec_password = ConvertTo-SecureString -String $password -AsPlainText -Force
|
||||||
|
$value = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $sec_password
|
||||||
|
} else {
|
||||||
|
$value = $Params.$property_name
|
||||||
|
|
||||||
|
# The actual value wasn't set, skip adding this property
|
||||||
|
if ($null -eq $value) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($property.ReferenceClassName -eq "MSFT_KeyValuePair") {
|
||||||
|
$key_value_pairs = [System.Collections.Generic.List`1[CimInstance]]@()
|
||||||
|
foreach ($value_info in $value.GetEnumerator()) {
|
||||||
|
$kvp = @{Key = $value_info.Key; Value = $value_info.Value.ToString()}
|
||||||
|
$cim_instance = ConvertTo-CimInstance -Name $property_name -ClassName MSFT_KeyValuePair `
|
||||||
|
-Value $kvp -Module $Module
|
||||||
|
$key_value_pairs.Add($cim_instance) > $null
|
||||||
|
}
|
||||||
|
$value = $key_value_pairs.ToArray()
|
||||||
|
} elseif ($null -ne $property.ReferenceClassName) {
|
||||||
|
# Convert the dict to a CimInstance (or list of CimInstances)
|
||||||
|
$convert_args = @{
|
||||||
|
ClassName = $property.ReferenceClassName
|
||||||
|
Module = $Module
|
||||||
|
Name = $property_name
|
||||||
|
Recurse = $true
|
||||||
|
}
|
||||||
|
if ($property_type.EndsWith("Array")) {
|
||||||
|
$value = [System.Collections.Generic.List`1[CimInstance]]@()
|
||||||
|
foreach ($raw in $Params.$property_name.GetEnumerator()) {
|
||||||
|
$cim_instance = ConvertTo-CimInstance -Value $raw @convert_args
|
||||||
|
$value.Add($cim_instance) > $null
|
||||||
|
}
|
||||||
|
$value = $value.ToArray() # Need to make sure we are dealing with an Array not a List
|
||||||
|
} else {
|
||||||
|
$value = ConvertTo-CimInstance -Value $value @convert_args
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$dsc_properties.$property_name = $value
|
||||||
}
|
}
|
||||||
|
|
||||||
return ,$newValue
|
return $dsc_properties
|
||||||
}
|
}
|
||||||
|
|
||||||
Function Parse-DscProperty($name, $value, $resourceProp)
|
Function Invoke-DscMethod {
|
||||||
{
|
<#
|
||||||
$propertyTypeString = $resourceProp.PropertyType
|
.SYNOPSIS
|
||||||
if ($propertyTypeString.StartsWith("["))
|
Invokes the DSC Resource Method specified in another PS pipeline. This is
|
||||||
{
|
done so we can retrieve the Verbose stream and return it back to the user
|
||||||
$propertyTypeString = $propertyTypeString.Substring(1, $propertyTypeString.Length - 2)
|
for futher debugging.
|
||||||
}
|
#>
|
||||||
$propertyType = $propertyTypeString -as [type]
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][Ansible.Basic.AnsibleModule]$Module,
|
||||||
|
[Parameter(Mandatory=$true)][String]$Method,
|
||||||
|
[Parameter(Mandatory=$true)][Hashtable]$Arguments
|
||||||
|
)
|
||||||
|
|
||||||
# CimInstance and CimInstance[] are reperesented as the actual Cim
|
# Invoke the DSC resource in a separate runspace so we can capture the Verbose output
|
||||||
# ClassName and the above returns a $null. We need to manually set the
|
$ps = [PowerShell]::Create()
|
||||||
# type in these cases
|
$ps.AddCommand("Invoke-DscResource").AddParameter("Method", $Method) > $null
|
||||||
if ($propertyType -eq $null)
|
$ps.AddParameters($Arguments) > $null
|
||||||
{
|
|
||||||
if ($propertyTypeString.EndsWith("[]"))
|
$result = $ps.Invoke()
|
||||||
{
|
|
||||||
$propertyType = [CimInstance[]]
|
# Pass the warnings through to the AnsibleModule return result
|
||||||
}
|
foreach ($warning in $ps.Streams.Warning) {
|
||||||
Else
|
$Module.Warn($warning.Message)
|
||||||
{
|
}
|
||||||
$propertyType = [CimInstance]
|
|
||||||
|
# If running at a high enough verbosity, add the verbose output to the AnsibleModule return result
|
||||||
|
if ($Module.Verbosity -ge 3) {
|
||||||
|
$verbose_logs = [System.Collections.Generic.List`1[String]]@()
|
||||||
|
foreach ($verbosity in $ps.Streams.Verbose) {
|
||||||
|
$verbose_logs.Add($verbosity.Message) > $null
|
||||||
}
|
}
|
||||||
|
$Module.Result."verbose_$($Method.ToLower())" = $verbose_logs
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($propertyType.IsArray)
|
if ($ps.HadErrors) {
|
||||||
{
|
# Cannot pass in the ErrorRecord as it's a RemotingErrorRecord and doesn't contain the ScriptStackTrace
|
||||||
# convert the value to a list for later conversion
|
# or other info that would be useful
|
||||||
if ($value -is [string])
|
$Module.FailJson("Failed to invoke DSC $Method method: $($ps.Streams.Error[0].Exception.Message)")
|
||||||
{
|
|
||||||
$value = $value.Split(",").Trim()
|
|
||||||
}
|
|
||||||
ElseIf ($value -isnot [array])
|
|
||||||
{
|
|
||||||
$value = @($value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$newValue = Cast-Value -value $value -type $propertyType -typeString $propertyTypeString -name $name
|
|
||||||
|
|
||||||
return ,$newValue
|
|
||||||
}
|
|
||||||
|
|
||||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
|
||||||
$resourcename = Get-AnsibleParam -obj $params -name "resource_name" -type "str" -failifempty $true
|
|
||||||
$module_version = Get-AnsibleParam -obj $params -name "module_version" -type "str" -default "latest"
|
|
||||||
|
|
||||||
#From Ansible 2.3 onwards, params is now a Hash Array
|
|
||||||
$Attributes = @{}
|
|
||||||
foreach ($param in $params.GetEnumerator())
|
|
||||||
{
|
|
||||||
if ($param.Name -notin @("resource_name", "module_version") -and $param.Name -notlike "_ansible_*")
|
|
||||||
{
|
|
||||||
$Attributes[$param.Name] = $param.Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Attributes.Count -eq 0)
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message "No attributes specified"
|
|
||||||
}
|
|
||||||
|
|
||||||
#Always return some basic info
|
|
||||||
$result["reboot_required"] = $false
|
|
||||||
|
|
||||||
$Config = @{
|
|
||||||
Name = ($resourcename)
|
|
||||||
Property = @{}
|
|
||||||
}
|
|
||||||
|
|
||||||
#Get the latest version of the module
|
|
||||||
if ($module_version -eq "latest")
|
|
||||||
{
|
|
||||||
$Resource = Get-DscResource -Name $resourcename -ErrorAction SilentlyContinue | sort Version | select -Last 1
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$Resource = Get-DscResource -Name $resourcename -ErrorAction SilentlyContinue | where {$_.Version -eq $module_version}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$Resource)
|
|
||||||
{
|
|
||||||
if ($module_version -eq "latest")
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message "Resource $resourcename not found"
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message "Resource $resourcename with version $module_version not found"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $result
|
||||||
}
|
}
|
||||||
|
|
||||||
#Get the Module that provides the resource. Will be used as
|
# win_dsc is unique in that is builds the arg spec based on DSC Resource input. To get this info
|
||||||
#mandatory argument for Invoke-DscResource
|
# we need to read the resource_name and module_version value which is done outside of Ansible.Basic
|
||||||
$Module = @{
|
if ($args.Length -gt 0) {
|
||||||
ModuleName = $Resource.ModuleName
|
$params = Get-Content -Path $args[0] | ConvertFrom-Json
|
||||||
ModuleVersion = $Resource.Version
|
} else {
|
||||||
|
$params = $complex_args
|
||||||
|
}
|
||||||
|
if (-not $params.ContainsKey("resource_name")) {
|
||||||
|
$res = @{
|
||||||
|
msg = "missing required argument: resource_name"
|
||||||
|
failed = $true
|
||||||
|
}
|
||||||
|
Write-Output -InputObject (ConvertTo-Json -Compress -InputObject $res)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$resource_name = $params.resource_name
|
||||||
|
|
||||||
|
if ($params.ContainsKey("module_version")) {
|
||||||
|
$module_version = $params.module_version
|
||||||
|
} else {
|
||||||
|
$module_version = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
$module_versions = (Get-DscResource -Name $resource_name -ErrorAction SilentlyContinue | Sort-Object -Property Version)
|
||||||
|
$resource = $null
|
||||||
|
if ($module_version -eq "latest" -and $null -ne $module_versions) {
|
||||||
|
$resource = $module_versions[-1]
|
||||||
|
} elseif ($module_version -ne "latest") {
|
||||||
|
$resource = $module_versions | Where-Object { $_.Version -eq $module_version }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $resource) {
|
||||||
|
if ($module_version -eq "latest") {
|
||||||
|
$msg = "Resource '$resource_name' not found."
|
||||||
|
} else {
|
||||||
|
$msg = "Resource '$resource_name' with version '$module_version' not found."
|
||||||
|
$msg += " Versions installed: '$($module_versions.Version -join "', '")'."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Output -InputObject (ConvertTo-Json -Compress -InputObject @{ failed = $true; msg = $msg })
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build the base args for the DSC Invocation based on the resource selected
|
||||||
|
$dsc_args = @{
|
||||||
|
Name = $resource.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
# Binary resources are not working very well with that approach - need to guesstimate module name/version
|
# Binary resources are not working very well with that approach - need to guesstimate module name/version
|
||||||
if ( -not ($Module.ModuleName -or $Module.ModuleVersion)) {
|
$module_version = $null
|
||||||
$Module = 'PSDesiredStateConfiguration'
|
if ($resource.Module) {
|
||||||
|
$dsc_args.ModuleName = @{
|
||||||
|
ModuleName = $resource.Module.Name
|
||||||
|
ModuleVersion = $resource.Module.Version
|
||||||
|
}
|
||||||
|
$module_version = $resource.Module.Version.ToString()
|
||||||
|
} else {
|
||||||
|
$dsc_args.ModuleName = "PSDesiredStateConfiguration"
|
||||||
}
|
}
|
||||||
|
|
||||||
#grab the module version if we can
|
# To ensure the class registered with CIM is the one based on our version, we want to run the Get method so the DSC
|
||||||
|
# engine updates the metadata propery. We don't care about any errors here
|
||||||
try {
|
try {
|
||||||
if ($Resource.Module.Version)
|
Invoke-DscResource -Method Get -Property @{Fake="Fake"} @dsc_args > $null
|
||||||
{
|
} catch {}
|
||||||
$result["module_version"] = $Resource.Module.Version.ToString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {}
|
|
||||||
|
|
||||||
#Convert params to correct datatype and inject
|
# Dynamically build the option spec based on the resource_name specified and create the module object
|
||||||
foreach ($attribute in $Attributes.GetEnumerator())
|
$spec = Get-OptionSpec -ClassName $resource.ResourceType
|
||||||
{
|
$spec.supports_check_mode = $true
|
||||||
$key = $attribute.Name.Replace("item_name", "name")
|
$spec.options.module_version = @{ type = "str"; default = "latest" }
|
||||||
$value = $attribute.Value
|
$spec.options.resource_name = @{ type = "str"; required = $true }
|
||||||
$prop = $resource.Properties | Where-Object {$_.Name -eq $key}
|
|
||||||
if (!$prop)
|
|
||||||
{
|
|
||||||
#If its a credential specified as "credential", Ansible will support credential_username and credential_password. Need to check for that
|
|
||||||
$prop = $resource.Properties | Where-Object {$_.Name -eq $key.Replace("_username","")}
|
|
||||||
if ($prop)
|
|
||||||
{
|
|
||||||
#We need to construct a cred object. At this point keyvalue is the username, so grab the password
|
|
||||||
$PropUserNameValue = $value
|
|
||||||
$PropPassword = $key.Replace("_username","_password")
|
|
||||||
$PropPasswordValue = $Attributes.$PropPassword
|
|
||||||
|
|
||||||
$KeyValue = New-Object System.Management.Automation.PSCredential ($PropUserNameValue, ($PropPasswordValue | ConvertTo-SecureString -AsPlainText -Force))
|
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
|
||||||
$config.Property.Add($key.Replace("_username",""),$KeyValue)
|
$module.Result.reboot_required = $false
|
||||||
}
|
$module.Result.module_version = $module_version
|
||||||
ElseIf ($key.Contains("_password"))
|
|
||||||
{
|
|
||||||
#Do nothing. We suck in the password in the handler for _username, so we can just skip it.
|
|
||||||
}
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message "Property $key in resource $resourcename is not a valid property"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
if ($value -eq $null)
|
|
||||||
{
|
|
||||||
$keyValue = $null
|
|
||||||
}
|
|
||||||
Else
|
|
||||||
{
|
|
||||||
$keyValue = Parse-DscProperty -name $key -value $value -resourceProp $prop
|
|
||||||
}
|
|
||||||
|
|
||||||
$config.Property.Add($key, $keyValue)
|
# Build the DSC invocation arguments and invoke the resource
|
||||||
|
$dsc_args.Property = ConvertTo-DscProperty -ClassName $resource.ResourceType -Module $module -Params $Module.Params
|
||||||
|
$dsc_args.Verbose = $true
|
||||||
|
|
||||||
|
$test_result = Invoke-DscMethod -Module $module -Method Test -Arguments $dsc_args
|
||||||
|
if ($test_result.InDesiredState -ne $true) {
|
||||||
|
if (-not $module.CheckMode) {
|
||||||
|
$result = Invoke-DscMethod -Module $module -Method Set -Arguments $dsc_args
|
||||||
|
$module.Result.reboot_required = $result.RebootRequired
|
||||||
}
|
}
|
||||||
|
$module.Result.changed = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
$module.ExitJson()
|
||||||
{
|
|
||||||
#Defined variables in strictmode
|
|
||||||
$TestError, $TestError = $null
|
|
||||||
$TestResult = Invoke-DscResource @Config -Method Test -ModuleName $Module -ErrorVariable TestError -ErrorAction SilentlyContinue -WarningVariable TestWarn
|
|
||||||
foreach ($warning in $TestWarn) {
|
|
||||||
Add-Warning -obj $result -message $warning.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($TestError)
|
|
||||||
{
|
|
||||||
throw ($TestError[0].Exception.Message)
|
|
||||||
}
|
|
||||||
ElseIf (($TestResult.InDesiredState) -ne $true)
|
|
||||||
{
|
|
||||||
if ($check_mode -eq $False)
|
|
||||||
{
|
|
||||||
$SetResult = Invoke-DscResource -Method Set @Config -ModuleName $Module -ErrorVariable SetError -ErrorAction SilentlyContinue -WarningVariable SetWarn
|
|
||||||
foreach ($warning in $SetWarn) {
|
|
||||||
Add-Warning -obj $result -message $warning.Message
|
|
||||||
}
|
|
||||||
if ($SetError -and ($SetResult -eq $null))
|
|
||||||
{
|
|
||||||
#If SetError was filled, throw to exit out of the try/catch loop
|
|
||||||
throw $SetError
|
|
||||||
}
|
|
||||||
$result["reboot_required"] = $SetResult.RebootRequired
|
|
||||||
}
|
|
||||||
$result["changed"] = $true
|
|
||||||
if ($SetError)
|
|
||||||
{
|
|
||||||
throw ($SetError[0].Exception.Message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Catch
|
|
||||||
{
|
|
||||||
Fail-Json -obj $result -message $_[0].Exception.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
Exit-Json -obj $result
|
|
||||||
|
|
|
@ -54,6 +54,11 @@ options:
|
||||||
provided but a comma separated string also work. Use a list where
|
provided but a comma separated string also work. Use a list where
|
||||||
possible as no escaping is required and it works with more complex types
|
possible as no escaping is required and it works with more complex types
|
||||||
list C(CimInstance[]).
|
list C(CimInstance[]).
|
||||||
|
- If the type of the DSC resource option is a C(DateTime), use a string in
|
||||||
|
the form of an ISO 8901 string.
|
||||||
|
- Since Ansible 2.8, Ansible will now validate the input fields against the
|
||||||
|
DSC resource definition automatically. Older versions will silently
|
||||||
|
ignore invalid fields.
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
notes:
|
notes:
|
||||||
|
@ -65,6 +70,9 @@ notes:
|
||||||
- The DSC engine run's each task as the SYSTEM account, any resources that need
|
- The DSC engine run's each task as the SYSTEM account, any resources that need
|
||||||
to be accessed with a different account need to have C(PsDscRunAsCredential)
|
to be accessed with a different account need to have C(PsDscRunAsCredential)
|
||||||
set.
|
set.
|
||||||
|
- To see the valid options for a DSC resource, run the module with C(-vvv) to
|
||||||
|
show the possible module invocation. Default values are not shown in this
|
||||||
|
output but are applied within the DSC engine.
|
||||||
author:
|
author:
|
||||||
- Trond Hindenes (@trondhindenes)
|
- Trond Hindenes (@trondhindenes)
|
||||||
'''
|
'''
|
||||||
|
@ -103,6 +111,11 @@ EXAMPLES = r'''
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
Type: Directory
|
Type: Directory
|
||||||
|
|
||||||
|
- name: Call DSC resource with DateTime option
|
||||||
|
win_dsc:
|
||||||
|
resource_name: DateTimeResource
|
||||||
|
DateTimeOption: '2019-02-22T13:57:31.2311892+00:00'
|
||||||
|
|
||||||
# more complex example using custom DSC resource and dict values
|
# more complex example using custom DSC resource and dict values
|
||||||
- name: Setup the xWebAdministration module
|
- name: Setup the xWebAdministration module
|
||||||
win_psmodule:
|
win_psmodule:
|
||||||
|
@ -137,7 +150,7 @@ EXAMPLES = r'''
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
module_version:
|
module_version:
|
||||||
description: The version of the dsc resource/module used.
|
description: The version of the dsc resource/module used.
|
||||||
returned: success
|
returned: always
|
||||||
type: str
|
type: str
|
||||||
sample: "1.0.1"
|
sample: "1.0.1"
|
||||||
reboot_required:
|
reboot_required:
|
||||||
|
@ -146,9 +159,24 @@ reboot_required:
|
||||||
returned: always
|
returned: always
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
message:
|
verbose_test:
|
||||||
description: Any error message from invoking the DSC resource.
|
description: The verbose output as a list from executing the DSC test
|
||||||
returned: error
|
method.
|
||||||
type: str
|
returned: Ansible verbosity is -vvv or greater
|
||||||
sample: Multiple DSC modules found with resource name xyz
|
type: list
|
||||||
|
sample: [
|
||||||
|
"Perform operation 'Invoke CimMethod' with the following parameters, ",
|
||||||
|
"[SERVER]: LCM: [Start Test ] [[File]DirectResourceAccess]",
|
||||||
|
"Operation 'Invoke CimMethod' complete."
|
||||||
|
]
|
||||||
|
verbose_set:
|
||||||
|
description: The verbose output as a list from executing the DSC Set
|
||||||
|
method.
|
||||||
|
returned: Ansible verbosity is -vvv or greater and a change occurred
|
||||||
|
type: list
|
||||||
|
sample: [
|
||||||
|
"Perform operation 'Invoke CimMethod' with the following parameters, ",
|
||||||
|
"[SERVER]: LCM: [Start Set ] [[File]DirectResourceAccess]",
|
||||||
|
"Operation 'Invoke CimMethod' complete."
|
||||||
|
]
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
# Feature not normally installed by default.
|
|
||||||
test_win_dsc_feature_name: Telnet-Client
|
|
||||||
test_win_dsc_folder: C:\ansible test
|
|
||||||
test_win_dsc_run_desctructive: no
|
|
|
@ -1,44 +0,0 @@
|
||||||
xTestResource Version: 2.0.0
|
|
||||||
|
|
||||||
Ensure:
|
|
||||||
Type: System.String
|
|
||||||
Value: Present
|
|
||||||
|
|
||||||
StringParam:
|
|
||||||
Type: System.String
|
|
||||||
Value: string param
|
|
||||||
|
|
||||||
UInt32Param:
|
|
||||||
Type: System.UInt32
|
|
||||||
Value: 1000
|
|
||||||
|
|
||||||
UInt64Param:
|
|
||||||
Type: System.UInt64
|
|
||||||
Value: 1000000
|
|
||||||
|
|
||||||
StringArrayParam:
|
|
||||||
Type: System.String[]
|
|
||||||
Value: [ "string 1", "string 2" ]
|
|
||||||
|
|
||||||
UInt32ArrayParam:
|
|
||||||
Type: System.UInt32[]
|
|
||||||
Value: [ 1000, 2000 ]
|
|
||||||
|
|
||||||
UInt64ArrayParam:
|
|
||||||
Type: System.UInt64[]
|
|
||||||
Value: [ 1000000, 2000000 ]
|
|
||||||
|
|
||||||
BooleanParam:
|
|
||||||
Type: System.Boolean
|
|
||||||
Value: True
|
|
||||||
|
|
||||||
PSCredentialParam:
|
|
||||||
Type: System.Management.Automation.PSCredential
|
|
||||||
Username: username
|
|
||||||
Password: password
|
|
||||||
|
|
||||||
CimInstanceParam:
|
|
||||||
Type: Microsoft.Management.Infrastructure.CimInstance
|
|
||||||
|
|
||||||
CimInstanceArrayParam:
|
|
||||||
Type: Microsoft.Management.Infrastructure.CimInstance[]
|
|
|
@ -1,44 +0,0 @@
|
||||||
xTestResource Version: 1.0.0
|
|
||||||
|
|
||||||
Ensure:
|
|
||||||
Type: System.String
|
|
||||||
Value: Present
|
|
||||||
|
|
||||||
StringParam:
|
|
||||||
Type: System.String
|
|
||||||
Value: string param
|
|
||||||
|
|
||||||
UInt32Param:
|
|
||||||
Type: System.UInt32
|
|
||||||
Value: 1000
|
|
||||||
|
|
||||||
UInt64Param:
|
|
||||||
Type: System.UInt64
|
|
||||||
Value: 1000000
|
|
||||||
|
|
||||||
StringArrayParam:
|
|
||||||
Type: System.String[]
|
|
||||||
Value: [ "string 1", "string 2" ]
|
|
||||||
|
|
||||||
UInt32ArrayParam:
|
|
||||||
Type: System.UInt32[]
|
|
||||||
Value: [ 1000, 2000 ]
|
|
||||||
|
|
||||||
UInt64ArrayParam:
|
|
||||||
Type: System.UInt64[]
|
|
||||||
Value: [ 1000000, 2000000 ]
|
|
||||||
|
|
||||||
BooleanParam:
|
|
||||||
Type: System.Boolean
|
|
||||||
Value: True
|
|
||||||
|
|
||||||
PSCredentialParam:
|
|
||||||
Type: System.Management.Automation.PSCredential
|
|
||||||
Username: username
|
|
||||||
Password: password
|
|
||||||
|
|
||||||
CimInstanceParam:
|
|
||||||
Type: Microsoft.Management.Infrastructure.CimInstance
|
|
||||||
|
|
||||||
CimInstanceArrayParam:
|
|
||||||
Type: Microsoft.Management.Infrastructure.CimInstance[]
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#Requires -Version 5.0 -Modules CimCmdlets
|
||||||
|
|
||||||
|
Function Get-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Hashtable])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String]$KeyParam
|
||||||
|
)
|
||||||
|
return @{Value = [bool]$global:DSCMachineStatus}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Set-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String]$KeyParam,
|
||||||
|
[Bool]$Value = $true
|
||||||
|
)
|
||||||
|
$global:DSCMachineStatus = [int]$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Test-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Boolean])]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String]$KeyParam,
|
||||||
|
[Bool]$Value = $true
|
||||||
|
)
|
||||||
|
$false
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function *-TargetResource
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[ClassVersion("1.0.0"), FriendlyName("xSetReboot")]
|
||||||
|
class ANSIBLE_xSetReboot : OMI_BaseResource
|
||||||
|
{
|
||||||
|
[Key] String KeyParam;
|
||||||
|
[Write] Boolean Value;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
#Requires -Version 5.0 -Modules CimCmdlets
|
||||||
|
|
||||||
|
Function ConvertFrom-CimInstance {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][CimInstance]$Instance
|
||||||
|
)
|
||||||
|
$hashtable = @{
|
||||||
|
_cim_instance = $Instance.CimSystemProperties.ClassName
|
||||||
|
}
|
||||||
|
foreach ($prop in $Instance.CimInstanceProperties) {
|
||||||
|
$hashtable."$($prop.Name)" = ConvertTo-OutputValue -Value $prop.Value
|
||||||
|
}
|
||||||
|
return $hashtable
|
||||||
|
}
|
||||||
|
|
||||||
|
Function ConvertTo-OutputValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($Value -is [DateTime[]]) {
|
||||||
|
$Value = $Value | ForEach-Object { $_.ToString("o") }
|
||||||
|
} elseif ($Value -is [DateTime]) {
|
||||||
|
$Value = $Value.ToString("o")
|
||||||
|
} elseif ($Value -is [Double]) {
|
||||||
|
$Value = $Value.ToString() # To avoid Python 2 double parsing issues on test validation
|
||||||
|
} elseif ($Value -is [Double[]]) {
|
||||||
|
$Value = $Value | ForEach-Object { $_.ToString() }
|
||||||
|
} elseif ($Value -is [PSCredential]) {
|
||||||
|
$password = $null
|
||||||
|
$password_ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($Value.Password)
|
||||||
|
try {
|
||||||
|
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($password_ptr)
|
||||||
|
} finally {
|
||||||
|
[System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($password_ptr)
|
||||||
|
}
|
||||||
|
$Value = @{
|
||||||
|
username = $Value.Username
|
||||||
|
password = $password
|
||||||
|
}
|
||||||
|
} elseif ($Value -is [CimInstance[]]) {
|
||||||
|
$value_list = [System.Collections.Generic.List`1[Hashtable]]@()
|
||||||
|
foreach ($cim_instance in $Value) {
|
||||||
|
$value_list.Add((ConvertFrom-CimInstance -Instance $cim_instance))
|
||||||
|
}
|
||||||
|
$Value = $value_list.ToArray()
|
||||||
|
} elseif ($Value -is [CimInstance]) {
|
||||||
|
$Value = ConvertFrom-CimInstance -Instance $Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return ,$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Hashtable])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path
|
||||||
|
)
|
||||||
|
return @{
|
||||||
|
Ensure = $Ensure
|
||||||
|
Path = $Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Set-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path,
|
||||||
|
|
||||||
|
[String] $DefaultParam = "Default",
|
||||||
|
[String] $StringParam,
|
||||||
|
[String[]] $StringArrayParam,
|
||||||
|
[SByte] $Int8Param,
|
||||||
|
[SByte[]] $Int8ArrayParam,
|
||||||
|
[Byte] $UInt8Param,
|
||||||
|
[Byte[]] $UInt8ArrayParam,
|
||||||
|
[Int16] $Int16Param,
|
||||||
|
[Int16[]] $Int16ArrayParam,
|
||||||
|
[UInt16] $UInt16Param,
|
||||||
|
[UInt16[]] $UInt16ArrayParam,
|
||||||
|
[Int32] $Int32Param,
|
||||||
|
[Int32[]] $Int32ArrayParam,
|
||||||
|
[UInt32] $UInt32Param,
|
||||||
|
[UInt32[]] $UInt32ArrayParam,
|
||||||
|
[Int64] $Int64Param,
|
||||||
|
[Int64[]] $Int64ArrayParam,
|
||||||
|
[UInt64] $UInt64Param,
|
||||||
|
[UInt64[]] $UInt64ArrayParam,
|
||||||
|
[Bool] $BooleanParam,
|
||||||
|
[Bool[]] $BooleanArrayParam,
|
||||||
|
[Char] $CharParam,
|
||||||
|
[Char[]] $CharArrayParam,
|
||||||
|
[Single] $SingleParam,
|
||||||
|
[Single[]] $SingleArrayParam,
|
||||||
|
[Double] $DoubleParam,
|
||||||
|
[Double[]] $DoubleArrayParam,
|
||||||
|
[DateTime] $DateTimeParam,
|
||||||
|
[DateTime[]] $DateTimeArrayParam,
|
||||||
|
[PSCredential] $PSCredentialParam,
|
||||||
|
[CimInstance[]] $HashtableParam,
|
||||||
|
[CimInstance] $CimInstanceParam,
|
||||||
|
[CimInstance[]] $CimInstanceArrayParam,
|
||||||
|
[CimInstance] $NestedCimInstanceParam,
|
||||||
|
[CimInstance[]] $NestedCimInstanceArrayParam
|
||||||
|
)
|
||||||
|
|
||||||
|
$info = @{
|
||||||
|
Version = "1.0.0"
|
||||||
|
Ensure = @{
|
||||||
|
Type = $Ensure.GetType().FullName
|
||||||
|
Value = $Ensure
|
||||||
|
}
|
||||||
|
Path = @{
|
||||||
|
Type = $Path.GetType().FullName
|
||||||
|
Value = $Path
|
||||||
|
}
|
||||||
|
DefaultParam = @{
|
||||||
|
Type = $DefaultParam.GetType().FullName
|
||||||
|
Value = $DefaultParam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($kvp in $PSCmdlet.MyInvocation.BoundParameters.GetEnumerator()) {
|
||||||
|
$info."$($kvp.Key)" = @{
|
||||||
|
Type = $kvp.Value.GetType().FullName
|
||||||
|
Value = (ConvertTo-OutputValue -Value $kvp.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -Path $Path) {
|
||||||
|
Remove-Item -Path $Path -Force > $null
|
||||||
|
}
|
||||||
|
New-Item -Path $Path -ItemType File > $null
|
||||||
|
Set-Content -Path $Path -Value (ConvertTo-Json -InputObject $info -Depth 10) > $null
|
||||||
|
Write-Verbose -Message "set verbose"
|
||||||
|
Write-Warning -Message "set warning"
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Test-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Boolean])]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path,
|
||||||
|
|
||||||
|
[String] $DefaultParam = "Default",
|
||||||
|
[String] $StringParam,
|
||||||
|
[String[]] $StringArrayParam,
|
||||||
|
[SByte] $Int8Param,
|
||||||
|
[SByte[]] $Int8ArrayParam,
|
||||||
|
[Byte] $UInt8Param,
|
||||||
|
[Byte[]] $UInt8ArrayParam,
|
||||||
|
[Int16] $Int16Param,
|
||||||
|
[Int16[]] $Int16ArrayParam,
|
||||||
|
[UInt16] $UInt16Param,
|
||||||
|
[UInt16[]] $UInt16ArrayParam,
|
||||||
|
[Int32] $Int32Param,
|
||||||
|
[Int32[]] $Int32ArrayParam,
|
||||||
|
[UInt32] $UInt32Param,
|
||||||
|
[UInt32[]] $UInt32ArrayParam,
|
||||||
|
[Int64] $Int64Param,
|
||||||
|
[Int64[]] $Int64ArrayParam,
|
||||||
|
[UInt64] $UInt64Param,
|
||||||
|
[UInt64[]] $UInt64ArrayParam,
|
||||||
|
[Bool] $BooleanParam,
|
||||||
|
[Bool[]] $BooleanArrayParam,
|
||||||
|
[Char] $CharParam,
|
||||||
|
[Char[]] $CharArrayParam,
|
||||||
|
[Single] $SingleParam,
|
||||||
|
[Single[]] $SingleArrayParam,
|
||||||
|
[Double] $DoubleParam,
|
||||||
|
[Double[]] $DoubleArrayParam,
|
||||||
|
[DateTime] $DateTimeParam,
|
||||||
|
[DateTime[]] $DateTimeArrayParam,
|
||||||
|
[PSCredential] $PSCredentialParam,
|
||||||
|
[CimInstance[]] $HashtableParam,
|
||||||
|
[CimInstance] $CimInstanceParam,
|
||||||
|
[CimInstance[]] $CimInstanceArrayParam,
|
||||||
|
[CimInstance] $NestedCimInstanceParam,
|
||||||
|
[CimInstance[]] $NestedCimInstanceArrayParam
|
||||||
|
)
|
||||||
|
Write-Verbose -Message "test verbose"
|
||||||
|
Write-Warning -Message "test warning"
|
||||||
|
$exists = Test-Path -LiteralPath $Path -PathType Leaf
|
||||||
|
if ($Ensure -eq "Present") {
|
||||||
|
$exists
|
||||||
|
} else {
|
||||||
|
-not $exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function *-TargetResource
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
[ClassVersion("1.0.0")]
|
||||||
|
class ANSIBLE_xTestClass
|
||||||
|
{
|
||||||
|
[Key] String Key;
|
||||||
|
[Write] String StringValue;
|
||||||
|
[Write] SInt32 IntValue;
|
||||||
|
[Write] String StringArrayValue[];
|
||||||
|
};
|
||||||
|
|
||||||
|
[ClassVersion("1.0.0")]
|
||||||
|
class ANSIBLE_xNestedClass
|
||||||
|
{
|
||||||
|
[Key] String KeyValue;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimValue;
|
||||||
|
[Write, EmbeddedInstance("MSFT_KeyValuePair")] String HashValue[];
|
||||||
|
[Write] SInt16 IntValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
[ClassVersion("1.0.0"), FriendlyName("xTestResource")]
|
||||||
|
class ANSIBLE_xTestResource : OMI_BaseResource
|
||||||
|
{
|
||||||
|
[Key] String Path;
|
||||||
|
[Required, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
|
||||||
|
[Read] String ReadParam;
|
||||||
|
[Write] String DefaultParam;
|
||||||
|
[Write] String StringParam;
|
||||||
|
[Write] String StringArrayParam[];
|
||||||
|
[Write] SInt8 Int8Param;
|
||||||
|
[Write] SInt8 Int8ArrayParam[];
|
||||||
|
[Write] UInt8 UInt8Param;
|
||||||
|
[Write] UInt8 UInt8ArrayParam[];
|
||||||
|
[Write] SInt16 Int16Param;
|
||||||
|
[Write] SInt16 Int16ArrayParam[];
|
||||||
|
[Write] UInt16 UInt16Param;
|
||||||
|
[Write] UInt16 UInt16ArrayParam[];
|
||||||
|
[Write] SInt32 Int32Param;
|
||||||
|
[Write] SInt32 Int32ArrayParam[];
|
||||||
|
[Write] UInt32 UInt32Param;
|
||||||
|
[Write] UInt32 UInt32ArrayParam[];
|
||||||
|
[Write] SInt64 Int64Param;
|
||||||
|
[Write] SInt64 Int64ArrayParam[];
|
||||||
|
[Write] UInt64 UInt64Param;
|
||||||
|
[Write] UInt64 UInt64ArrayParam[];
|
||||||
|
[Write] Boolean BooleanParam;
|
||||||
|
[Write] Boolean BooleanArrayParam[];
|
||||||
|
[Write] Char16 CharParam;
|
||||||
|
[Write] Char16 CharArrayParam[];
|
||||||
|
[Write] Real32 SingleParam;
|
||||||
|
[Write] Real32 SingleArrayParam[];
|
||||||
|
[Write] Real64 DoubleParam;
|
||||||
|
[Write] Real64 DoubleArrayParam[];
|
||||||
|
[Write] DateTime DateTimeParam;
|
||||||
|
[Write] DateTime DateTimeArrayParam[];
|
||||||
|
[Write, EmbeddedInstance("MSFT_Credential")] String PSCredentialParam;
|
||||||
|
[Write, EmbeddedInstance("MSFT_KeyValuePair")] String HashtableParam[];
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimInstanceArrayParam[];
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xNestedClass")] String NestedCimInstanceParam;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xNestedClass")] String NestedCimInstanceArrayParam[];
|
||||||
|
};
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
@{
|
@{
|
||||||
ModuleVersion = '{{item.version}}'
|
ModuleVersion = '1.0.0'
|
||||||
GUID = '{{item.version|to_uuid}}'
|
GUID = '80c895c4-de3f-4d6d-8fa4-c504c96b6f22'
|
||||||
Author = 'Ansible'
|
Author = 'Ansible'
|
||||||
CompanyName = 'Ansible'
|
CompanyName = 'Ansible'
|
||||||
Copyright = '(c) 2017'
|
Copyright = '(c) 2019'
|
||||||
Description = 'Test DSC Resource for Ansible integration tests'
|
Description = 'Test DSC Resource for Ansible integration tests'
|
||||||
PowerShellVersion = '5.0'
|
PowerShellVersion = '5.0'
|
||||||
CLRVersion = '4.0'
|
CLRVersion = '4.0'
|
||||||
FunctionsToExport = '*'
|
FunctionsToExport = '*'
|
||||||
CmdletsToExport = '*'
|
CmdletsToExport = '*'
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
#Requires -Version 5.0 -Modules CimCmdlets
|
||||||
|
|
||||||
|
Function ConvertFrom-CimInstance {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)][CimInstance]$Instance
|
||||||
|
)
|
||||||
|
$hashtable = @{
|
||||||
|
_cim_instance = $Instance.CimSystemProperties.ClassName
|
||||||
|
}
|
||||||
|
foreach ($prop in $Instance.CimInstanceProperties) {
|
||||||
|
$hashtable."$($prop.Name)" = ConvertTo-OutputValue -Value $prop.Value
|
||||||
|
}
|
||||||
|
return $hashtable
|
||||||
|
}
|
||||||
|
|
||||||
|
Function ConvertTo-OutputValue {
|
||||||
|
param($Value)
|
||||||
|
|
||||||
|
if ($Value -is [DateTime[]]) {
|
||||||
|
$Value = $Value | ForEach-Object { $_.ToString("o") }
|
||||||
|
} elseif ($Value -is [DateTime]) {
|
||||||
|
$Value = $Value.ToString("o")
|
||||||
|
} elseif ($Value -is [Double]) {
|
||||||
|
$Value = $Value.ToString() # To avoid Python 2 double parsing issues on test validation
|
||||||
|
} elseif ($Value -is [Double[]]) {
|
||||||
|
$Value = $Value | ForEach-Object { $_.ToString() }
|
||||||
|
} elseif ($Value -is [PSCredential]) {
|
||||||
|
$password = $null
|
||||||
|
$password_ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($Value.Password)
|
||||||
|
try {
|
||||||
|
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($password_ptr)
|
||||||
|
} finally {
|
||||||
|
[System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($password_ptr)
|
||||||
|
}
|
||||||
|
$Value = @{
|
||||||
|
username = $Value.Username
|
||||||
|
password = $password
|
||||||
|
}
|
||||||
|
} elseif ($Value -is [CimInstance[]]) {
|
||||||
|
$value_list = [System.Collections.Generic.List`1[Hashtable]]@()
|
||||||
|
foreach ($cim_instance in $Value) {
|
||||||
|
$value_list.Add((ConvertFrom-CimInstance -Instance $cim_instance))
|
||||||
|
}
|
||||||
|
$Value = $value_list.ToArray()
|
||||||
|
} elseif ($Value -is [CimInstance]) {
|
||||||
|
$Value = ConvertFrom-CimInstance -Instance $Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return ,$Value
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Get-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Hashtable])]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path
|
||||||
|
)
|
||||||
|
return @{
|
||||||
|
Ensure = $Ensure
|
||||||
|
Path = $Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Set-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path,
|
||||||
|
|
||||||
|
[String] $DefaultParam = "Default",
|
||||||
|
[String] $StringParam,
|
||||||
|
[String[]] $StringArrayParam,
|
||||||
|
[SByte] $Int8Param,
|
||||||
|
[SByte[]] $Int8ArrayParam,
|
||||||
|
[Byte] $UInt8Param,
|
||||||
|
[Byte[]] $UInt8ArrayParam,
|
||||||
|
[Int16] $Int16Param,
|
||||||
|
[Int16[]] $Int16ArrayParam,
|
||||||
|
[UInt16] $UInt16Param,
|
||||||
|
[UInt16[]] $UInt16ArrayParam,
|
||||||
|
[Int32] $Int32Param,
|
||||||
|
[Int32[]] $Int32ArrayParam,
|
||||||
|
[UInt32] $UInt32Param,
|
||||||
|
[UInt32[]] $UInt32ArrayParam,
|
||||||
|
[Int64] $Int64Param,
|
||||||
|
[Int64[]] $Int64ArrayParam,
|
||||||
|
[UInt64] $UInt64Param,
|
||||||
|
[UInt64[]] $UInt64ArrayParam,
|
||||||
|
[Bool] $BooleanParam,
|
||||||
|
[Bool[]] $BooleanArrayParam,
|
||||||
|
[Char] $CharParam,
|
||||||
|
[Char[]] $CharArrayParam,
|
||||||
|
[Single] $SingleParam,
|
||||||
|
[Single[]] $SingleArrayParam,
|
||||||
|
[Double] $DoubleParam,
|
||||||
|
[Double[]] $DoubleArrayParam,
|
||||||
|
[DateTime] $DateTimeParam,
|
||||||
|
[DateTime[]] $DateTimeArrayParam,
|
||||||
|
[PSCredential] $PSCredentialParam,
|
||||||
|
[CimInstance[]] $HashtableParam,
|
||||||
|
[CimInstance] $CimInstanceParam,
|
||||||
|
[CimInstance[]] $CimInstanceArrayParam,
|
||||||
|
[CimInstance] $NestedCimInstanceParam,
|
||||||
|
[CimInstance[]] $NestedCimInstanceArrayParam
|
||||||
|
)
|
||||||
|
|
||||||
|
$info = @{
|
||||||
|
Version = "1.0.1"
|
||||||
|
Ensure = @{
|
||||||
|
Type = $Ensure.GetType().FullName
|
||||||
|
Value = $Ensure
|
||||||
|
}
|
||||||
|
Path = @{
|
||||||
|
Type = $Path.GetType().FullName
|
||||||
|
Value = $Path
|
||||||
|
}
|
||||||
|
DefaultParam = @{
|
||||||
|
Type = $DefaultParam.GetType().FullName
|
||||||
|
Value = $DefaultParam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($kvp in $PSCmdlet.MyInvocation.BoundParameters.GetEnumerator()) {
|
||||||
|
$info."$($kvp.Key)" = @{
|
||||||
|
Type = $kvp.Value.GetType().FullName
|
||||||
|
Value = (ConvertTo-OutputValue -Value $kvp.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path -Path $Path) {
|
||||||
|
Remove-Item -Path $Path -Force > $null
|
||||||
|
}
|
||||||
|
New-Item -Path $Path -ItemType File > $null
|
||||||
|
Set-Content -Path $Path -Value (ConvertTo-Json -InputObject $info -Depth 10) > $null
|
||||||
|
Write-Verbose -Message "set verbose"
|
||||||
|
Write-Warning -Message "set warning"
|
||||||
|
}
|
||||||
|
|
||||||
|
Function Test-TargetResource
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Boolean])]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Present", "Absent")]
|
||||||
|
[String] $Ensure = "Present",
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String] $Path,
|
||||||
|
|
||||||
|
[String] $DefaultParam = "Default",
|
||||||
|
[String] $StringParam,
|
||||||
|
[String[]] $StringArrayParam,
|
||||||
|
[SByte] $Int8Param,
|
||||||
|
[SByte[]] $Int8ArrayParam,
|
||||||
|
[Byte] $UInt8Param,
|
||||||
|
[Byte[]] $UInt8ArrayParam,
|
||||||
|
[Int16] $Int16Param,
|
||||||
|
[Int16[]] $Int16ArrayParam,
|
||||||
|
[UInt16] $UInt16Param,
|
||||||
|
[UInt16[]] $UInt16ArrayParam,
|
||||||
|
[Int32] $Int32Param,
|
||||||
|
[Int32[]] $Int32ArrayParam,
|
||||||
|
[UInt32] $UInt32Param,
|
||||||
|
[UInt32[]] $UInt32ArrayParam,
|
||||||
|
[Int64] $Int64Param,
|
||||||
|
[Int64[]] $Int64ArrayParam,
|
||||||
|
[UInt64] $UInt64Param,
|
||||||
|
[UInt64[]] $UInt64ArrayParam,
|
||||||
|
[Bool] $BooleanParam,
|
||||||
|
[Bool[]] $BooleanArrayParam,
|
||||||
|
[Char] $CharParam,
|
||||||
|
[Char[]] $CharArrayParam,
|
||||||
|
[Single] $SingleParam,
|
||||||
|
[Single[]] $SingleArrayParam,
|
||||||
|
[Double] $DoubleParam,
|
||||||
|
[Double[]] $DoubleArrayParam,
|
||||||
|
[DateTime] $DateTimeParam,
|
||||||
|
[DateTime[]] $DateTimeArrayParam,
|
||||||
|
[PSCredential] $PSCredentialParam,
|
||||||
|
[CimInstance[]] $HashtableParam,
|
||||||
|
[CimInstance] $CimInstanceParam,
|
||||||
|
[CimInstance[]] $CimInstanceArrayParam,
|
||||||
|
[CimInstance] $NestedCimInstanceParam,
|
||||||
|
[CimInstance[]] $NestedCimInstanceArrayParam
|
||||||
|
)
|
||||||
|
Write-Verbose -Message "test verbose"
|
||||||
|
Write-Warning -Message "test warning"
|
||||||
|
$exists = Test-Path -LiteralPath $Path -PathType Leaf
|
||||||
|
if ($Ensure -eq "Present") {
|
||||||
|
$exists
|
||||||
|
} else {
|
||||||
|
-not $exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Export-ModuleMember -Function *-TargetResource
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
[ClassVersion("1.0.1")]
|
||||||
|
class ANSIBLE_xTestClass
|
||||||
|
{
|
||||||
|
[Key] String KeyValue;
|
||||||
|
[Write, ValueMap{"Choice1", "Choice2"}, Values{"Choice1", "Choice2"}] String Choice;
|
||||||
|
[Write] String StringValue;
|
||||||
|
[Write] SInt32 IntValue;
|
||||||
|
[Write] String StringArrayValue[];
|
||||||
|
};
|
||||||
|
|
||||||
|
[ClassVersion("1.0.1")]
|
||||||
|
class ANSIBLE_xNestedClass
|
||||||
|
{
|
||||||
|
[Key] String KeyValue;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimValue;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimArrayValue[];
|
||||||
|
[Write, EmbeddedInstance("MSFT_KeyValuePair")] String HashValue[];
|
||||||
|
[Write] SInt16 IntValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
[ClassVersion("1.0.1"), FriendlyName("xTestResource")]
|
||||||
|
class ANSIBLE_xTestResource : OMI_BaseResource
|
||||||
|
{
|
||||||
|
[Key] String Path;
|
||||||
|
[Required, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
|
||||||
|
[Read] String ReadParam;
|
||||||
|
[Write] String DefaultParam;
|
||||||
|
[Write] String StringParam;
|
||||||
|
[Write] String StringArrayParam[];
|
||||||
|
[Write] SInt8 Int8Param;
|
||||||
|
[Write] SInt8 Int8ArrayParam[];
|
||||||
|
[Write] UInt8 UInt8Param;
|
||||||
|
[Write] UInt8 UInt8ArrayParam[];
|
||||||
|
[Write] SInt16 Int16Param;
|
||||||
|
[Write] SInt16 Int16ArrayParam[];
|
||||||
|
[Write] UInt16 UInt16Param;
|
||||||
|
[Write] UInt16 UInt16ArrayParam[];
|
||||||
|
[Write] SInt32 Int32Param;
|
||||||
|
[Write] SInt32 Int32ArrayParam[];
|
||||||
|
[Write] UInt32 UInt32Param;
|
||||||
|
[Write] UInt32 UInt32ArrayParam[];
|
||||||
|
[Write] SInt64 Int64Param;
|
||||||
|
[Write] SInt64 Int64ArrayParam[];
|
||||||
|
[Write] UInt64 UInt64Param;
|
||||||
|
[Write] UInt64 UInt64ArrayParam[];
|
||||||
|
[Write] Boolean BooleanParam;
|
||||||
|
[Write] Boolean BooleanArrayParam[];
|
||||||
|
[Write] Char16 CharParam;
|
||||||
|
[Write] Char16 CharArrayParam[];
|
||||||
|
[Write] Real32 SingleParam;
|
||||||
|
[Write] Real32 SingleArrayParam[];
|
||||||
|
[Write] Real64 DoubleParam;
|
||||||
|
[Write] Real64 DoubleArrayParam[];
|
||||||
|
[Write] DateTime DateTimeParam;
|
||||||
|
[Write] DateTime DateTimeArrayParam[];
|
||||||
|
[Write, EmbeddedInstance("MSFT_Credential")] String PSCredentialParam;
|
||||||
|
[Write, EmbeddedInstance("MSFT_KeyValuePair")] String HashtableParam[];
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimInstanceParam;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimInstanceArrayParam[];
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xNestedClass")] String NestedCimInstanceParam;
|
||||||
|
[Write, EmbeddedInstance("ANSIBLE_xNestedClass")] String NestedCimInstanceArrayParam[];
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
@{
|
||||||
|
ModuleVersion = '1.0.1'
|
||||||
|
GUID = '80c895c4-de3f-4d6d-8fa4-c504c96b6f22'
|
||||||
|
Author = 'Ansible'
|
||||||
|
CompanyName = 'Ansible'
|
||||||
|
Copyright = '(c) 2019'
|
||||||
|
Description = 'Test DSC Resource for Ansible integration tests'
|
||||||
|
PowerShellVersion = '5.0'
|
||||||
|
CLRVersion = '4.0'
|
||||||
|
FunctionsToExport = '*'
|
||||||
|
CmdletsToExport = '*'
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
# (c) 2017 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
|
|
||||||
|
|
||||||
class FilterModule(object):
|
|
||||||
def filters(self):
|
|
||||||
return {
|
|
||||||
'strip_newline': self.strip_newline
|
|
||||||
}
|
|
||||||
|
|
||||||
def strip_newline(self, value):
|
|
||||||
# will convert \r\n and \n to just \n
|
|
||||||
split_lines = value.splitlines()
|
|
||||||
|
|
||||||
return "\n".join(split_lines)
|
|
|
@ -1,41 +0,0 @@
|
||||||
#!powershell
|
|
||||||
# This file is part of Ansible
|
|
||||||
|
|
||||||
# Copyright (c) 2017 Ansible Project
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
#Requires -Module Ansible.ModuleUtils.Legacy
|
|
||||||
|
|
||||||
Import-Module -Name WebAdministration
|
|
||||||
$params = Parse-Args $args -supports_check_mode $true
|
|
||||||
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
|
|
||||||
|
|
||||||
$site = Get-Website -Name $name
|
|
||||||
|
|
||||||
$result = @{}
|
|
||||||
if ($site -eq $null) {
|
|
||||||
$result.exists = $false
|
|
||||||
} else {
|
|
||||||
$result.exists = $true
|
|
||||||
$site_config = Get-WebConfiguration -Filter "System.WebServer/Security/Authentication/*" -PSPath "IIS:\Sites\$name"
|
|
||||||
$http_bindings = $site.bindings.Collection | Where-Object { $_.protocol -eq "http" }
|
|
||||||
$https_bindings = $site.bindings.Collection | Where-Object { $_.protocol -eq "https" }
|
|
||||||
|
|
||||||
$result.http = @{
|
|
||||||
binding = $http_bindings.bindingInformation
|
|
||||||
}
|
|
||||||
$result.https = @{
|
|
||||||
binding = $https_bindings.bindingInformation
|
|
||||||
sslFlags = $https_bindings.sslFlags
|
|
||||||
store = ($https_bindings.Attributes | Where-Object { $_.Name -eq "certificateStoreName" }).Value
|
|
||||||
hash = ($https_bindings.Attributes | Where-Object { $_.Name -eq "certificateHash" }).Value
|
|
||||||
}
|
|
||||||
$result.auth = @{
|
|
||||||
anonymous = ($site_config | Where-Object { $_.ElementTagName -like "*anonymous*" }).enabled
|
|
||||||
basic = ($site_config | Where-Object { $_.ElementTagName -like "*basic*" }).enabled
|
|
||||||
digest = ($site_config | Where-Object { $_.ElementTagName -like "*digest*" }).enabled
|
|
||||||
windows = ($site_config | Where-Object { $_.ElementTagName -like "*windows*" }).enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Exit-Json -obj $result
|
|
2
test/integration/targets/win_dsc/meta/main.yml
Normal file
2
test/integration/targets/win_dsc/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
dependencies:
|
||||||
|
- setup_remote_tmp_dir
|
|
@ -1,135 +0,0 @@
|
||||||
# these tests are destructive and can be run manually on a throwaway host
|
|
||||||
# set test_win_dsc_run_desctructive: yes in default/main.yml
|
|
||||||
---
|
|
||||||
- name: ensure IIS features are installed
|
|
||||||
win_feature:
|
|
||||||
name: Web-Server
|
|
||||||
include_sub_features: yes
|
|
||||||
include_management_tools: no
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: install xWebAdministration module
|
|
||||||
win_psmodule:
|
|
||||||
name: xWebAdministration
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: ensure IIS website does not exist
|
|
||||||
win_iis_website:
|
|
||||||
name: Ansible DSC Test
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: get certificate hash for IIS test
|
|
||||||
win_shell: (Get-ChildItem -Path Cert:\LocalMachine\My)[0].Thumbprint
|
|
||||||
register: win_dsc_cert_thumbprint
|
|
||||||
|
|
||||||
- name: create an IIS website with auth and binding info (check mode)
|
|
||||||
win_dsc:
|
|
||||||
resource_name: xWebSite
|
|
||||||
Ensure: Present
|
|
||||||
Name: Ansible DSC Test
|
|
||||||
State: Started
|
|
||||||
PhysicalPath: C:\inetpub\wwwroot
|
|
||||||
BindingInfo:
|
|
||||||
- Protocol: https
|
|
||||||
Port: 8443
|
|
||||||
CertificateStoreName: MY
|
|
||||||
CertificateThumbprint: '{{win_dsc_cert_thumbprint.stdout_lines[0]}}'
|
|
||||||
HostName: DSCTest
|
|
||||||
IPAddress: '*'
|
|
||||||
SSLFlags: '1'
|
|
||||||
- Protocol: http
|
|
||||||
Port: 8888
|
|
||||||
IPAddress: '*'
|
|
||||||
AuthenticationInfo:
|
|
||||||
Anonymous: yes
|
|
||||||
Basic: no
|
|
||||||
Digest: no
|
|
||||||
Windows: yes
|
|
||||||
register: win_dsc_iis_check
|
|
||||||
check_mode: yes
|
|
||||||
|
|
||||||
- name: get result of create an IIS website (check mode)
|
|
||||||
test_win_dsc_iis_info:
|
|
||||||
name: Ansible DSC Test
|
|
||||||
register: win_dsc_iis_check_result
|
|
||||||
|
|
||||||
- name: assert results of create an IIS website (check mode)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_iis_check is changed
|
|
||||||
- win_dsc_iis_check_result.exists == False
|
|
||||||
|
|
||||||
- name: create an IIS website with auth and binding info
|
|
||||||
win_dsc:
|
|
||||||
resource_name: xWebSite
|
|
||||||
Ensure: Present
|
|
||||||
Name: Ansible DSC Test
|
|
||||||
State: Started
|
|
||||||
PhysicalPath: C:\inetpub\wwwroot
|
|
||||||
BindingInfo:
|
|
||||||
- Protocol: https
|
|
||||||
Port: 8443
|
|
||||||
CertificateStoreName: MY
|
|
||||||
CertificateThumbprint: '{{win_dsc_cert_thumbprint.stdout_lines[0]}}'
|
|
||||||
HostName: Test
|
|
||||||
IPAddress: '*'
|
|
||||||
SSLFlags: '1'
|
|
||||||
- Protocol: http
|
|
||||||
Port: 8888
|
|
||||||
IPAddress: '*'
|
|
||||||
AuthenticationInfo:
|
|
||||||
Anonymous: yes
|
|
||||||
Basic: no
|
|
||||||
Digest: no
|
|
||||||
Windows: yes
|
|
||||||
register: win_dsc_iis
|
|
||||||
|
|
||||||
- name: get result of create an IIS website
|
|
||||||
test_win_dsc_iis_info:
|
|
||||||
name: Ansible DSC Test
|
|
||||||
register: win_dsc_iis_result
|
|
||||||
|
|
||||||
- name: assert results of create an IIS website
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_iis is changed
|
|
||||||
- win_dsc_iis_result.exists == True
|
|
||||||
- win_dsc_iis_result.auth.anonymous == True
|
|
||||||
- win_dsc_iis_result.auth.basic == False
|
|
||||||
- win_dsc_iis_result.auth.digest == False
|
|
||||||
- win_dsc_iis_result.auth.windows == True
|
|
||||||
- win_dsc_iis_result.http.binding == "*:8888:"
|
|
||||||
- win_dsc_iis_result.https.binding == "*:8443:Test"
|
|
||||||
- win_dsc_iis_result.https.hash == '{{win_dsc_cert_thumbprint.stdout_lines[0]}}'
|
|
||||||
- win_dsc_iis_result.https.sslFlags == 1
|
|
||||||
- win_dsc_iis_result.https.store == "MY"
|
|
||||||
|
|
||||||
- name: create an IIS website with auth and binding info (idempotent)
|
|
||||||
win_dsc:
|
|
||||||
resource_name: xWebSite
|
|
||||||
Ensure: Present
|
|
||||||
Name: Ansible DSC Test
|
|
||||||
State: Started
|
|
||||||
PhysicalPath: C:\inetpub\wwwroot
|
|
||||||
BindingInfo:
|
|
||||||
- Protocol: https
|
|
||||||
Port: 8443
|
|
||||||
CertificateStoreName: MY
|
|
||||||
CertificateThumbprint: '{{win_dsc_cert_thumbprint.stdout_lines[0]}}'
|
|
||||||
HostName: Test
|
|
||||||
IPAddress: '*'
|
|
||||||
SSLFlags: '1'
|
|
||||||
- Protocol: http
|
|
||||||
Port: 8888
|
|
||||||
IPAddress: '*'
|
|
||||||
AuthenticationInfo:
|
|
||||||
Anonymous: yes
|
|
||||||
Basic: no
|
|
||||||
Digest: no
|
|
||||||
Windows: yes
|
|
||||||
register: win_dsc_iis_again
|
|
||||||
|
|
||||||
- name: assert results of create an IIS website (idempotent)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_iis_again is not changed
|
|
|
@ -3,32 +3,37 @@
|
||||||
win_shell: $PSVersionTable.PSVersion.Major
|
win_shell: $PSVersionTable.PSVersion.Major
|
||||||
register: powershell_version
|
register: powershell_version
|
||||||
|
|
||||||
- name: run smoke tests when we can't run the full suite
|
- name: expect failure when running on old PS hosts
|
||||||
include_tasks: smoke.yml
|
win_dsc:
|
||||||
|
resource_name: File
|
||||||
|
register: fail_dsc_old
|
||||||
|
failed_when: '"This module cannot run as it requires a minimum PowerShell version of 5.0" not in fail_dsc_old.msg'
|
||||||
when: powershell_version.stdout_lines[0]|int < 5
|
when: powershell_version.stdout_lines[0]|int < 5
|
||||||
|
|
||||||
- block:
|
- name: run tests when PSv5+
|
||||||
- name: run non-destructive tests
|
when: powershell_version.stdout_lines[0]|int >= 5
|
||||||
|
block:
|
||||||
|
- name: add remote temp dir to PSModulePath
|
||||||
|
win_path:
|
||||||
|
name: PSModulePath
|
||||||
|
state: present
|
||||||
|
scope: machine
|
||||||
|
elements:
|
||||||
|
- '{{ remote_tmp_dir }}'
|
||||||
|
|
||||||
|
- name: copy custom DSC resources to remote temp dir
|
||||||
|
win_copy:
|
||||||
|
src: xTestDsc
|
||||||
|
dest: '{{ remote_tmp_dir }}'
|
||||||
|
|
||||||
|
- name: run tests
|
||||||
include_tasks: tests.yml
|
include_tasks: tests.yml
|
||||||
|
|
||||||
- name: run destructive tests if flag is set
|
|
||||||
include_tasks: destructive.yml
|
|
||||||
when: test_win_dsc_run_desctructive == True
|
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: remove test feature
|
- name: remove remote tmp dir from PSModulePath
|
||||||
win_feature:
|
win_path:
|
||||||
name: '{{test_win_dsc_feature_name}}'
|
name: PSModulePath
|
||||||
state: absent
|
state: absent
|
||||||
|
scope: machine
|
||||||
- name: remove test folder
|
elements:
|
||||||
win_file:
|
- '{{ remote_tmp_dir }}'
|
||||||
path: '{{test_win_dsc_folder}}'
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: remove custom DSC resource folder
|
|
||||||
win_file:
|
|
||||||
path: C:\Program Files\WindowsPowerShell\Modules\xTestDsc
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
when: powershell_version.stdout_lines[0]|int >= 5
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
# basic smoke tests run on hosts that cannot run DSC, verifies the code is at
|
|
||||||
# least runnable
|
|
||||||
---
|
|
||||||
- name: expect failure when running on old PS hosts
|
|
||||||
win_dsc:
|
|
||||||
resource_name: File
|
|
||||||
register: fail_dsc_old
|
|
||||||
failed_when: '"This module cannot run as it requires a minimum PowerShell version of 5.0, actual was " not in fail_dsc_old.msg'
|
|
|
@ -1,333 +1,544 @@
|
||||||
# slightly non-destructive tests that will run if WMF 5.0 is installed
|
|
||||||
---
|
---
|
||||||
- name: start with feature absent
|
|
||||||
win_feature:
|
|
||||||
name: '{{test_win_dsc_feature_name}}'
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: fail with incorrect DSC resource name
|
- name: fail with incorrect DSC resource name
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: FakeResource
|
resource_name: FakeResource
|
||||||
Name: fake
|
|
||||||
register: fail_invalid_resource
|
register: fail_invalid_resource
|
||||||
failed_when: fail_invalid_resource.msg != "Resource FakeResource not found"
|
failed_when: fail_invalid_resource.msg != "Resource 'FakeResource' not found."
|
||||||
|
|
||||||
- name: fail by not setting mandatory option
|
- name: fail with invalid DSC version
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xTestResource
|
||||||
|
module_version: 0.0.1
|
||||||
|
register: fail_invalid_version
|
||||||
|
failed_when: 'fail_invalid_version.msg != "Resource ''xTestResource'' with version ''0.0.1'' not found. Versions installed: ''1.0.0'', ''1.0.1''."'
|
||||||
|
|
||||||
|
- name: fail with mandatory option not set
|
||||||
|
win_dsc:
|
||||||
|
resource_name: xSetReboot
|
||||||
|
Value: yes
|
||||||
|
register: fail_man_key
|
||||||
|
failed_when: 'fail_man_key.msg != "missing required arguments: KeyParam"'
|
||||||
|
|
||||||
|
- name: fail with mandatory option not set in sub dict
|
||||||
|
win_dsc:
|
||||||
|
resource_name: xTestResource
|
||||||
|
Path: C:\path
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
register: fail_missing_mandatory
|
CimInstanceParam: # Missing KeyValue in dict
|
||||||
failed_when: fail_missing_mandatory.msg != "Could not find mandatory property Name. Add this property and try again."
|
Choice: Choice1
|
||||||
|
register: fail_man_key_sub_dict
|
||||||
|
failed_when: 'fail_man_key_sub_dict.msg != "missing required arguments: KeyValue found in CimInstanceParam"'
|
||||||
|
|
||||||
- name: fail to add a non-existant feature
|
- name: fail invalid option
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xSetReboot
|
||||||
Name: InvalidFeature
|
KeyParam: key
|
||||||
|
OtherParam: invalid
|
||||||
|
register: fail_invalid_option
|
||||||
|
failed_when: 'fail_invalid_option.msg != "Unsupported parameters for (win_dsc) module: OtherParam. Supported parameters include: KeyParam, PsDscRunAsCredential_username, module_version, Value, PsDscRunAsCredential_password, resource_name, DependsOn"'
|
||||||
|
|
||||||
|
- name: fail invalid option in sub dict
|
||||||
|
win_dsc:
|
||||||
|
resource_name: xTestResource
|
||||||
|
Path: C:\path
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
register: fail_invalid_feature
|
NestedCimInstanceParam:
|
||||||
failed_when: '"The requested feature InvalidFeature is not found on the target machine" not in fail_invalid_feature.msg'
|
KeyValue: key
|
||||||
|
CimValue:
|
||||||
|
KeyValue: other key
|
||||||
|
InvalidKey: invalid
|
||||||
|
register: fail_invalid_option_sub_dict
|
||||||
|
failed_when: 'fail_invalid_option_sub_dict.msg != "Unsupported parameters for (win_dsc) module: InvalidKey found in NestedCimInstanceParam -> CimValue. Supported parameters include: IntValue, KeyValue, StringArrayValue, Choice, StringValue"'
|
||||||
|
|
||||||
- name: add Windows feature (check mode)
|
- name: fail invalid read only option
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xTestResource
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
Path: C:\path
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
register: win_dsc_add_feature_check
|
ReadParam: abc
|
||||||
check_mode: yes
|
register: fail_invalid_option_read_only
|
||||||
|
failed_when: '"Unsupported parameters for (win_dsc) module: ReadParam" not in fail_invalid_option_read_only.msg'
|
||||||
|
|
||||||
- name: get result of add Windows feature (check mode)
|
- name: fail invalid choice
|
||||||
win_shell: (Get-WindowsFeature -Name {{test_win_dsc_feature_name}}).Installed
|
|
||||||
register: win_dsc_add_feature_result_check
|
|
||||||
|
|
||||||
- name: assert result of add Windows feature (check mode)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_add_feature_check is changed
|
|
||||||
- win_dsc_add_feature_result_check.stdout == "False\r\n"
|
|
||||||
|
|
||||||
- name: add Windows feature
|
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xTestResource
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
Path: C:\path
|
||||||
|
Ensure: invalid
|
||||||
|
register: fail_invalid_choice
|
||||||
|
failed_when: 'fail_invalid_choice.msg != "value of Ensure must be one of: Present, Absent. Got no match for: invalid"'
|
||||||
|
|
||||||
|
- name: fail invalid choice in sub dict
|
||||||
|
win_dsc:
|
||||||
|
resource_name: xTestResource
|
||||||
|
Path: C:\path
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
register: win_dsc_add_feature
|
CimInstanceArrayParam:
|
||||||
|
- KeyValue: key
|
||||||
|
- KeyValue: key2
|
||||||
|
Choice: Choice3
|
||||||
|
register: fail_invalid_choice_sub_dict
|
||||||
|
failed_when: 'fail_invalid_choice_sub_dict.msg != "value of Choice must be one of: Choice1, Choice2. Got no match for: Choice3 found in CimInstanceArrayParam"'
|
||||||
|
|
||||||
- name: get result of add Windows feature
|
- name: fail old version missing new option
|
||||||
win_shell: (Get-WindowsFeature -Name {{test_win_dsc_feature_name}}).Installed
|
|
||||||
register: win_dsc_add_feature_result
|
|
||||||
|
|
||||||
- name: assert result of add Windows feature
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_add_feature is changed
|
|
||||||
- win_dsc_add_feature_result.stdout == "True\r\n"
|
|
||||||
|
|
||||||
- name: add Windows feature (idempotent)
|
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xTestResource
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
module_version: 1.0.0
|
||||||
|
Path: C:\path
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
register: win_dsc_add_feature_again
|
CimInstanceParam: # CimInstanceParam does not exist in the 1.0.0 version
|
||||||
|
Key: key
|
||||||
|
register: fail_invalid_option_old
|
||||||
|
failed_when: '"Unsupported parameters for (win_dsc) module: CimInstanceParam" not in fail_invalid_option_old.msg'
|
||||||
|
|
||||||
- name: assert result of add Windows feature (idempotent)
|
- name: fail old version missing new option sub dict
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_add_feature_again is not changed
|
|
||||||
|
|
||||||
- name: remove Windows feature (check mode)
|
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: WindowsFeature
|
resource_name: xTestResource
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
module_version: 1.0.0
|
||||||
Ensure: Absent
|
Path: C:\path
|
||||||
register: win_dsc_remove_feature_check
|
Ensure: Present
|
||||||
check_mode: yes
|
CimInstanceArrayParam:
|
||||||
|
- Key: key
|
||||||
- name: get result of remove Windows feature (check mode)
|
Choice: Choice1
|
||||||
win_shell: (Get-WindowsFeature -Name {{test_win_dsc_feature_name}}).Installed
|
register: fail_invalid_option_old_sub_dict
|
||||||
register: win_dsc_remove_feature_result_check
|
failed_when: 'fail_invalid_option_old_sub_dict.msg != "Unsupported parameters for (win_dsc) module: Choice found in CimInstanceArrayParam. Supported parameters include: Key, IntValue, StringArrayValue, StringValue"'
|
||||||
|
|
||||||
- name: assert result of remove Windows feature (check mode)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_remove_feature_check is changed
|
|
||||||
- win_dsc_remove_feature_result_check.stdout == "True\r\n"
|
|
||||||
|
|
||||||
- name: remove Windows feature
|
|
||||||
win_dsc:
|
|
||||||
resource_name: WindowsFeature
|
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
|
||||||
Ensure: Absent
|
|
||||||
register: win_dsc_remove_feature
|
|
||||||
|
|
||||||
- name: get result of remove Windows feature
|
|
||||||
win_shell: (Get-WindowsFeature -Name {{test_win_dsc_feature_name}}).Installed
|
|
||||||
register: win_dsc_remove_feature_result
|
|
||||||
|
|
||||||
- name: assert result of remove Windows feature
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_remove_feature is changed
|
|
||||||
- win_dsc_remove_feature_result.stdout == "False\r\n"
|
|
||||||
|
|
||||||
- name: remove Windows feature (idempotent)
|
|
||||||
win_dsc:
|
|
||||||
resource_name: WindowsFeature
|
|
||||||
Name: '{{test_win_dsc_feature_name}}'
|
|
||||||
Ensure: Absent
|
|
||||||
register: win_dsc_remove_feature_again
|
|
||||||
|
|
||||||
- name: assert result of remove Windows feature (idempotent)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- win_dsc_remove_feature_again is not changed
|
|
||||||
|
|
||||||
- name: ensure test folder doesn't exist before test
|
|
||||||
win_file:
|
|
||||||
path: '{{test_win_dsc_folder}}'
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: create test file (check mode)
|
- name: create test file (check mode)
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: File
|
resource_name: File
|
||||||
DestinationPath: '{{test_win_dsc_folder}}\dsc-file'
|
DestinationPath: '{{ remote_tmp_dir }}\dsc-file'
|
||||||
Contents: file contents
|
Contents: file contents
|
||||||
Attributes:
|
Attributes:
|
||||||
- Hidden
|
- Hidden
|
||||||
- ReadOnly
|
- ReadOnly
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
Type: File
|
Type: File
|
||||||
register: win_dsc_create_file_check
|
register: create_file_check
|
||||||
check_mode: yes
|
check_mode: yes
|
||||||
|
|
||||||
- name: get result of create test file (check mode)
|
- name: get result of create test file (check mode)
|
||||||
win_stat:
|
win_stat:
|
||||||
path: '{{test_win_dsc_folder}}\dsc-file'
|
path: '{{ remote_tmp_dir }}\dsc-file'
|
||||||
register: win_dsc_create_file_result_check
|
register: create_file_actual_check
|
||||||
|
|
||||||
- name: assert results of create test file (check mode)
|
- name: assert create test file (check mode)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- win_dsc_create_file_check is changed
|
- create_file_check is changed
|
||||||
- win_dsc_create_file_result_check.stat.exists == False
|
- create_file_check.module_version == None # Some built in modules don't have a version set
|
||||||
|
- not create_file_check.reboot_required
|
||||||
|
- not create_file_actual_check.stat.exists
|
||||||
|
|
||||||
|
- name: assert create test file verbosity (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- create_file_check.verbose_test is defined
|
||||||
|
- not create_file_check.verbose_set is defined
|
||||||
|
when: ansible_verbosity >= 3
|
||||||
|
|
||||||
- name: create test file
|
- name: create test file
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: File
|
resource_name: File
|
||||||
DestinationPath: '{{test_win_dsc_folder}}\dsc-file'
|
DestinationPath: '{{ remote_tmp_dir }}\dsc-file'
|
||||||
Contents: file contents
|
Contents: file contents
|
||||||
Attributes:
|
Attributes:
|
||||||
- Hidden
|
- Hidden
|
||||||
- ReadOnly
|
- ReadOnly
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
Type: File
|
Type: File
|
||||||
register: win_dsc_create_file
|
register: create_file
|
||||||
|
|
||||||
- name: get result of create test file
|
- name: get result of create test file
|
||||||
win_stat:
|
win_stat:
|
||||||
path: '{{test_win_dsc_folder}}\dsc-file'
|
path: '{{ remote_tmp_dir }}\dsc-file'
|
||||||
register: win_dsc_create_file_result
|
register: create_file_actual
|
||||||
|
|
||||||
- name: assert results of create test file
|
- name: assert create test file verbosity
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- win_dsc_create_file is changed
|
- create_file.verbose_test is defined
|
||||||
- win_dsc_create_file_result.stat.exists == True
|
- create_file.verbose_set is defined
|
||||||
- win_dsc_create_file_result.stat.isdir == False
|
when: ansible_verbosity >= 3
|
||||||
- win_dsc_create_file_result.stat.ishidden == True
|
|
||||||
- win_dsc_create_file_result.stat.isreadonly == True
|
- name: assert create test file
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- create_file is changed
|
||||||
|
- create_file.module_version == None
|
||||||
|
- not create_file.reboot_required
|
||||||
|
- create_file_actual.stat.exists
|
||||||
|
- create_file_actual.stat.attributes == "ReadOnly, Hidden, Archive"
|
||||||
|
- create_file_actual.stat.checksum == 'd48daab51112b49ecabd917adc345b8ba257055e'
|
||||||
|
|
||||||
- name: create test file (idempotent)
|
- name: create test file (idempotent)
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: File
|
resource_name: File
|
||||||
DestinationPath: '{{test_win_dsc_folder}}\dsc-file'
|
DestinationPath: '{{ remote_tmp_dir }}\dsc-file'
|
||||||
Contents: file contents
|
Contents: file contents
|
||||||
Attributes: Hidden, ReadOnly
|
Attributes:
|
||||||
|
- Hidden
|
||||||
|
- ReadOnly
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
Type: File
|
Type: File
|
||||||
register: win_dsc_create_file_again
|
register: create_file_again
|
||||||
|
|
||||||
- name: assert results of create test file (idempotent)
|
- name: assert create test file (idempotent)
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- win_dsc_create_file_again is not changed
|
- not create_file_again is changed
|
||||||
|
- create_file.module_version == None
|
||||||
|
- not create_file.reboot_required
|
||||||
|
|
||||||
- name: get SID of current ansible user
|
- name: get SID of the current Ansible user
|
||||||
win_shell: (New-Object System.Security.Principal.NTAccount("{{ansible_user}}")).Translate([System.Security.Principal.SecurityIdentifier]).ToString()
|
win_shell: |
|
||||||
register: win_dsc_actual_sid
|
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
|
||||||
|
[System.DirectoryServices.AccountManagement.UserPrincipal]::Current.Sid.Value
|
||||||
|
register: actual_sid
|
||||||
|
|
||||||
- name: run DSC process as another user
|
- name: run DSC process as another user
|
||||||
win_dsc:
|
win_dsc:
|
||||||
resource_name: Script
|
resource_name: Script
|
||||||
GetScript: '@{ Result = "" }'
|
GetScript: '@{ Result= "" }'
|
||||||
SetScript: |
|
SetScript: |
|
||||||
$output = &whoami.exe
|
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
|
||||||
$sid = (New-Object System.Security.Principal.NTAccount($output)).Translate([System.Security.Principal.SecurityIdentifier]).ToString()
|
$sid = [System.DirectoryServices.AccountManagement.UserPrincipal]::Current.Sid.Value
|
||||||
Set-Content -Path "{{test_win_dsc_folder}}\file" -Value $sid
|
Set-Content -Path "{{ remote_tmp_dir }}\runas.txt" -Value $sid
|
||||||
TestScript: Test-Path -Path "{{test_win_dsc_folder}}\file"
|
TestScript: $false
|
||||||
PsDscRunAsCredential_username: '{{ansible_user}}'
|
PsDscRunAsCredential_username: '{{ ansible_user }}'
|
||||||
PsDscRunAsCredential_password: '{{ansible_password}}'
|
PsDscRunAsCredential_password: '{{ ansible_password }}'
|
||||||
register: win_dsc_runas
|
register: runas_user
|
||||||
|
|
||||||
- name: get content of script output file
|
- name: get result of run DSC process as another user
|
||||||
slurp:
|
slurp:
|
||||||
path: '{{test_win_dsc_folder}}\file'
|
path: '{{ remote_tmp_dir }}\runas.txt'
|
||||||
register: win_dsc_runas_result
|
register: runas_user_result
|
||||||
|
|
||||||
- name: assert results of run DSC process as another user
|
- name: assert run DSC process as another user
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- win_dsc_runas is changed
|
- runas_user is changed
|
||||||
- win_dsc_runas_result.content|b64decode == win_dsc_actual_sid.stdout
|
- runas_user.module_version != None # Can't reliably set the version but we can test it is set
|
||||||
|
- not runas_user.reboot_required
|
||||||
|
- runas_user_result.content|b64decode == actual_sid.stdout
|
||||||
|
|
||||||
- name: create custom DSC resource folder
|
- name: run DSC that sets reboot_required with defaults
|
||||||
win_file:
|
win_dsc:
|
||||||
path: C:\Program Files\WindowsPowerShell\Modules\xTestDsc\{{item}}\DSCResources\ANSIBLE_xTestResource
|
resource_name: xSetReboot
|
||||||
state: directory
|
KeyParam: value # Just to satisfy the Resource with key validation
|
||||||
with_items:
|
register: set_reboot_defaults
|
||||||
- "1.0.0"
|
|
||||||
- "2.0.0"
|
|
||||||
|
|
||||||
- name: template custom DSC resource files
|
- name: assert run DSC that sets reboot_required with defaults
|
||||||
win_template:
|
assert:
|
||||||
src: '{{item.src}}'
|
that:
|
||||||
dest: C:\Program Files\WindowsPowerShell\Modules\xTestDsc\{{item.version}}\{{item.dest}}
|
- set_reboot_defaults.reboot_required
|
||||||
with_items:
|
|
||||||
- src: ANSIBLE_xTestResource.schema.mof
|
|
||||||
dest: DSCResources\ANSIBLE_xTestResource\ANSIBLE_xTestResource.schema.mof
|
|
||||||
version: "1.0.0"
|
|
||||||
- src: ANSIBLE_xTestResource.psm1
|
|
||||||
dest: DSCResources\ANSIBLE_xTestResource\ANSIBLE_xTestResource.psm1
|
|
||||||
version: "1.0.0"
|
|
||||||
- src: xTestDsc.psd1
|
|
||||||
dest: xTestDsc.psd1
|
|
||||||
version: "1.0.0"
|
|
||||||
- src: ANSIBLE_xTestResource.schema.mof
|
|
||||||
dest: DSCResources\ANSIBLE_xTestResource\ANSIBLE_xTestResource.schema.mof
|
|
||||||
version: "2.0.0"
|
|
||||||
- src: ANSIBLE_xTestResource.psm1
|
|
||||||
dest: DSCResources\ANSIBLE_xTestResource\ANSIBLE_xTestResource.psm1
|
|
||||||
version: "2.0.0"
|
|
||||||
- src: xTestDsc.psd1
|
|
||||||
dest: xTestDsc.psd1
|
|
||||||
version: "2.0.0"
|
|
||||||
|
|
||||||
- name: run custom DSC resource
|
- name: run DSC that sets reboot_required with False
|
||||||
win_dsc: &dsc_params
|
win_dsc:
|
||||||
|
resource_name: xSetReboot
|
||||||
|
KeyParam: value
|
||||||
|
Value: no
|
||||||
|
register: set_reboot_false
|
||||||
|
|
||||||
|
- name: assert run DSC that sets reboot_required with False
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not set_reboot_false.reboot_required
|
||||||
|
|
||||||
|
- name: run DSC that sets reboot_required with True
|
||||||
|
win_dsc:
|
||||||
|
resource_name: xSetReboot
|
||||||
|
KeyParam: value
|
||||||
|
Value: yes
|
||||||
|
register: set_reboot_true
|
||||||
|
|
||||||
|
- name: assert run DSC that sets reboot_required with True
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- set_reboot_true.reboot_required
|
||||||
|
|
||||||
|
- name: test DSC with all types
|
||||||
|
win_dsc:
|
||||||
resource_name: xTestResource
|
resource_name: xTestResource
|
||||||
Path: '{{test_win_dsc_folder}}\custom-output.txt'
|
Path: '{{ remote_tmp_dir }}\test-types.json'
|
||||||
Ensure: Present
|
Ensure: Present
|
||||||
StringParam: string param
|
StringParam: string param
|
||||||
UInt32Param: 1000
|
|
||||||
UInt64Param: 1000000
|
|
||||||
StringArrayParam:
|
StringArrayParam:
|
||||||
- string 1
|
- string 1
|
||||||
- string 2
|
- string 2
|
||||||
|
Int8Param: 127 # [SByte]::MaxValue
|
||||||
|
Int8ArrayParam:
|
||||||
|
- 127
|
||||||
|
- '127'
|
||||||
|
UInt8Param: 255 # [Byte]::MaxValue
|
||||||
|
UInt8ArrayParam:
|
||||||
|
- 255
|
||||||
|
- '255'
|
||||||
|
Int16Param: 32767 # [Int16]::MaxValue
|
||||||
|
Int16ArrayParam: 32767, 32767
|
||||||
|
UInt16Param: '65535' # [UInt16]::MaxValue
|
||||||
|
UInt16ArrayParam: 65535
|
||||||
|
Int32Param: 2147483647 # [Int32]::MaxValue
|
||||||
|
Int32ArrayParam: '2147483647'
|
||||||
|
UInt32Param: '4294967295' # [UInt32]::MaxValue
|
||||||
UInt32ArrayParam:
|
UInt32ArrayParam:
|
||||||
- 1000
|
- '4294967295'
|
||||||
- 2000
|
- 4294967295
|
||||||
|
Int64Param: 9223372036854775807 # [Int64]::MaxValue
|
||||||
|
Int64ArrayParam:
|
||||||
|
- -9223372036854775808 # [Int64]::MinValue
|
||||||
|
- 9223372036854775807
|
||||||
|
UInt64Param: 18446744073709551615 # [UInt64]::MaxValue
|
||||||
UInt64ArrayParam:
|
UInt64ArrayParam:
|
||||||
- 1000000
|
- 0 # [UInt64]::MinValue
|
||||||
- 2000000
|
- 18446744073709551615
|
||||||
BooleanParam: yes
|
BooleanParam: True
|
||||||
PSCredentialParam_username: username
|
BooleanArrayParam:
|
||||||
PSCredentialParam_password: password
|
- True
|
||||||
|
- 'True'
|
||||||
|
- 'true'
|
||||||
|
- 'y'
|
||||||
|
- 'yes'
|
||||||
|
- 1
|
||||||
|
- False
|
||||||
|
- 'False'
|
||||||
|
- 'false'
|
||||||
|
- 'n'
|
||||||
|
- 'no'
|
||||||
|
- 0
|
||||||
|
CharParam: c
|
||||||
|
CharArrayParam:
|
||||||
|
- c
|
||||||
|
- h
|
||||||
|
- a
|
||||||
|
- r
|
||||||
|
SingleParam: 3.402823E+38
|
||||||
|
SingleArrayParam:
|
||||||
|
- '3.402823E+38'
|
||||||
|
- 1.2393494
|
||||||
|
DoubleParam: 1.79769313486232E+300
|
||||||
|
DoubleArrayParam:
|
||||||
|
- '1.79769313486232E+300'
|
||||||
|
- 3.56821831681516
|
||||||
|
DateTimeParam: '2019-02-22T13:57:31.2311892-04:00'
|
||||||
|
DateTimeArrayParam:
|
||||||
|
- '2019-02-22T13:57:31.2311892+00:00'
|
||||||
|
- '2019-02-22T13:57:31.2311892+04:00'
|
||||||
|
PSCredentialParam_username: username1
|
||||||
|
PSCredentialParam_password: password1
|
||||||
|
HashtableParam:
|
||||||
|
key1: string 1
|
||||||
|
key2: ''
|
||||||
|
key3: 1
|
||||||
CimInstanceParam:
|
CimInstanceParam:
|
||||||
StringKey: a
|
KeyValue: a
|
||||||
BooleanKey: yes
|
|
||||||
UInt32Key: 1
|
|
||||||
StringArrayKey:
|
|
||||||
- string 1
|
|
||||||
- string 2
|
|
||||||
CimInstanceArrayParam:
|
CimInstanceArrayParam:
|
||||||
- StringKey: b
|
- KeyValue: b
|
||||||
BooleanKey: no
|
Choice: Choice1
|
||||||
UInt32Key: 2
|
StringValue: string 1
|
||||||
StringArrayKey:
|
IntValue: 1
|
||||||
- string 3
|
StringArrayValue:
|
||||||
- string 4
|
- abc
|
||||||
- StringKey: c
|
- def
|
||||||
BooleanKey: no
|
- KeyValue: c
|
||||||
UInt32Key: 3
|
Choice: Choice2
|
||||||
StringArrayKey:
|
StringValue: string 2
|
||||||
- string 5
|
IntValue: '2'
|
||||||
- string 6
|
StringArrayValue:
|
||||||
register: test_dsc_custom
|
- ghi
|
||||||
|
- jkl
|
||||||
|
NestedCimInstanceParam:
|
||||||
|
KeyValue: key value
|
||||||
|
CimValue:
|
||||||
|
KeyValue: d
|
||||||
|
CimArrayValue:
|
||||||
|
- KeyValue: e
|
||||||
|
Choice: Choice2
|
||||||
|
HashValue:
|
||||||
|
a: a
|
||||||
|
IntValue: '300'
|
||||||
|
register: dsc_types
|
||||||
|
|
||||||
- name: get output of custom DSC resource
|
- name: get result of test DSC with all types
|
||||||
slurp:
|
slurp:
|
||||||
path: '{{test_win_dsc_folder}}\custom-output.txt'
|
path: '{{ remote_tmp_dir }}\test-types.json'
|
||||||
register: test_dsc_custom_output
|
register: dsc_types_raw
|
||||||
|
|
||||||
- name: get expected output of custom DSC resource
|
- name: convert result of test DSC with all types to dict
|
||||||
set_fact:
|
set_fact:
|
||||||
test_dsc_custom_expected: '{{lookup("file", "custom-result-normal.txt")}}'
|
dsc_types_actual: '{{ dsc_types_raw.content | b64decode | from_json }}'
|
||||||
|
|
||||||
- name: assert result of custom DSC resource
|
- name: assert test DSC with all types
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- test_dsc_custom is changed
|
- dsc_types is changed
|
||||||
- test_dsc_custom_output.content|b64decode|strip_newline == test_dsc_custom_expected|strip_newline
|
- dsc_types.module_version == '1.0.1'
|
||||||
- test_dsc_custom.warnings | length == 2
|
- not dsc_types.reboot_required
|
||||||
- "'[[xTestResource]DirectResourceAccess] test warning' in test_dsc_custom.warnings[0]"
|
- dsc_types_actual.Version == '1.0.1'
|
||||||
- "'[[xTestResource]DirectResourceAccess] set warning' in test_dsc_custom.warnings[1]"
|
- dsc_types_actual.Verbose.Value.IsPresent
|
||||||
|
- dsc_types_actual.DefaultParam.Value == 'Default' # ensures that the default is set in the engine if we don't set it outselves
|
||||||
|
- dsc_types_actual.Ensure.Value == 'Present'
|
||||||
|
- dsc_types_actual.Path.Value == remote_tmp_dir + "\\test-types.json"
|
||||||
|
- dsc_types_actual.StringParam.Type == 'System.String'
|
||||||
|
- dsc_types_actual.StringParam.Value == 'string param'
|
||||||
|
- dsc_types_actual.StringArrayParam.Type == 'System.String[]'
|
||||||
|
- dsc_types_actual.StringArrayParam.Value == ['string 1', 'string 2']
|
||||||
|
- dsc_types_actual.Int8Param.Type == 'System.SByte'
|
||||||
|
- dsc_types_actual.Int8Param.Value == 127
|
||||||
|
- dsc_types_actual.Int8ArrayParam.Type == 'System.SByte[]'
|
||||||
|
- dsc_types_actual.Int8ArrayParam.Value == [127, 127]
|
||||||
|
- dsc_types_actual.UInt8Param.Type == 'System.Byte'
|
||||||
|
- dsc_types_actual.UInt8Param.Value == 255
|
||||||
|
- dsc_types_actual.UInt8ArrayParam.Type == 'System.Byte[]'
|
||||||
|
- dsc_types_actual.UInt8ArrayParam.Value == [255, 255]
|
||||||
|
- dsc_types_actual.Int16Param.Type == 'System.Int16'
|
||||||
|
- dsc_types_actual.Int16Param.Value == 32767
|
||||||
|
- dsc_types_actual.Int16ArrayParam.Type == 'System.Int16[]'
|
||||||
|
- dsc_types_actual.Int16ArrayParam.Value == [32767, 32767]
|
||||||
|
- dsc_types_actual.UInt16Param.Type == 'System.UInt16'
|
||||||
|
- dsc_types_actual.UInt16Param.Value == 65535
|
||||||
|
- dsc_types_actual.UInt16ArrayParam.Type == 'System.UInt16[]'
|
||||||
|
- dsc_types_actual.UInt16ArrayParam.Value == [65535]
|
||||||
|
- dsc_types_actual.Int32Param.Type == 'System.Int32'
|
||||||
|
- dsc_types_actual.Int32Param.Value == 2147483647
|
||||||
|
- dsc_types_actual.Int32ArrayParam.Type == 'System.Int32[]'
|
||||||
|
- dsc_types_actual.Int32ArrayParam.Value == [2147483647]
|
||||||
|
- dsc_types_actual.UInt32Param.Type == 'System.UInt32'
|
||||||
|
- dsc_types_actual.UInt32Param.Value == 4294967295
|
||||||
|
- dsc_types_actual.UInt32ArrayParam.Type == 'System.UInt32[]'
|
||||||
|
- dsc_types_actual.UInt32ArrayParam.Value == [4294967295, 4294967295]
|
||||||
|
- dsc_types_actual.Int64Param.Type == 'System.Int64'
|
||||||
|
- dsc_types_actual.Int64Param.Value == 9223372036854775807
|
||||||
|
- dsc_types_actual.Int64ArrayParam.Type == 'System.Int64[]'
|
||||||
|
- dsc_types_actual.Int64ArrayParam.Value == [-9223372036854775808, 9223372036854775807]
|
||||||
|
- dsc_types_actual.UInt64Param.Type == 'System.UInt64'
|
||||||
|
- dsc_types_actual.UInt64Param.Value == 18446744073709551615
|
||||||
|
- dsc_types_actual.UInt64ArrayParam.Type == 'System.UInt64[]'
|
||||||
|
- dsc_types_actual.UInt64ArrayParam.Value == [0, 18446744073709551615]
|
||||||
|
- dsc_types_actual.BooleanParam.Type == 'System.Boolean'
|
||||||
|
- dsc_types_actual.BooleanParam.Value == True
|
||||||
|
- dsc_types_actual.BooleanArrayParam.Type == 'System.Boolean[]'
|
||||||
|
- dsc_types_actual.BooleanArrayParam.Value == [True, True, True, True, True, True, False, False, False, False, False, False]
|
||||||
|
- dsc_types_actual.CharParam.Type == 'System.Char'
|
||||||
|
- dsc_types_actual.CharParam.Value == 'c'
|
||||||
|
- dsc_types_actual.CharArrayParam.Type == 'System.Char[]'
|
||||||
|
- dsc_types_actual.CharArrayParam.Value == ['c', 'h', 'a', 'r']
|
||||||
|
- dsc_types_actual.SingleParam.Type == 'System.Single'
|
||||||
|
- dsc_types_actual.SingleParam.Value|string == '3.402823e+38'
|
||||||
|
- dsc_types_actual.SingleArrayParam.Type == 'System.Single[]'
|
||||||
|
- dsc_types_actual.SingleArrayParam.Value|length == 2
|
||||||
|
- dsc_types_actual.SingleArrayParam.Value[0]|string == '3.402823e+38'
|
||||||
|
- dsc_types_actual.SingleArrayParam.Value[1]|string == '1.23934937'
|
||||||
|
- dsc_types_actual.DoubleParam.Type == 'System.Double'
|
||||||
|
- dsc_types_actual.DoubleParam.Value == '1.79769313486232E+300'
|
||||||
|
- dsc_types_actual.DoubleArrayParam.Type == 'System.Double[]'
|
||||||
|
- dsc_types_actual.DoubleArrayParam.Value|length == 2
|
||||||
|
- dsc_types_actual.DoubleArrayParam.Value[0] == '1.79769313486232E+300'
|
||||||
|
- dsc_types_actual.DoubleArrayParam.Value[1] == '3.56821831681516'
|
||||||
|
- dsc_types_actual.DateTimeParam.Type == 'System.DateTime'
|
||||||
|
- dsc_types_actual.DateTimeParam.Value == '2019-02-22T17:57:31.2311890+00:00'
|
||||||
|
- dsc_types_actual.DateTimeArrayParam.Type == 'System.DateTime[]'
|
||||||
|
- dsc_types_actual.DateTimeArrayParam.Value == ['2019-02-22T13:57:31.2311890+00:00', '2019-02-22T09:57:31.2311890+00:00']
|
||||||
|
- dsc_types_actual.PSCredentialParam.Type == 'System.Management.Automation.PSCredential'
|
||||||
|
- dsc_types_actual.PSCredentialParam.Value.username == 'username1'
|
||||||
|
- dsc_types_actual.PSCredentialParam.Value.password == 'password1'
|
||||||
|
# Hashtable is actually a CimInstance[] of MSFT_KeyValuePairs
|
||||||
|
- dsc_types_actual.HashtableParam.Type == 'Microsoft.Management.Infrastructure.CimInstance[]'
|
||||||
|
- dsc_types_actual.HashtableParam.Value|length == 3
|
||||||
|
# Can't guarantee the order of the keys so just check they are the values they could be
|
||||||
|
- dsc_types_actual.HashtableParam.Value[0].Key in ["key1", "key2", "key3"]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[0].Value in ["string 1", "1", ""]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[0]._cim_instance == 'MSFT_KeyValuePair'
|
||||||
|
- dsc_types_actual.HashtableParam.Value[1].Key in ["key1", "key2", "key3"]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[1].Value in ["string 1", "1", ""]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[1]._cim_instance == 'MSFT_KeyValuePair'
|
||||||
|
- dsc_types_actual.HashtableParam.Value[2].Key in ["key1", "key2", "key3"]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[2].Value in ["string 1", "1", ""]
|
||||||
|
- dsc_types_actual.HashtableParam.Value[2]._cim_instance == 'MSFT_KeyValuePair'
|
||||||
|
- dsc_types_actual.CimInstanceParam.Type == 'Microsoft.Management.Infrastructure.CimInstance'
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value.Choice == None
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value.IntValue == None
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value.KeyValue == 'a'
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value.StringArrayValue == None
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value.StringValue == None
|
||||||
|
- dsc_types_actual.CimInstanceParam.Value._cim_instance == "ANSIBLE_xTestClass"
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Type == 'Microsoft.Management.Infrastructure.CimInstance[]'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value|length == 2
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0].Choice == 'Choice1'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0].IntValue == 1
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0].KeyValue == 'b'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0].StringArrayValue == ['abc', 'def']
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0].StringValue == 'string 1'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[0]._cim_instance == 'ANSIBLE_xTestClass'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1].Choice == 'Choice2'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1].IntValue == 2
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1].KeyValue == 'c'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1].StringArrayValue == ['ghi', 'jkl']
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1].StringValue == 'string 2'
|
||||||
|
- dsc_types_actual.CimInstanceArrayParam.Value[1]._cim_instance == 'ANSIBLE_xTestClass'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Type == 'Microsoft.Management.Infrastructure.CimInstance'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue|length == 1
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0].Choice == 'Choice2'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0].IntValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0].KeyValue == 'e'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0].StringArrayValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0].StringValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimArrayValue[0]._cim_instance == 'ANSIBLE_xTestClass'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue.Choice == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue.IntValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue.KeyValue == 'd'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue.StringArrayValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue.StringValue == None
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.CimValue._cim_instance == 'ANSIBLE_xTestClass'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.HashValue|length == 1
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.HashValue[0].Key == 'a'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.HashValue[0].Value == 'a'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.HashValue[0]._cim_instance == 'MSFT_KeyValuePair'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.IntValue == 300
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value.KeyValue == 'key value'
|
||||||
|
- dsc_types_actual.NestedCimInstanceParam.Value._cim_instance == 'ANSIBLE_xNestedClass'
|
||||||
|
|
||||||
- name: run custom DSC resource with version
|
- name: test DSC with all types older version
|
||||||
win_dsc:
|
win_dsc:
|
||||||
<<: *dsc_params
|
resource_name: xTestResource
|
||||||
module_version: '1.0.0'
|
module_version: 1.0.0
|
||||||
register: test_dsc_custom_version
|
Path: '{{ remote_tmp_dir }}\test-types.json'
|
||||||
|
Ensure: Absent
|
||||||
|
StringParam: string param old
|
||||||
|
CimInstanceArrayParam:
|
||||||
|
- Key: old key
|
||||||
|
StringValue: string old 1
|
||||||
|
IntValue: 0
|
||||||
|
StringArrayValue:
|
||||||
|
- zyx
|
||||||
|
- wvu
|
||||||
|
register: dsc_types_old
|
||||||
|
|
||||||
- name: get output of custom DSC resource with version
|
- name: get result of test DSC with all types older version
|
||||||
slurp:
|
slurp:
|
||||||
path: '{{test_win_dsc_folder}}\custom-output.txt'
|
path: '{{ remote_tmp_dir }}\test-types.json'
|
||||||
register: test_dsc_custom_output_version
|
register: dsc_types_old_raw
|
||||||
|
|
||||||
- name: get expected output of custom DSC resource with version
|
- name: convert result of test DSC with all types to dict
|
||||||
set_fact:
|
set_fact:
|
||||||
test_dsc_custom_expected_version: '{{lookup("file", "custom-result-versioned.txt")}}'
|
dsc_types_old_actual: '{{ dsc_types_old_raw.content | b64decode | from_json }}'
|
||||||
|
|
||||||
- name: assert result of custom DSC resource with version
|
- name: assert test DSC with all types older version
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- test_dsc_custom is changed
|
- dsc_types_old is changed
|
||||||
- test_dsc_custom_output_version.content|b64decode|strip_newline == test_dsc_custom_expected_version|strip_newline
|
- dsc_types_old.module_version == '1.0.0'
|
||||||
|
- not dsc_types_old.reboot_required
|
||||||
|
- dsc_types_old_actual.Version == '1.0.0'
|
||||||
|
- dsc_types_old_actual.Verbose.Value.IsPresent
|
||||||
|
- dsc_types_old_actual.DefaultParam.Value == 'Default'
|
||||||
|
- dsc_types_old_actual.Ensure.Value == 'Absent'
|
||||||
|
- dsc_types_old_actual.Path.Value == remote_tmp_dir + "\\test-types.json"
|
||||||
|
- dsc_types_old_actual.StringParam.Type == 'System.String'
|
||||||
|
- dsc_types_old_actual.StringParam.Value == 'string param old'
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Type == 'Microsoft.Management.Infrastructure.CimInstance[]'
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value|length == 1
|
||||||
|
- not dsc_types_old_actual.CimInstanceArrayParam.Value[0].Choice is defined # 1.0.0 does not have a Choice option
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value[0].IntValue == 0
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value[0].Key == 'old key'
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value[0].StringArrayValue == ['zyx', 'wvu']
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value[0].StringValue == 'string old 1'
|
||||||
|
- dsc_types_old_actual.CimInstanceArrayParam.Value[0]._cim_instance == 'ANSIBLE_xTestClass'
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
#Requires -Version 5.0 -Modules CimCmdlets
|
|
||||||
|
|
||||||
Function Get-TargetResource
|
|
||||||
{
|
|
||||||
[CmdletBinding()]
|
|
||||||
[OutputType([Hashtable])]
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateSet("Present", "Absent")]
|
|
||||||
[String]
|
|
||||||
$Ensure = "Present",
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[String]
|
|
||||||
$Path
|
|
||||||
)
|
|
||||||
return @{
|
|
||||||
Ensure = $Ensure
|
|
||||||
Path = $Path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Function Set-TargetResource
|
|
||||||
{
|
|
||||||
[CmdletBinding()]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateSet("Present", "Absent")]
|
|
||||||
[String]
|
|
||||||
$Ensure = "Present",
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[String]
|
|
||||||
$Path,
|
|
||||||
|
|
||||||
[String]
|
|
||||||
$StringParam,
|
|
||||||
|
|
||||||
[UInt32]
|
|
||||||
$UInt32Param,
|
|
||||||
|
|
||||||
[UInt64]
|
|
||||||
$UInt64Param,
|
|
||||||
|
|
||||||
[String[]]
|
|
||||||
$StringArrayParam,
|
|
||||||
|
|
||||||
[UInt32[]]
|
|
||||||
$UInt32ArrayParam,
|
|
||||||
|
|
||||||
[UInt64[]]
|
|
||||||
$UInt64ArrayParam,
|
|
||||||
|
|
||||||
[Boolean]
|
|
||||||
$BooleanParam,
|
|
||||||
|
|
||||||
[PSCredential]
|
|
||||||
$PSCredentialParam,
|
|
||||||
|
|
||||||
[Microsoft.Management.Infrastructure.CimInstance]
|
|
||||||
$CimInstanceParam,
|
|
||||||
|
|
||||||
[Microsoft.Management.Infrastructure.CimInstance[]]
|
|
||||||
$CimInstanceArrayParam
|
|
||||||
)
|
|
||||||
|
|
||||||
$file_contents = @"
|
|
||||||
xTestResource Version: {{item.version}}
|
|
||||||
|
|
||||||
Ensure:
|
|
||||||
Type: $($Ensure.GetType().FullName)
|
|
||||||
Value: $($Ensure.ToString())
|
|
||||||
|
|
||||||
StringParam:
|
|
||||||
Type: $($StringParam.GetType().FullName)
|
|
||||||
Value: $($StringParam)
|
|
||||||
|
|
||||||
UInt32Param:
|
|
||||||
Type: $($UInt32Param.GetType().FullName)
|
|
||||||
Value: $($UInt32Param.ToString())
|
|
||||||
|
|
||||||
UInt64Param:
|
|
||||||
Type: $($UInt64Param.GetType().FullName)
|
|
||||||
Value: $($UInt64Param.ToString())
|
|
||||||
|
|
||||||
StringArrayParam:
|
|
||||||
Type: $($StringArrayParam.GetType().FullName)
|
|
||||||
Value: [ "$($StringArrayParam -join '", "')" ]
|
|
||||||
|
|
||||||
UInt32ArrayParam:
|
|
||||||
Type: $($UInt32ArrayParam.GetType().FullName)
|
|
||||||
Value: [ $($UInt32ArrayParam -join ', ') ]
|
|
||||||
|
|
||||||
UInt64ArrayParam:
|
|
||||||
Type: $($UInt64ArrayParam.GetType().FullName)
|
|
||||||
Value: [ $($UInt64ArrayParam -join ', ') ]
|
|
||||||
|
|
||||||
BooleanParam:
|
|
||||||
Type: $($BooleanParam.GetType().FullName)
|
|
||||||
Value: $($BooleanParam.ToString())
|
|
||||||
|
|
||||||
PSCredentialParam:
|
|
||||||
Type: $($PSCredentialParam.GetType().FullName)
|
|
||||||
Username: $($PSCredentialParam.GetNetworkCredential().Username)
|
|
||||||
Password: $($PSCredentialParam.GetNetworkCredential().Password)
|
|
||||||
|
|
||||||
CimInstanceParam:
|
|
||||||
Type: $($CimInstanceParam.GetType().FullName)
|
|
||||||
|
|
||||||
CimInstanceArrayParam:
|
|
||||||
Type: $($CimInstanceArrayParam.GetType().FullName)
|
|
||||||
"@
|
|
||||||
if (Test-Path -Path $Path)
|
|
||||||
{
|
|
||||||
Remove-Item -Path $Path -Force > $null
|
|
||||||
}
|
|
||||||
New-Item -Path $Path -ItemType File > $null
|
|
||||||
Set-Content -Path $Path -Value $file_contents > $null
|
|
||||||
Write-Warning -Message "set warning"
|
|
||||||
}
|
|
||||||
|
|
||||||
Function Test-TargetResource
|
|
||||||
{
|
|
||||||
[CmdletBinding()]
|
|
||||||
[OutputType([Boolean])]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateSet("Present", "Absent")]
|
|
||||||
[String]
|
|
||||||
$Ensure = "Present",
|
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[String]
|
|
||||||
$Path,
|
|
||||||
|
|
||||||
[String]
|
|
||||||
$StringParam,
|
|
||||||
|
|
||||||
[UInt32]
|
|
||||||
$UInt32Param,
|
|
||||||
|
|
||||||
[UInt64]
|
|
||||||
$UInt64Param,
|
|
||||||
|
|
||||||
[String[]]
|
|
||||||
$StringArrayParam,
|
|
||||||
|
|
||||||
[UInt32[]]
|
|
||||||
$UInt32ArrayParam,
|
|
||||||
|
|
||||||
[UInt64[]]
|
|
||||||
$UInt64ArrayParam,
|
|
||||||
|
|
||||||
[Boolean]
|
|
||||||
$BooleanParam,
|
|
||||||
|
|
||||||
[PSCredential]
|
|
||||||
$PSCredentialParam,
|
|
||||||
|
|
||||||
[Microsoft.Management.Infrastructure.CimInstance]
|
|
||||||
$CimInstanceParam,
|
|
||||||
|
|
||||||
[Microsoft.Management.Infrastructure.CimInstance[]]
|
|
||||||
$CimInstanceArrayParam
|
|
||||||
)
|
|
||||||
Write-Warning -Message "test warning"
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
Export-ModuleMember -Function *-TargetResource
|
|
|
@ -1,25 +0,0 @@
|
||||||
[ClassVersion("{{item.version}}")]
|
|
||||||
class ANSIBLE_xTestClass
|
|
||||||
{
|
|
||||||
[Write] String StringKey;
|
|
||||||
[Write] Boolean BooleanKey;
|
|
||||||
[Write] UInt32 UInt32Key;
|
|
||||||
[Write] String StringArrayKey[];
|
|
||||||
};
|
|
||||||
|
|
||||||
[ClassVersion("{{item.version}}"), FriendlyName("xTestResource")]
|
|
||||||
class ANSIBLE_xTestResource : OMI_BaseResource
|
|
||||||
{
|
|
||||||
[Key] String Path;
|
|
||||||
[Required, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] String Ensure;
|
|
||||||
[Write] String StringParam;
|
|
||||||
[Write] UInt32 UInt32Param;
|
|
||||||
[Write] UInt64 UInt64Param;
|
|
||||||
[Write] String StringArrayParam[];
|
|
||||||
[Write] UInt32 UInt32ArrayParam[];
|
|
||||||
[Write] UInt64 UInt64ArrayParam[];
|
|
||||||
[Write] Boolean BooleanParam;
|
|
||||||
[Write, EmbeddedInstance("MSFT_Credential")] String PSCredentialParam;
|
|
||||||
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimInstanceParam;
|
|
||||||
[Write, EmbeddedInstance("ANSIBLE_xTestClass")] String CimInstanceArrayParam[];
|
|
||||||
};
|
|
|
@ -30,9 +30,7 @@ lib/ansible/modules/windows/win_domain_membership.ps1 PSAvoidGlobalVars
|
||||||
lib/ansible/modules/windows/win_domain_membership.ps1 PSAvoidUsingWMICmdlet
|
lib/ansible/modules/windows/win_domain_membership.ps1 PSAvoidUsingWMICmdlet
|
||||||
lib/ansible/modules/windows/win_domain_membership.ps1 PSUseApprovedVerbs
|
lib/ansible/modules/windows/win_domain_membership.ps1 PSUseApprovedVerbs
|
||||||
lib/ansible/modules/windows/win_domain_membership.ps1 PSUseDeclaredVarsMoreThanAssignments
|
lib/ansible/modules/windows/win_domain_membership.ps1 PSUseDeclaredVarsMoreThanAssignments
|
||||||
lib/ansible/modules/windows/win_dsc.ps1 PSAvoidUsingCmdletAliases
|
|
||||||
lib/ansible/modules/windows/win_dsc.ps1 PSAvoidUsingEmptyCatchBlock
|
lib/ansible/modules/windows/win_dsc.ps1 PSAvoidUsingEmptyCatchBlock
|
||||||
lib/ansible/modules/windows/win_dsc.ps1 PSUseApprovedVerbs
|
|
||||||
lib/ansible/modules/windows/win_eventlog.ps1 PSUseDeclaredVarsMoreThanAssignments
|
lib/ansible/modules/windows/win_eventlog.ps1 PSUseDeclaredVarsMoreThanAssignments
|
||||||
lib/ansible/modules/windows/win_find.ps1 PSAvoidUsingEmptyCatchBlock
|
lib/ansible/modules/windows/win_find.ps1 PSAvoidUsingEmptyCatchBlock
|
||||||
lib/ansible/modules/windows/win_find.ps1 PSAvoidUsingWMICmdlet
|
lib/ansible/modules/windows/win_find.ps1 PSAvoidUsingWMICmdlet
|
||||||
|
@ -72,7 +70,6 @@ lib/ansible/modules/windows/win_user.ps1 PSAvoidUsingCmdletAliases
|
||||||
lib/ansible/modules/windows/win_wait_for.ps1 PSAvoidUsingEmptyCatchBlock
|
lib/ansible/modules/windows/win_wait_for.ps1 PSAvoidUsingEmptyCatchBlock
|
||||||
lib/ansible/modules/windows/win_webpicmd.ps1 PSAvoidUsingInvokeExpression
|
lib/ansible/modules/windows/win_webpicmd.ps1 PSAvoidUsingInvokeExpression
|
||||||
test/integration/targets/win_audit_rule/library/test_get_audit_rule.ps1 PSAvoidUsingCmdletAliases
|
test/integration/targets/win_audit_rule/library/test_get_audit_rule.ps1 PSAvoidUsingCmdletAliases
|
||||||
test/integration/targets/win_dsc/templates/ANSIBLE_xTestResource.psm1 PSAvoidDefaultValueForMandatoryParameter
|
|
||||||
test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1 PSUseApprovedVerbs
|
test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1 PSUseApprovedVerbs
|
||||||
test/integration/targets/win_module_utils/library/argv_parser_test.ps1 PSUseApprovedVerbs
|
test/integration/targets/win_module_utils/library/argv_parser_test.ps1 PSUseApprovedVerbs
|
||||||
test/integration/targets/win_module_utils/library/camel_conversion_test.ps1 PSUseDeclaredVarsMoreThanAssignments
|
test/integration/targets/win_module_utils/library/camel_conversion_test.ps1 PSUseDeclaredVarsMoreThanAssignments
|
||||||
|
|
|
@ -1 +1,6 @@
|
||||||
test/integration/targets/win_ping/library/win_ping_syntax_error.ps1
|
test/integration/targets/win_ping/library/win_ping_syntax_error.ps1
|
||||||
|
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xSetReboot/ANSIBLE_xSetReboot.psm1
|
||||||
|
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/xTestDsc.psd1
|
||||||
|
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1
|
||||||
|
test/integration/targets/win_dsc/files/xTestDsc/1.0.1/xTestDsc.psd1
|
||||||
|
test/integration/targets/win_dsc/files/xTestDsc/1.0.1/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1
|
||||||
|
|
Loading…
Reference in a new issue