diff --git a/lib/ansible/modules/windows/win_iis_webapppool.ps1 b/lib/ansible/modules/windows/win_iis_webapppool.ps1 index b4f0cd4948..c61c81be2a 100644 --- a/lib/ansible/modules/windows/win_iis_webapppool.ps1 +++ b/lib/ansible/modules/windows/win_iis_webapppool.ps1 @@ -17,124 +17,242 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . - # WANT_JSON # POWERSHELL_COMMON -$params = Parse-Args $args -# Name parameter -$name = Get-AnsibleParam -obj $params -name "name" -type "string" -failifempty $true +$ErrorActionPreference = 'Stop' +$params = Parse-Args -arguments $args -supports_check_mode $true +$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false -# State parameter -$state = Get-AnsibleParam -obj $params -name "state" -default "present" -validateSet "started","restarted","stopped","absent" +$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true +$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateSet "started","restarted","stopped","absent","present" +$result = @{ + changed = $false + attributes = @{} + info = @{ + name = $name + state = $state + attributes = @{} + cpu = @{} + failure = @{} + processModel = @{} + recycling = @{ + periodicRestart = @{} + } + } +} -# Attributes parameter - Pipe separated list of attributes where -# keys and values are separated by comma (paramA:valyeA|paramB:valueB) -$attributes = @{}; -$attrs = Get-AnsibleParam -obj $params -name "attributes" -type "string" -failifempty $false -If ($attrs) { - $attrs -split '\|' | foreach { - $key, $value = $_ -split "\:" - $attributes.Add($key, $value) - } +# Stores the free form attributes for the module +$attributes = @{} +$input_attributes = Get-AnsibleParam -obj $params -name "attributes" +if ($input_attributes) { + if ($input_attributes -is [System.Collections.Hashtable]) { + # Uses dict style parameters, newer and recommended style + $attributes = $input_attributes + } else { + # Uses older style of separating with | per key pair and : for key:value (paramA:valueA|paramB:valueB) + Add-DeprecationWarning -obj $result -message "Using a string for the attributes parameter is deprecated, please use a dict instead" -version 2.6 + $input_attributes -split '\|' | ForEach-Object { + $key, $value = $_ -split "\:" + $attributes.$key = $value + } + } +} +$result.attributes = $attributes + +Function Get-DotNetClassForAttribute($attribute_parent) { + switch ($attribute_parent) { + "attributes" { [Microsoft.Web.Administration.ApplicationPool] } + "cpu" { [Microsoft.Web.Administration.ApplicationPoolCpu] } + "failure" { [Microsoft.Web.Administration.ApplicationPoolFailure] } + "processModel" { [Microsoft.Web.Administration.ApplicationPoolProcessModel] } + "recycling" { [Microsoft.Web.Administration.ApplicationPoolRecycling] } + default { [Microsoft.Web.Administration.ApplicationPool] } + } +} + +Function Convert-ToPropertyValue($pool, $attribute_key, $attribute_value) { + # Will convert the new value to the enum value expected and cast accordingly to the type + if ([bool]($attribute_value.PSobject.Properties -match "Value")) { + $attribute_value = $attribute_value.Value + } + $attribute_key_split = $attribute_key -split "\." + if ($attribute_key_split.Length -eq 1) { + $attribute_parent = "attributes" + $attribute_child = $attribute_key + $attribute_meta = $pool.Attributes | Where-Object { $_.Name -eq $attribute_child } + } elseif ($attribute_key_split.Length -eq 2) { + $attribute_parent = $attribute_key_split[0] + $attribute_child = $attribute_key_split[1] + $attribute_meta = $pool.$attribute_parent.Attributes | Where-Object { $_.Name -eq $attribute_child } + } + + if ($attribute_meta) { + $type = $attribute_meta.Schema.Type + $value = $attribute_value + if ($type -eq "enum") { + # Attempt to convert the value from human friendly to enum value - use existing value if we fail + $dot_net_class = Get-DotNetClassForAttribute -attribute_parent $attribute_parent + $enum_attribute_name = $attribute_child.Substring(0,1).ToUpper() + $attribute_child.Substring(1) + $enum = $dot_net_class.GetProperty($enum_attribute_name).PropertyType.FullName + if ($enum) { + $enum_values = [Enum]::GetValues($enum) + foreach ($enum_value in $enum_values) { + if ($attribute_value.GetType() -is $enum_value.GetType()) { + if ($enum_value -eq $attribute_value) { + $value = $enum_value + break + } + } else { + if ([System.String]$enum_value -eq [System.String]$attribute_value) { + $value = $enum_value + break + } + } + } + } + } + # Try and cast the variable using the chosen type, revert to the default if it fails + Set-Variable -Name casted_value -Value ($value -as ([type] $attribute_meta.TypeName)) + if ($casted_value -eq $null) { + $value + } else { + $casted_value + } + } else { + $attribute_value + } } # Ensure WebAdministration module is loaded -if ((Get-Module "WebAdministration" -ErrorAction SilentlyContinue) -eq $NULL){ - Import-Module WebAdministration - $web_admin_dll_path = Join-Path $env:SystemRoot system32\inetsrv\Microsoft.Web.Administration.dll - Add-Type -Path $web_admin_dll_path - $t = [Type]"Microsoft.Web.Administration.ApplicationPool" +if ((Get-Module -Name "WebAdministration" -ErrorAction SilentlyContinue) -eq $null) { + Import-Module WebAdministration + $web_admin_dll_path = Join-Path $env:SystemRoot system32\inetsrv\Microsoft.Web.Administration.dll + Add-Type -Path $web_admin_dll_path } -# Result -$result = @{ - changed = $FALSE -# attributes = $attributes +$pool = Get-Item -Path IIS:\AppPools\$name -ErrorAction SilentlyContinue +if ($state -eq "absent") { + # Remove pool if present + if ($pool) { + try { + Remove-WebAppPool -Name $name -WhatIf:$check_mode + } catch { + Fail-Json $result "Failed to remove Web App pool $($name): $($_.Exception.Message)" + } + $result.changed = $true + } +} else { + # Add pool if absent + if (-not $pool) { + if (-not $check_mode) { + try { + New-WebAppPool -Name $name + } catch { + Fail-Json $result "Failed to create new Web App Pool $($name): $($_.Exception.Message)" + } + } + $result.changed = $true + # If in check mode this pool won't actually exists so skip it + if (-not $check_mode) { + $pool = Get-Item -Path IIS:\AppPools\$name + } + } + + # Modify pool based on parameters + foreach ($attribute in $attributes.GetEnumerator()) { + $attribute_key = $attribute.Name + $new_raw_value = $attribute.Value + $new_value = Convert-ToPropertyValue -pool $pool -attribute_key $attribute_key -attribute_value $new_raw_value + + $current_raw_value = Get-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -ErrorAction SilentlyContinue + $current_value = Convert-ToPropertyValue -pool $pool -attribute_key $attribute_key -attribute_value $current_raw_value + + # Cannot use ($current_value -or (..)) as that will fire if $current_value is 0/$null/"" when we only want $null + if (($current_value -eq $null) -or ($current_value -ne $new_value)) { + try { + Set-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -Value $new_value -WhatIf:$check_mode + } catch { + Fail-Json $result "Failed to set attribute to Web App Pool $name. Attribute: $attribute_key, Value: $new_value, Exception: $($_.Exception.Message)" + } + $result.changed = $true + } + } + + # Set the state of the pool + if (($state -eq "stopped") -and ($pool.State -eq "Started")) { + if (-not $check_mode) { + try { + Stop-WebAppPool -Name $name + } catch { + Fail-Json $result "Failed to stop Web App Pool $($name): $($_.Exception.Message)" + } + } + $result.changed = $true + } + + + if ($pool.State -eq "Stopped") { + if ($state -eq "started" -or $state -eq "restarted") { + if (-not $check_mode) { + try { + Start-WebAppPool -Name $name + } catch { + Fail-Json $result "Failed to start Web App Pool $($name): $($_.Exception.Message)" + } + } + $result.changed = $true + } + } else { + if ($state -eq "stopped") { + if (-not $check_mode) { + try { + Stop-WebAppPool -Name $name + } catch { + Fail-Json $result "Failed to stop Web App Pool $($name): $($_.Exception.Message)" + } + } + $result.changed = $true + } elseif ($state -eq "restarted") { + if (-not $check_mode) { + try { + Restart-WebAppPool -Name $name + } catch { + Fail-Json $result "Failed to restart Web App Pool $($name): $($_.Exception.Message)" + } + } + $result.changed = $true + } + } } -$result.attributes = $attributes +# Get all the current attributes for the pool +$pool = Get-Item -Path IIS:\AppPools\$name -ErrorAction SilentlyContinue +$elements = @("attributes", "cpu", "failure", "processModel", "recycling") -# Get pool -$pool = Get-Item IIS:\AppPools\$name - -try { - # Add - if (-not $pool -and $state -in ('started', 'stopped', 'restarted')) { - New-WebAppPool $name - $result.changed = $TRUE - } - - # Remove - if ($pool -and $state -eq 'absent') { - Remove-WebAppPool $name - $result.changed = $TRUE - } - - $pool = Get-Item IIS:\AppPools\$name - if($pool) { - # Set properties - $attributes.GetEnumerator() | foreach { - $newParameter = $_ - $currentParameter = Get-ItemProperty ("IIS:\AppPools\" + $name) $newParameter.Key - $currentParamVal = "" - try { - $currentParamVal = $currentParameter - } catch { - $currentParamVal = $currentParameter.Value - } - if(-not $currentParamVal -or ($currentParamVal -as [String]) -ne $newParameter.Value) { - Set-ItemProperty ("IIS:\AppPools\" + $name) $newParameter.Key $newParameter.Value - $result.changed = $TRUE - } +foreach ($element in $elements) { + if ($element -eq "attributes") { + $attribute_collection = $pool.Attributes + $attribute_parent = $pool + } else { + $attribute_collection = $pool.$element.Attributes + $attribute_parent = $pool.$element } - # Set run state - if (($state -eq 'stopped') -and ($pool.State -eq 'Started')) { - Stop-WebAppPool -Name $name -ErrorAction Stop - $result.changed = $TRUE + foreach ($attribute in $attribute_collection) { + $attribute_name = $attribute.Name + $attribute_value = $attribute_parent.$attribute_name + + $result.info.$element.Add($attribute_name, $attribute_value) } - if (($state -eq 'started') -and ($pool.State -eq 'Stopped')) { - Start-WebAppPool -Name $name -ErrorAction Stop - $result.changed = $TRUE - } - if ($state -eq 'restarted') { - switch ($pool.State) - { - 'Stopped' { Start-WebAppPool -Name $name -ErrorAction Stop } - default { Restart-WebAppPool -Name $name -ErrorAction Stop } - } - $result.changed = $TRUE - } - } -} catch { - Fail-Json $result $_.Exception.Message } -# Result -$pool = Get-Item IIS:\AppPools\$name -if ($pool) -{ - $result.info = @{ - name = $pool.Name - state = $pool.State - attributes = @{} - }; - - $pool.Attributes | ForEach { - # lookup name if enum - if ($_.Schema.Type -eq 'enum') { - $propertyName = $_.Name.Substring(0,1).ToUpper() + $_.Name.Substring(1) - $enum = [Microsoft.Web.Administration.ApplicationPool].GetProperty($propertyName).PropertyType.FullName - $enum_names = [Enum]::GetNames($enum) - $result.info.attributes.Add($_.Name, $enum_names[$_.Value]) - } else { - $result.info.attributes.Add($_.Name, $_.Value); - } - } - +# Manually get the periodicRestart attributes in recycling +foreach ($attribute in $pool.recycling.periodicRestart.Attributes) { + $attribute_name = $attribute.Name + $attribute_value = $pool.recycling.periodicRestart.$attribute_name + $result.info.recycling.periodicRestart.Add($attribute_name, $attribute_value) } Exit-Json $result - diff --git a/lib/ansible/modules/windows/win_iis_webapppool.py b/lib/ansible/modules/windows/win_iis_webapppool.py index f407b468ae..3f8f4f6050 100644 --- a/lib/ansible/modules/windows/win_iis_webapppool.py +++ b/lib/ansible/modules/windows/win_iis_webapppool.py @@ -27,125 +27,208 @@ DOCUMENTATION = r''' --- module: win_iis_webapppool version_added: "2.0" -short_description: Configures an IIS Web Application Pool. +short_description: configures an IIS Web Application Pool description: - - Creates, Removes and configures an IIS Web Application Pool + - Creates, removes and configures an IIS Web Application Pool. options: + attributes: + description: + - As of Ansible 2.4, this field can take in dict entries to set the + application pool attributes. + - These attributes are based on the naming standard at + U(https://www.iis.net/configreference/system.applicationhost/applicationpools/add#005), + see the examples section for more details on how to set this. + - You can also set the attributes of child elements like cpu and + processModel, see the examples to see how it is done. + - While you can use the numeric values for enums it is recommended to use + the enum name itself, e.g. use SpecificUser instead of 3 for + processModel.identityType. + - managedPipelineMode may be either "Integrated" or "Classic". + - startMode may be either "OnDemand" or "AlwaysRunning". + - Use C(state) module parameter to modify the state of the app pool. + - When trying to set 'processModel.password' and you receive a 'Value + does fall within the expected range' error, you have a corrupted + keystore. Please follow + U(http://structuredsight.com/2014/10/26/im-out-of-range-youre-out-of-range/) + to help fix your host. + - DEPRECATED As of Ansible 2.4 this field should be set using a dict + form, in older versions of Ansible this field used to be a string. + - This string has attributes that are separated by a pipe '|' and + attribute name/values by colon ':' + Ex. "startMode:OnDemand|managedPipelineMode:Classic". name: description: - - Name of application pool + - Name of the application pool. required: true - default: null - aliases: [] state: - description: - - State of the binding choices: + - present - absent - stopped - started - restarted - required: false - default: null - attributes: + default: present description: - - Application Pool attributes from string where attributes are separated by a pipe and attribute name/values by colon Ex. "foo:1|bar:2". - - The following attributes may only have the following names. - - managedPipelineMode may be either "Integrated" or "Classic". - - startMode may be either "OnDemand" or "AlwaysRunning". - - state may be one of "Starting", "Started", "Stopping", "Stopped", "Unknown". - Use the C(state) module parameter to modify, states shown are reflect the possible runtime values. - required: false - default: null -author: Henrik Wallström + - The state of the application pool. + - If C(present) will ensure the app pool is configured and exists. + - If C(absent) will ensure the app pool is removed. + - If C(stopped) will ensure the app pool exists and is stopped. + - If C(started) will ensure the app pool exists and is started. + - If C(restarted) will ensure the app pool exists and will restart, this + is never idempotent. +author: + - "Henrik Wallström (@henrikwallstrom)" + - "Jordan Borean (@jborean93)" ''' EXAMPLES = r''' - name: return information about an existing application pool win_iis_webapppool: name: DefaultAppPool + state: present -- name: Create a new application pool in 'Started' state +- name: create a new application pool in 'Started' state win_iis_webapppool: name: AppPool state: started -- name: Stop an application pool +- name: stop an application pool win_iis_webapppool: name: AppPool state: stopped -- name: Restart an application pool +- name: restart an application pool (non-idempotent) win_iis_webapppool: name: AppPool state: restart -- name: Changes application pool attributes without touching state +- name: change application pool attributes using new dict style + win_iis_webapppool: + name: AppPool + attributes: + managedRuntimeVersion: v4.0 + autoStart: false + +# Note this format style has been deprecated, please use the newer dict style instead +- name: change application pool attributes using older string style win_iis_webapppool: name: AppPool attributes: 'managedRuntimeVersion:v4.0|autoStart:false' -- name: Creates an application pool and sets attributes +# This is the preferred style to use when setting attributes +- name: creates an application pool, sets attributes and starts it win_iis_webapppool: name: AnotherAppPool state: started - attributes: 'managedRuntimeVersion:v4.0|autoStart:false' + attributes: + managedRuntimeVersion: v4.0 + autoStart: false -# Playbook example ---- - -- name: App Pool with .NET 4.0 +# In the below example we are setting attributes in child element processModel +# https://www.iis.net/configreference/system.applicationhost/applicationpools/add/processmodel +- name: manage child element and set identity of application pool win_iis_webapppool: - name: 'AppPool' + name: IdentitiyAppPool state: started - attributes: managedRuntimeVersion:v4.0 - register: webapppool + attributes: + managedPipelineMode: Classic + processModel.identityType: SpecificUser + processModel.username: '{{ansible_user}}' + processModel.password: '{{ansible_password}}' + processModel.loadUserProfile: True +- name: manage a timespan attribute + win_iis_webapppool: + name: TimespanAppPool + state: started + attributes: + # Timespan with full string "day:hour:minute:second.millisecond" + recycling.periodicRestart.time: "00:00:05:00.000000" + # Shortened timespan "hour:minute:second" + processModel.pingResponseTime: "00:03:00" ''' -RETURN = ''' +RETURN = r''' attributes: - description: - - Application Pool attributes from that were processed by this module invocation. + description: Application Pool attributes that were set and processed by this + module invocation. returned: success type: dictionary sample: - "enable32BitAppOnWin64": "true" - "managedRuntimeVersion": "v4.0" - "managedPipelineMode": "Classic" + enable32BitAppOnWin64: "true" + managedRuntimeVersion: "v4.0" + managedPipelineMode: "Classic" info: - description: Information on current state of the Application Pool + description: Information on current state of the Application Pool. See + https://www.iis.net/configreference/system.applicationhost/applicationpools/add#005 + for the full list of return attributes based on your IIS version. returned: success type: complex sample: contains: attributes: - description: key value pairs showing the current Application Pool attributes + description: Key value pairs showing the current Application Pool attributes. returned: success type: dictionary sample: - "autoStart": true - "managedRuntimeLoader": "webengine4.dll" - "managedPipelineMode": "Classic" - "name": "DefaultAppPool" - "CLRConfigFile": "" - "passAnonymousToken": true - "applicationPoolSid": "S-1-5-82-1352790163-598702362-1775843902-1923651883-1762956711" - "queueLength": 1000 - "managedRuntimeVersion": "v4.0" - "state": "Started" - "enableConfigurationOverride": true - "startMode": "OnDemand" - "enable32BitAppOnWin64": true + autoStart: true + managedRuntimeLoader: "webengine4.dll" + managedPipelineMode: "Classic" + name: "DefaultAppPool" + CLRConfigFile: "" + passAnonymousToken: true + applicationPoolSid: "S-1-5-82-1352790163-598702362-1775843902-1923651883-1762956711" + queueLength: 1000 + managedRuntimeVersion: "v4.0" + state: "Started" + enableConfigurationOverride: true + startMode: "OnDemand" + enable32BitAppOnWin64: true + cpu: + description: Key value pairs showing the current Application Pool cpu attributes. + returned: success + type: dictionary + sample: + action: "NoAction" + limit: 0 + resetInterval: + Days: 0 + Hours: 0 + failure: + description: Key value pairs showing the current Application Pool failure attributes. + returned: success + type: dictionary + sample: + autoShutdownExe: "" + orphanActionExe: "" + rapidFailProtextionInterval: + Days: 0 + Hours: 0 name: - description: - - Name of Application Pool that was processed by this module invocation. + description: Name of Application Pool that was processed by this module invocation. returned: success type: string sample: "DefaultAppPool" + processModel: + description: Key value pairs showing the current Application Pool processModel attributes. + returned: success + type: dictionary + sample: + identityType: "ApplicationPoolIdentity" + logonType: "LogonBatch" + pingInterval: + Days: 0 + Hours: 0 + recycling: + description: Key value pairs showing the current Application Pool recycling attributes. + returned: success + type: dictionary + sample: + disallowOverlappingRotation: false + disallowRotationOnConfigChange: false + logEventOnRecycle: "Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory" state: - description: - - Current runtime state of the pool as the module completed. + description: Current runtime state of the pool as the module completed. returned: success type: string sample: "Started" diff --git a/test/integration/targets/win_iis_webapppool/aliases b/test/integration/targets/win_iis_webapppool/aliases new file mode 100644 index 0000000000..10e03fc2bf --- /dev/null +++ b/test/integration/targets/win_iis_webapppool/aliases @@ -0,0 +1 @@ +windows/ci/group1 diff --git a/test/integration/targets/win_iis_webapppool/defaults/main.yml b/test/integration/targets/win_iis_webapppool/defaults/main.yml new file mode 100644 index 0000000000..bd0f15c998 --- /dev/null +++ b/test/integration/targets/win_iis_webapppool/defaults/main.yml @@ -0,0 +1 @@ +test_iis_webapppool_name: TestPool \ No newline at end of file diff --git a/test/integration/targets/win_iis_webapppool/tasks/main.yml b/test/integration/targets/win_iis_webapppool/tasks/main.yml new file mode 100644 index 0000000000..462bc4f4aa --- /dev/null +++ b/test/integration/targets/win_iis_webapppool/tasks/main.yml @@ -0,0 +1,61 @@ +--- +# Cannot use win_feature to install IIS on Server 2008. +# Run a brief check and skip hosts that don't support +# that operation +- name: check if win_feature will work on test host + win_command: powershell.exe "Get-WindowsFeature" + register: module_available + failed_when: False + +# Run actual tests +- block: + # Setup for tests + - name: this is too finicky reboot before feature install + win_reboot: + + - name: ensure IIS features are installed + win_feature: + name: Web-Server + state: present + includ_sub_features: True + include_management_tools: True + register: feature_install + + - name: reboot after feature install + win_reboot: + when: feature_install.reboot_required + + - name: set version of IIS for tests + win_file_version: + path: C:\Windows\System32\inetsrv\w3wp.exe + register: iis_version + + - name: ensure test pool is deleted as a baseline + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: absent + + # Tests + - name: run tests on hosts that support it + include_tasks: tests.yml + + always: + # Cleanup + - name: ensure test pool is deleted + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: absent + + - name: remove IIS features after test + win_feature: + name: Web-Server + state: absent + includ_sub_features: True + include_management_tools: True + register: feature_uninstall + + - name: reboot after feature install + win_reboot: + when: feature_uninstall.reboot_required + + when: module_available.rc == 0 diff --git a/test/integration/targets/win_iis_webapppool/tasks/tests.yml b/test/integration/targets/win_iis_webapppool/tasks/tests.yml new file mode 100644 index 0000000000..a792980361 --- /dev/null +++ b/test/integration/targets/win_iis_webapppool/tasks/tests.yml @@ -0,0 +1,414 @@ +--- +- name: create default pool check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: started + register: create_default_check + check_mode: yes + +- name: get actual of create default pool check + win_command: powershell.exe "Import-Module WebAdministration; Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}" + register: create_default_actual_check + failed_when: False + +- name: assert create default pool check + assert: + that: + - create_default_check|changed + - create_default_actual_check.rc == 1 + +- name: create default pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + register: create_default + +- name: get actual of create default pool + win_command: powershell.exe "Import-Module WebAdministration; Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}" + register: create_default_actual + failed_when: False + +- name: assert create default pool + assert: + that: + - create_default|changed + - create_default.info.attributes.name == test_iis_webapppool_name + - create_default.info.attributes.startMode == 'OnDemand' + - create_default.info.attributes.state == 'Started' + - create_default_actual.rc == 0 + +- name: change attributes of pool check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + managedPipelineMode: 1 # Using an enum value + cpu.limit: 95 # Nested values + processModel.identityType: LocalSystem # Using an enum name + processModel.loadUserProfile: True + register: change_pool_attributes_check + check_mode: yes + +- name: assert change attributes of pool check + assert: + that: + - change_pool_attributes_check|changed + - change_pool_attributes_check.info == create_default.info + +- name: change attributes of pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + managedPipelineMode: 1 # Using an enum value + cpu.limit: 95 # Nested values + processModel.identityType: LocalSystem # Using an enum name + processModel.loadUserProfile: True + test: True + register: change_pool_attributes + +- name: assert change attributes of pool + assert: + that: + - change_pool_attributes|changed + - change_pool_attributes.info.attributes.managedPipelineMode == 'Classic' + - change_pool_attributes.info.cpu.limit == 95 + - change_pool_attributes.info.processModel.identityType == 'LocalSystem' + - change_pool_attributes.info.processModel.loadUserProfile == True + +- name: change attributes of pool again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + managedPipelineMode: 1 # Using an enum value + cpu.limit: 95 # Nested values + processModel.identityType: LocalSystem # Using an enum name + processModel.loadUserProfile: True + register: change_pool_attributes_again + +- name: assert change attributes of pool again + assert: + that: + - not change_pool_attributes_again|changed + - change_pool_attributes_again.info == change_pool_attributes.info + +- name: change attributes of pool (old style) check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: "managedPipelineMode:0|startMode:OnDemand|cpu.limit:0|processModel.identityType:NetworkService" + register: change_pool_attributes_deprecated_check + check_mode: yes + +- name: assert change attributes of pool (old style) check + assert: + that: + - change_pool_attributes_deprecated_check|changed + - change_pool_attributes_deprecated_check.info == change_pool_attributes_again.info + +- name: change attributes of pool (old style) + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: "managedPipelineMode:0|startMode:OnDemand|cpu.limit:10|processModel.identityType:NetworkService" + register: change_pool_attributes_deprecated + +- name: assert change attributes of pool (old style) + assert: + that: + - change_pool_attributes_deprecated|changed + - change_pool_attributes_deprecated.info.attributes.managedPipelineMode == 'Integrated' + - change_pool_attributes_deprecated.info.attributes.startMode == 'OnDemand' + - change_pool_attributes_deprecated.info.cpu.limit == 10 + - change_pool_attributes_deprecated.info.processModel.identityType == 'NetworkService' + +- name: change attributes of pool (old style) again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: "managedPipelineMode:0|startMode:OnDemand|cpu.limit:10|processModel.identityType:NetworkService" + register: change_pool_attributes_deprecated_again + +- name: assert change attributes of pool (old style) again + assert: + that: + - not change_pool_attributes_deprecated_again|changed + - change_pool_attributes_deprecated_again.info == change_pool_attributes_deprecated.info + +- name: change more complex variables check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + queueLength: 500 + recycling.periodicRestart.requests: 10 # Deeply nested attribute + recycling.periodicRestart.time: "00:00:05:00.000000" # Timespan with string + processModel.pingResponseTime: "00:03:00" # Timespan without days or milliseconds + register: change_complex_attributes_check + check_mode: yes + +- name: assert change more complex variables check + assert: + that: + - change_complex_attributes_check|changed + - change_complex_attributes_check.info == change_pool_attributes_deprecated_again.info + +- name: change more complex variables + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + queueLength: 500 + recycling.periodicRestart.requests: 10 # Deeply nested attribute + recycling.periodicRestart.time: "00:00:05:00.000000" # Timespan with string + processModel.pingResponseTime: "00:03:00" # Timespan without days or milliseconds + register: change_complex_attributes + +- name: assert change more complex variables + assert: + that: + - change_complex_attributes|changed + - change_complex_attributes.info.attributes.queueLength == 500 + - change_complex_attributes.info.recycling.periodicRestart.requests == 10 + - change_complex_attributes.info.recycling.periodicRestart.time.TotalSeconds == 300 + - change_complex_attributes.info.processModel.pingResponseTime.TotalSeconds == 180 + +- name: change more complex variables again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + queueLength: 500 + recycling.periodicRestart.requests: 10 # Deeply nested attribute + recycling.periodicRestart.time: "00:00:05:00.000000" # Timespan with string + processModel.pingResponseTime: "00:03:00" # Timespan without days or milliseconds + register: change_complex_attributes_again + +- name: assert change more complex variables again + assert: + that: + - not change_complex_attributes_again|changed + - change_complex_attributes_again.info == change_complex_attributes.info + +- name: stop web pool check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: stopped + register: stop_pool_check + check_mode: yes + +- name: get actual status of pool check + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: stop_pool_actual_check + +- name: assert stop web pool check + assert: + that: + - stop_pool_check|changed + - stop_pool_actual_check.stdout == 'Started\r\n' + +- name: stop web pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: stopped + register: stop_pool + +- name: get actual status of pool + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: stop_pool_actual + +- name: assert stop web pool + assert: + that: + - stop_pool|changed + - stop_pool_actual.stdout == 'Stopped\r\n' + +- name: stop web pool again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: stopped + register: stop_pool_again + +- name: get actual status of pool again + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: stop_pool_actual_again + +- name: assert stop web pool again + assert: + that: + - not stop_pool_again|changed + - stop_pool_actual_again.stdout == 'Stopped\r\n' + +- name: start web pool check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: started + register: start_pool_check + check_mode: yes + +- name: get actual status of pool check + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: start_pool_actual_check + +- name: assert start web pool check + assert: + that: + - start_pool_check|changed + - start_pool_actual_check.stdout == 'Stopped\r\n' + +- name: start web pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: started + register: start_pool + +- name: get actual status of pool + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: start_pool_actual + +- name: assert start web pool + assert: + that: + - start_pool|changed + - start_pool_actual.stdout == 'Started\r\n' + +- name: start web pool again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: started + register: start_pool_again + +- name: get actual status of pool again + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: start_pool_actual_again + +- name: assert start web pool again + assert: + that: + - not start_pool_again|changed + - start_pool_actual_again.stdout == 'Started\r\n' + +- name: restart web pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: restarted + register: restart_pool + +- name: get actual status of pool + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: restart_pool_actual + +- name: assert restart web pool + assert: + that: + - restart_pool|changed + - restart_pool_actual.stdout == 'Started\r\n' + +- name: stop pool before restart on stop test + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: stopped + +- name: restart from stopped web pool check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: restarted + register: restart_from_stop_pool_check + check_mode: yes + +- name: get actual status of pool check + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: restart_from_stop_pool_actual_check + +- name: assert restart from stopped web pool check + assert: + that: + - restart_from_stop_pool_check|changed + - restart_from_stop_pool_actual_check.stdout == 'Stopped\r\n' + +- name: restart from stopped web pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: restarted + register: restart_from_stop_pool + +- name: get actual status of pool + win_command: powershell.exe "Import-Module WebAdministration; (Get-Item -Path IIS:\AppPools\{{test_iis_webapppool_name}}).state" + register: restart_from_stop_pool_actual + +- name: assert restart from stopped web pool + assert: + that: + - restart_from_stop_pool|changed + - restart_from_stop_pool_actual.stdout == 'Started\r\n' + +# The following tests are only for IIS versions 8.0 or newer +- block: + - name: delete test pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: absent + + - name: create test pool + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + register: iis_attributes_blank + + - name: change attributes for newer IIS version check + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + startMode: AlwaysRunning + processModel.identityType: 3 + processModel.userName: '{{ansible_user}}' + processModel.password: '{{ansible_password}}' + register: iis_attributes_new_check + check_mode: yes + + - name: assert change attributes for newer IIS version check + assert: + that: + - iis_attributes_new_check|changed + - iis_attributes_new_check.info == iis_attributes_blank.info + + - name: change attributes for newer IIS version + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + startMode: AlwaysRunning + processModel.identityType: 3 + processModel.userName: '{{ansible_user}}' + processModel.password: '{{ansible_password}}' + register: iis_attributes_new + + - name: assert change attributes for newer IIS version + assert: + that: + - iis_attributes_new|changed + - iis_attributes_new.info.attributes.startMode == 'AlwaysRunning' + - iis_attributes_new.info.processModel.identityType == 'SpecificUser' + - iis_attributes_new.info.processModel.userName == ansible_user + - iis_attributes_new.info.processModel.password == ansible_password + + - name: change attributes for newer IIS version again + win_iis_webapppool: + name: '{{test_iis_webapppool_name}}' + state: present + attributes: + startMode: AlwaysRunning + processModel.identityType: 3 + processModel.userName: '{{ansible_user}}' + processModel.password: '{{ansible_password}}' + register: iis_attributes_new_again + + - name: assert change attributes for newer IIS version again + assert: + that: + - not iis_attributes_new_again|changed + - iis_attributes_new_again.info == iis_attributes_new.info + + when: iis_version.win_file_version.file_major_part|int > 7