From be7768efc79b59863f5b2cfc46ecd3840d6c5021 Mon Sep 17 00:00:00 2001
From: Jordan Borean <jborean93@gmail.com>
Date: Tue, 5 Mar 2019 14:18:00 +1000
Subject: [PATCH] win_chocolatey_source - fix state=disabled with no source
 (#53097)

---
 .../win_chocolatey_source_disabled.yaml       |  2 +
 .../modules/windows/win_chocolatey_source.ps1 | 31 +++----
 .../modules/windows/win_chocolatey_source.py  |  3 +-
 .../win_chocolatey_source/tasks/tests.yml     | 88 +++++++++++++++++++
 4 files changed, 105 insertions(+), 19 deletions(-)
 create mode 100644 changelogs/fragments/win_chocolatey_source_disabled.yaml

diff --git a/changelogs/fragments/win_chocolatey_source_disabled.yaml b/changelogs/fragments/win_chocolatey_source_disabled.yaml
new file mode 100644
index 00000000000..779c614383f
--- /dev/null
+++ b/changelogs/fragments/win_chocolatey_source_disabled.yaml
@@ -0,0 +1,2 @@
+bugfixes:
+- win_chocolatey_source - fix bug where a Chocolatey source could not be disabled unless ``source`` was also set - https://github.com/ansible/ansible/issues/50133
diff --git a/lib/ansible/modules/windows/win_chocolatey_source.ps1 b/lib/ansible/modules/windows/win_chocolatey_source.ps1
index 043c2fcc7ec..c2360f153ab 100644
--- a/lib/ansible/modules/windows/win_chocolatey_source.ps1
+++ b/lib/ansible/modules/windows/win_chocolatey_source.ps1
@@ -7,8 +7,6 @@
 #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
 $diff = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
@@ -22,7 +20,7 @@ $bypass_proxy = Get-AnsibleParam -obj $params -name "bypass_proxy" -type "bool"
 $certificate = Get-AnsibleParam -obj $params -name "certificate" -type "str"
 $certificate_password = Get-AnsibleParam -obj $params -name "certificate_password" -type "str"
 $priority = Get-AnsibleParam -obj $params -name "priority" -type "int"
-$source = Get-AnsibleParam -obj $params -name "source" -type "str" -failifempty ($state -ne "absent")
+$source = Get-AnsibleParam -obj $params -name "source" -type "str"
 $source_username = Get-AnsibleParam -obj $params -name "source_username" -type "str"
 $source_password = Get-AnsibleParam -obj $params -name "source_password" -type "str" -failifempty ($null -ne $source_username)
 $update_password = Get-AnsibleParam -obj $params -name "update_password" -type "str" -default "always" -validateset "always", "on_create"
@@ -225,9 +223,12 @@ if ($state -eq "absent" -and $null -ne $actual_source) {
 } elseif ($state -in ("disabled", "present")) {
     $change = $false
     if ($null -eq $actual_source) {
+        if ($null -eq $source) {
+            Fail-Json -obj $result -message "The source option must be set when creating a new source"
+        }
         $change = $true
     } else {
-        if ($source -ne $actual_source.source) {
+        if ($null -ne $source -and $source -ne $actual_source.source) {
             $change = $true
         }
         if ($null -ne $source_username -and $source_username -ne $actual_source.source_username) {
@@ -271,29 +272,23 @@ if ($state -eq "absent" -and $null -ne $actual_source) {
     }
 
     # enable/disable the source if necessary
+    $status_action = $null
     if ($state -ne "disabled" -and $actual_source.disabled) {
-        $arguments = [System.Collections.ArrayList]@($choco_app.Path, "source", "enable", "--name", $name)
-        if ($check_mode) {
-            $arguments.Add("--what-if") > $null
-        }
-        $command = Argv-ToString -arguments $arguments
-        $res = Run-Command -command $command
-        if ($res.rc -ne 0) {
-            Fail-Json -obj $result -message "Failed to enable Chocolatey source '$name': $($res.stderr)"
-        }
-        $actual_source.disabled = $false
-        $result.changed = $true
+        $status_action = "enable"
     } elseif ($state -eq "disabled" -and (-not $actual_source.disabled)) {
-        $arguments = [System.Collections.ArrayList]@($choco_app.Path, "source", "disable", "--name", $name)
+        $status_action = "disable"
+    }
+    if ($null -ne $status_action) {
+        $arguments = [System.Collections.ArrayList]@($choco_app.Path, "source", $status_action, "--name", $name)
         if ($check_mode) {
             $arguments.Add("--what-if") > $null
         }
         $command = Argv-ToString -arguments $arguments
         $res = Run-Command -command $command
         if ($res.rc -ne 0) {
-            Fail-Json -obj $result -message "Failed to disable Chocolatey source '$name': $($res.stderr)"
+            Fail-Json -obj $result -message "Failed to $status_action Chocolatey source '$name': $($res.stderr)"
         }
-        $actual_source.disabled = $true
+        $actual_source.disabled = ($status_action -eq "disable")
         $result.changed = $true
     }
 
diff --git a/lib/ansible/modules/windows/win_chocolatey_source.py b/lib/ansible/modules/windows/win_chocolatey_source.py
index 69f62bab3bb..0e1fc0f588e 100644
--- a/lib/ansible/modules/windows/win_chocolatey_source.py
+++ b/lib/ansible/modules/windows/win_chocolatey_source.py
@@ -60,7 +60,8 @@ options:
   source:
     description:
     - The file/folder/url of the source.
-    - Required when I(state) is C(present) or C(disabled).
+    - Required when I(state) is C(present) or C(disabled) and the source does
+      not already exist.
   source_username:
     description:
     - The username used to access I(source).
diff --git a/test/integration/targets/win_chocolatey_source/tasks/tests.yml b/test/integration/targets/win_chocolatey_source/tasks/tests.yml
index 0a574c4e945..58f6b6a86bd 100644
--- a/test/integration/targets/win_chocolatey_source/tasks/tests.yml
+++ b/test/integration/targets/win_chocolatey_source/tasks/tests.yml
@@ -241,3 +241,91 @@
   assert:
     that:
     - not modify_source_again is changed
+
+- name: disable source (check mode)
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: disabled
+  register: disable_source_check
+  check_mode: True
+
+- name: get result of disable source (check mode)
+  win_command: choco.exe source list -r
+  register: disable_source_actual_check
+
+- name: assert disable source (check mode)
+  assert:
+    that:
+    - disable_source_check is changed
+    - disable_source_actual_check.stdout == modify_source_actual.stdout
+
+- name: disable source
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: disabled
+  register: disable_source
+
+- name: get result of disable source
+  win_command: choco.exe source list -r
+  register: disable_source_actual
+
+- name: assert disable source
+  assert:
+    that:
+    - disable_source is changed
+    - disable_source_actual.stdout_lines == ["test'|\"source 123^|C:\\chocolatey repos2|True|username2|C:\\cert2.pfx|5|False|True|True"]
+
+- name: disable source (idempotent)
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: disabled
+  register: disable_source_again
+
+- name: assert disable source (idempotent)
+  assert:
+    that:
+    - not disable_source_again is changed
+
+- name: enable source (check mode)
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: present
+  register: enable_source_check
+  check_mode: True
+
+- name: get result of enable source (check mode)
+  win_command: choco.exe source list -r
+  register: enable_source_actual_check
+
+- name: assert enable source (check mode)
+  assert:
+    that:
+    - enable_source_check is changed
+    - enable_source_actual_check.stdout == disable_source_actual.stdout
+
+- name: enable source
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: present
+  register: enable_source
+
+- name: get result of enable source
+  win_command: choco.exe source list -r
+  register: enable_source_actual
+
+- name: assert enable source
+  assert:
+    that:
+    - enable_source is changed
+    - enable_source_actual.stdout_lines == ["test'|\"source 123^|C:\\chocolatey repos2|False|username2|C:\\cert2.pfx|5|False|True|True"]
+
+- name: enable source (idempotent)
+  win_chocolatey_source:
+    name: '{{ test_chocolatey_name }}'
+    state: present
+  register: enable_source_again
+
+- name: assert enable source (idempotent)
+  assert:
+    that:
+    - not enable_source_again is changed