Windows module: win_optional_feature for Windows workstations (#53709)
* initial commit * fix execute and \r\n * \r attempt 2 * updated with integration tests and using new csharp import * Apply suggestions from code review Co-Authored-By: rcanderson23 <rcanderson23@gmail.com> * fixed small docuement inaccuracies wrt returns * removal of state in feature result * removal of rc * small fixes suggested in code review * fixed variable assigning to result * addition of comments on conditionals for clarity on matching * swap logic of check_mode * set $reboot_required so it is always returned * removal of extraneous return information * addition of integration tests * set installation of parent features to true * remove 2008 from tests * changed test for TelnetClient from NetFx3 * change of tabs to spaces * Add test check for OS version
This commit is contained in:
parent
f5f4948480
commit
31ceba7fd8
5 changed files with 270 additions and 0 deletions
71
lib/ansible/modules/windows/win_optional_feature.ps1
Normal file
71
lib/ansible/modules/windows/win_optional_feature.ps1
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!powershell
|
||||
|
||||
# Copyright: (c) 2019, Carson Anderson <rcanderson23@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
#AnsibleRequires -CSharpUtil Ansible.Basic
|
||||
|
||||
$spec = @{
|
||||
options = @{
|
||||
name = @{ type = "str"; required = $true }
|
||||
state = @{ type = "str"; default = "present"; choices = @("absent", "present") }
|
||||
source = @{ type = "str" }
|
||||
include_parent = @{ type = "bool"; default = $false }
|
||||
}
|
||||
supports_check_mode = $true
|
||||
}
|
||||
|
||||
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
|
||||
|
||||
$name = $module.Params.name
|
||||
$state = $module.Params.state
|
||||
$source = $module.Params.source
|
||||
$include_parent = $module.Params.include_parent
|
||||
|
||||
$module.Result.reboot_required = $false
|
||||
|
||||
if (-not (Get-Command -Name Enable-WindowsOptionalFeature -ErrorAction SilentlyContinue)) {
|
||||
$module.FailJson("This version of Windows does not support the Enable-WindowsOptionalFeature.")
|
||||
}
|
||||
|
||||
$feature_state_start = Get-WindowsOptionalFeature -Online -FeatureName $name
|
||||
if (-not $feature_state_start) {
|
||||
$module.FailJson("Failed to find feature '$name'")
|
||||
}
|
||||
|
||||
if ($state -eq "present") {
|
||||
# Matches for "Enabled" and "EnabledPending"
|
||||
if ($feature_state_start.State -notlike "Enabled*") {
|
||||
$install_args = @{
|
||||
FeatureName = $name
|
||||
All = $include_parent
|
||||
}
|
||||
|
||||
if ($source) {
|
||||
if (-not (Test-Path -LiteralPath $source)) {
|
||||
$module.FailJson("Path could not be found '$source'")
|
||||
}
|
||||
$install_args.Source = $source
|
||||
}
|
||||
|
||||
if (-not $module.CheckMode) {
|
||||
$action_result = Enable-WindowsOptionalFeature -Online -NoRestart @install_args
|
||||
$module.Result.reboot_required = $action_result.RestartNeeded
|
||||
}
|
||||
$module.Result.changed = $true
|
||||
}
|
||||
} else {
|
||||
# Matches for Disabled, DisabledPending, and DisabledWithPayloadRemoved
|
||||
if ($feature_state_start.State -notlike "Disabled*") {
|
||||
$remove_args = @{
|
||||
FeatureName = $name
|
||||
}
|
||||
|
||||
if (-not $module.CheckMode) {
|
||||
$action_result = Disable-WindowsOptionalFeature -Online -NoRestart @remove_args
|
||||
$module.Result.reboot_required = $action_result.RestartNeeded
|
||||
}
|
||||
$module.Result.changed = $true
|
||||
}
|
||||
}
|
||||
$module.ExitJson()
|
83
lib/ansible/modules/windows/win_optional_feature.py
Normal file
83
lib/ansible/modules/windows/win_optional_feature.py
Normal file
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2019, Carson Anderson <rcanderson23@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
# this is a windows documentation stub. actual code lives in the .ps1
|
||||
# file of the same name
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: win_optional_feature
|
||||
version_added: "2.8"
|
||||
short_description: Manage optional Windows features
|
||||
description:
|
||||
- Install or uninstall optional Windows features on non-Server Windows.
|
||||
- This module uses the C(Enable-WindowsOptionalFeature) and C(Disable-WindowsOptionalFeature) cmdlets.
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The name of the feature to install.
|
||||
- This relates to C(FeatureName) in the Powershell cmdlet.
|
||||
- To list all available features use the PowerShell command C(Get-WindowsOptionalFeature).
|
||||
type: str
|
||||
required: yes
|
||||
state:
|
||||
description:
|
||||
- Whether to ensure the feature is absent or present on the system.
|
||||
type: str
|
||||
choices: [ absent, present ]
|
||||
default: present
|
||||
include_parent:
|
||||
description:
|
||||
- Whether to enable the parent feature and the parent's dependencies.
|
||||
type: bool
|
||||
default: no
|
||||
source:
|
||||
description:
|
||||
- Specify a source to install the feature from.
|
||||
- Can either be C({driveletter}:\sources\sxs) or C(\\{IP}\share\sources\sxs).
|
||||
type: str
|
||||
seealso:
|
||||
- module: win_chocolatey
|
||||
- module: win_feature
|
||||
- module: win_package
|
||||
author:
|
||||
- Carson Anderson (@rcanderson23)
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Install .Net 3.5
|
||||
win_optional_feature:
|
||||
name: NetFx3
|
||||
state: present
|
||||
|
||||
- name: Install .Net 3.5 from source
|
||||
win_optional_feature:
|
||||
name: NetFx3
|
||||
source: \\share01\win10\sources\sxs
|
||||
state: present
|
||||
|
||||
- name: Install Microsoft Subsystem for Linux
|
||||
win_optional_feature:
|
||||
name: Microsoft-Windows-Subsystem-Linux
|
||||
state: present
|
||||
register: wsl_status
|
||||
|
||||
- name: Reboot if installing Linux Subsytem as feature requires it
|
||||
win_reboot:
|
||||
when: wsl_status.reboot_required
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
reboot_required:
|
||||
description: True when the target server requires a reboot to complete updates
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
'''
|
3
test/integration/targets/win_optional_feature/aliases
Normal file
3
test/integration/targets/win_optional_feature/aliases
Normal file
|
@ -0,0 +1,3 @@
|
|||
shippable/windows/group2
|
||||
skip/windows/2008
|
||||
skip/windows/2008-R2
|
25
test/integration/targets/win_optional_feature/tasks/main.yml
Normal file
25
test/integration/targets/win_optional_feature/tasks/main.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Test code for win_optional_feature module
|
||||
# Copyright: (c) 2019, Carson Anderson <rcanderson23@gmail.com>
|
||||
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
- name: check if host supports module
|
||||
win_shell: if (Get-Command -Name Enable-WindowsOptionalFeature -ErrorAction SilentlyContinue) { $true } else { $false }
|
||||
register: run_tests
|
||||
|
||||
- name: run tests
|
||||
include_tasks: tests.yml
|
||||
when: run_tests.stdout | trim | bool
|
|
@ -0,0 +1,88 @@
|
|||
# Test code for win_optional_feature module
|
||||
# Copyright: (c) 2019, Carson Anderson <rcanderson23@gmail.com>
|
||||
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
- name: run with check_mode
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: present
|
||||
include_parent: true
|
||||
check_mode: yes
|
||||
register: feature_check
|
||||
|
||||
- name: assert check_mode
|
||||
assert:
|
||||
that:
|
||||
- feature_check.changed
|
||||
|
||||
- name: run without check_mode
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: present
|
||||
include_parent: true
|
||||
register: real_feature_check
|
||||
|
||||
- name: assert feature installed
|
||||
assert:
|
||||
that:
|
||||
- real_feature_check.changed
|
||||
|
||||
- name: test idempotence for install
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: present
|
||||
include_parent: true
|
||||
register: real_feature_check
|
||||
|
||||
- name: assert idempotence
|
||||
assert:
|
||||
that:
|
||||
- not real_feature_check.changed
|
||||
|
||||
- name: removal run with check_mode
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: absent
|
||||
check_mode: yes
|
||||
register: feature_check
|
||||
|
||||
- name: assert removal check_mode
|
||||
assert:
|
||||
that:
|
||||
- feature_check.changed
|
||||
|
||||
- name: remove feature
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: absent
|
||||
register: real_feature_check
|
||||
|
||||
- name: assert feature removed
|
||||
assert:
|
||||
that:
|
||||
- real_feature_check.changed
|
||||
|
||||
- name: test idempotence for removal
|
||||
win_optional_feature:
|
||||
name: TelnetClient
|
||||
state: absent
|
||||
register: real_feature_check
|
||||
|
||||
- name: assert idempotence
|
||||
assert:
|
||||
that:
|
||||
- not real_feature_check.changed
|
Loading…
Reference in a new issue