diff --git a/lib/ansible/modules/windows/win_chocolatey_feature.ps1 b/lib/ansible/modules/windows/win_chocolatey_feature.ps1 new file mode 100644 index 0000000000..a33378cd6a --- /dev/null +++ b/lib/ansible/modules/windows/win_chocolatey_feature.ps1 @@ -0,0 +1,74 @@ +#!powershell + +# Copyright: (c), 2018 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#Requires -Module Ansible.ModuleUtils.CommandUtil +#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 "enabled" -validateset "disabled", "enabled" + +$result = @{ + changed = $false +} + +Function Get-ChocolateyFeatures { + param($choco_app) + + $res = Run-Command -command "`"$($choco_app.Path)`" feature list -r" + if ($res.rc -ne 0) { + Fail-Json -obj $result -message "Failed to list Chocolatey features: $($res.stderr)" + } + $feature_info = @{} + $res.stdout -split "`r`n" | Where-Object { $_ -ne "" } | ForEach-Object { + $feature_split = $_ -split "\|" + $feature_info."$($feature_split[0])" = $feature_split[1] -eq "Enabled" + } + + return ,$feature_info +} + +Function Set-ChocolateyFeature { + param( + $choco_app, + $name, + $enabled + ) + + if ($enabled) { + $state_string = "enable" + } else { + $state_string = "disable" + } + $res = Run-Command -command "`"$($choco_app.Path)`" feature $state_string --name `"$name`"" + if ($res.rc -ne 0) { + Fail-Json -obj $result -message "Failed to set Chocolatey feature $name to $($state_string): $($res.stderr)" + } +} + +$choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue +if (-not $choco_app) { + Fail-Json -obj $result -message "Failed to find Chocolatey installation, make sure choco.exe is in the PATH env value" +} + +$feature_info = Get-ChocolateyFeatures -choco_app $choco_app +if ($name -notin $feature_info.keys) { + Fail-Json -obj $result -message "Invalid feature name '$name' specified, valid features are: $($feature_info.keys -join ', ')" +} + +$expected_status = $state -eq "enabled" +$feature_status = $feature_info.$name +if ($feature_status -ne $expected_status) { + if (-not $check_mode) { + Set-ChocolateyFeature -choco_app $choco_app -name $name -enabled $expected_status + } + $result.changed = $true +} + +Exit-Json -obj $result diff --git a/lib/ansible/modules/windows/win_chocolatey_feature.py b/lib/ansible/modules/windows/win_chocolatey_feature.py new file mode 100644 index 0000000000..e1449f8445 --- /dev/null +++ b/lib/ansible/modules/windows/win_chocolatey_feature.py @@ -0,0 +1,50 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2018, Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: win_chocolatey_feature +version_added: '2.7' +short_description: Manages Chocolatey features +description: +- Used to enable or disable features in Chocolatey. +options: + name: + description: + - The name of the feature to manage. + - Run C(choco.exe feature list) to get a list of features that can be + managed. + required: yes + state: + description: + - When C(disabled) then the feature will be disabled. + - When C(enabled) then the feature will be enabled. + choices: + - disabled + - enabled + default: enabled +author: +- Jordan Borean (@jborean93) +''' + +EXAMPLES = r''' +- name: disable file checksum matching + win_chocolatey_feature: + name: checksumFiles + state: disabled + +- name: stop Chocolatey on the first package failure + win_chocolatey_feature: + name: stopOnFirstPackageFailure + state: enabled +''' + +RETURN = r''' +''' diff --git a/test/integration/targets/win_chocolatey_feature/aliases b/test/integration/targets/win_chocolatey_feature/aliases new file mode 100644 index 0000000000..10e03fc2bf --- /dev/null +++ b/test/integration/targets/win_chocolatey_feature/aliases @@ -0,0 +1 @@ +windows/ci/group1 diff --git a/test/integration/targets/win_chocolatey_feature/filter_plugins/choco_checksum_state.py b/test/integration/targets/win_chocolatey_feature/filter_plugins/choco_checksum_state.py new file mode 100644 index 0000000000..8dff044d1a --- /dev/null +++ b/test/integration/targets/win_chocolatey_feature/filter_plugins/choco_checksum_state.py @@ -0,0 +1,14 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +def choco_checksum_state(value): + return [i for i in value if i.startswith("checksumFiles|")][0].split("|")[1] == "Enabled" + + +class FilterModule(object): + + def filters(self): + return { + 'choco_checksum_state': choco_checksum_state + } diff --git a/test/integration/targets/win_chocolatey_feature/tasks/main.yml b/test/integration/targets/win_chocolatey_feature/tasks/main.yml new file mode 100644 index 0000000000..c2100be01f --- /dev/null +++ b/test/integration/targets/win_chocolatey_feature/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: ensure Chocolatey is installed + win_chocolatey: + name: chocolatey + state: present + +- name: ensure we start from a baseline for test feature + win_chocolatey_feature: + name: checksumFiles + state: disabled + +- block: + - name: run tests + include_tasks: tests.yml + + always: + - name: set feature back to enabled + win_chocolatey_feature: + name: checksumFiles + state: enabled diff --git a/test/integration/targets/win_chocolatey_feature/tasks/tests.yml b/test/integration/targets/win_chocolatey_feature/tasks/tests.yml new file mode 100644 index 0000000000..94bbb7a9ce --- /dev/null +++ b/test/integration/targets/win_chocolatey_feature/tasks/tests.yml @@ -0,0 +1,95 @@ +--- +- name: fail on invalid feature + win_chocolatey_feature: + name: failFeature + state: enabled + register: fail_res + failed_when: '"Invalid feature name ''failFeature'' specified, valid features are: " not in fail_res.msg' + +- name: enable disabled feature (check mode) + win_chocolatey_feature: + name: checksumFiles + state: enabled + check_mode: yes + register: enable_check + +- name: get actual state of feature (check mode) + win_command: choco.exe feature list -r + register: enable_actual_check + +- name: assert enable disabled feature (check mode) + assert: + that: + - enable_check is changed + - enable_actual_check.stdout_lines|choco_checksum_state == False + +- name: enable disabled feature + win_chocolatey_feature: + name: checksumFiles + state: enabled + register: enable + +- name: get actual state of feature + win_command: choco.exe feature list -r + register: enable_actual + +- name: assert enable disabled feature + assert: + that: + - enable is changed + - enable_actual.stdout_lines|choco_checksum_state == True + +- name: enable disabled feature (idempotent) + win_chocolatey_feature: + name: checksumFiles + state: enabled + register: enable_again + +- name: assert enable disabled feature (idempotent) + assert: + that: + - not enable_again is changed + +- name: disable enabled feature (check mode) + win_chocolatey_feature: + name: checksumFiles + state: disabled + check_mode: yes + register: disable_check + +- name: get actual state of feature (check mode) + win_command: choco.exe feature list -r + register: disable_actual_check + +- name: assert disable enabled feature (check mode) + assert: + that: + - disable_check is changed + - disable_actual_check.stdout_lines|choco_checksum_state == True + +- name: disable enabled feature + win_chocolatey_feature: + name: checksumFiles + state: disabled + register: disable + +- name: get actual state of feature + win_command: choco.exe feature list -r + register: disable_actual + +- name: assert disable enabled feature + assert: + that: + - disable is changed + - disable_actual.stdout_lines|choco_checksum_state == False + +- name: disable enabled feature (idempotent) + win_chocolatey_feature: + name: checksumFiles + state: disabled + register: disable_again + +- name: assert disable enabled feature (idempotent) + assert: + that: + - not disable_again is changed