Skip to content

Commit

Permalink
Migrate win_iis_webapplication module to new microsoft.iis repository
Browse files Browse the repository at this point in the history
  • Loading branch information
ronger4 committed Dec 26, 2024
2 parents fa6cdff + f823bb6 commit 2a3ce9c
Show file tree
Hide file tree
Showing 6 changed files with 1,024 additions and 0 deletions.
341 changes: 341 additions & 0 deletions plugins/modules/win_iis_webapppool.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
#!powershell

# Copyright: (c) 2015, Henrik Wallström <[email protected]>
# 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

$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

$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 = @{}
}
}
}

# 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 {
Fail-Json -obj $result -message "Using a string for the attributes parameter is not longer supported, please use a dict instead"
}
}
$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-CollectionToList($collection) {
$list = @()

if ($collection -is [String]) {
$raw_list = $collection -split ","
foreach ($entry in $raw_list) {
$list += $entry.Trim()
}
}
elseif ($collection -is [Microsoft.IIs.PowerShell.Framework.ConfigurationElement]) {
# the collection is the value from IIS itself, we need to conver accordingly
foreach ($entry in $collection.Collection) {
$list += $entry.Value.ToString()
}
}
elseif ($collection -isnot [Array]) {
$list += $collection
}
else {
$list = $collection
}

return , $list
}

Function Compare-Value($current, $new) {
if ($null -eq $current) {
return $true
}

if ($current -is [Array]) {
if ($new -isnot [Array]) {
return $true
}

if ($current.Count -ne $new.Count) {
return $true
}
for ($i = 0; $i -lt $current.Count; $i++) {
if ($current[$i] -ne $new[$i]) {
return $true
}
}
}
else {
if ($current -ne $new) {
return $true
}
}
return $false
}

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.Name -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 -gt 1) {
$attribute_parent = $attribute_key_split[0]
$attribute_key_split = $attribute_key_split[1..$($attribute_key_split.Length - 1)]
$parent = $pool.$attribute_parent

foreach ($key in $attribute_key_split) {
$attribute_meta = $parent.Attributes | Where-Object { $_.Name -eq $key }
$parent = $parent.$key
if ($null -eq $attribute_meta) {
$attribute_meta = $parent
}
}
$attribute_child = $attribute_key_split[-1]
}

if ($attribute_meta) {
if (($attribute_meta.PSObject.Properties.Name -eq "Collection").Count -gt 0) {
return , (Convert-CollectionToList -collection $attribute_value)
}
$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 ($null -eq $casted_value) {
$value
}
else {
$casted_value
}
}
else {
$attribute_value
}
}

# Ensure WebAdministration module is loaded
if ($null -eq (Get-Module -Name "WebAdministration" -ErrorAction SilentlyContinue)) {
Import-Module WebAdministration
$web_admin_dll_path = Join-Path $env:SystemRoot system32\inetsrv\Microsoft.Web.Administration.dll
Add-Type -LiteralPath $web_admin_dll_path
}

$pool = Get-Item -LiteralPath 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 > $null
}
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 -LiteralPath IIS:\AppPools\$name
}
}

# Cannot run the below in check mode if the pool did not always exist
if ($pool) {
# 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 -LiteralPath IIS:\AppPools\$name -Name $attribute_key -ErrorAction SilentlyContinue
$current_value = Convert-ToPropertyValue -pool $pool -attribute_key $attribute_key -attribute_value $current_raw_value

$changed = Compare-Value -current $current_value -new $new_value
if ($changed -eq $true) {
if ($new_value -is [Array]) {
try {
Clear-ItemProperty -LiteralPath IIS:\AppPools\$name -Name $attribute_key -WhatIf:$check_mode
}
catch {
$msg = -join @(
"Failed to clear attribute to Web App Pool $name. Attribute: $attribute_key, "
"Exception: $($_.Exception.Message)"
)
Fail-Json -obj $result -message $msg
}
foreach ($value in $new_value) {
try {
New-ItemProperty -LiteralPath IIS:\AppPools\$name -Name $attribute_key -Value @{value = $value } -WhatIf:$check_mode > $null
}
catch {
$msg = -join @(
"Failed to add new attribute to Web App Pool $name. Attribute: $attribute_key, "
"Value: $value, Exception: $($_.Exception.Message)"
)
Fail-Json -obj $result -message $msg
}
}
}
else {
try {
Set-ItemProperty -LiteralPath IIS:\AppPools\$name -Name $attribute_key -Value $new_value -WhatIf:$check_mode
}
catch {
$msg = -join @(
"Failed to set attribute to Web App Pool $name. Attribute: $attribute_key, "
"Value: $new_value, Exception: $($_.Exception.Message)"
)
Fail-Json $result $msg
}
}
$result.changed = $true
}
}

# Set the state of the pool
if ($pool.State -eq "Stopped") {
if ($state -eq "started" -or $state -eq "restarted") {
if (-not $check_mode) {
try {
Start-WebAppPool -Name $name > $null
}
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 > $null
}
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 > $null
}
catch {
Fail-Json $result "Failed to restart Web App Pool $($name): $($_.Exception.Message)"
}
}
$result.changed = $true
}
}
}
}

# Get all the current attributes for the pool
$pool = Get-Item -LiteralPath IIS:\AppPools\$name -ErrorAction SilentlyContinue
$elements = @("attributes", "cpu", "failure", "processModel", "recycling")

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
}

foreach ($attribute in $attribute_collection) {
$attribute_name = $attribute.Name
if ($attribute_name -notlike "*password*") {
$attribute_value = $attribute_parent.$attribute_name

$result.info.$element.Add($attribute_name, $attribute_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
Loading

0 comments on commit 2a3ce9c

Please sign in to comment.