win_chocolatey: refactor module to fix bugs and add new features (#43013)

* win_chocolatey: refactor module to fix bugs and add new features

* Fix some typos and only emit install warning not in check mode

* Fixes when testing out installing chocolatey from a server

* Added changelog fragment
This commit is contained in:
Jordan Borean
2018-07-24 07:52:13 +10:00
committed by GitHub
parent 460f858640
commit 93c05074ee
11 changed files with 1267 additions and 600 deletions

View File

@@ -0,0 +1,9 @@
---
test_choco_path: '{{ win_output_dir }}\win_chocolatey'
test_choco_source: '{{ test_choco_path }}\packages'
test_choco_source2: '{{ test_choco_path }}\packages2' # used to verify source works with the source name and not just the path
test_choco_package1: ansible
test_choco_package2: ansible-test
test_choco_packages:
- '{{ test_choco_package1 }}'
- '{{ test_choco_package2 }}'

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>--- NAME ---</id>
<version>--- VERSION ---</version>
<title>--- NAME ---</title>
<authors>Jordan Borean</authors>
<description>Test for win_chocolatey module</description>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>

View File

@@ -0,0 +1,9 @@
$ErrorActionPreference = 'Stop'
$package_name = $env:ChocolateyPackageName
$package_version = $env:ChocolateyPackageVersion
$install_path = "--- PATH ---\$package_name-$package_version.txt"
if (Test-Path -Path $install_path) {
Remove-Item -Path $install_path -Force > $null
}

View File

@@ -0,0 +1,49 @@
$ErrorActionPreference = 'Stop'
$package_name = $env:ChocolateyPackageName
$package_version = $env:ChocolateyPackageVersion
$install_path = "--- PATH ---\$package_name-$package_version.txt"
$source = "--- SOURCE ---" # used by the test to determine which source it was installed from
if ($env:ChocolateyAllowEmptyChecksums) {
$allow_empty_checksums = $true
} else {
$allow_empty_checksums = $false
}
if ($env:ChocolateyIgnoreChecksums) {
$ignore_checksums = $true
} else {
$ignore_checksums = $false
}
if ($env:ChocolateyForce) {
$force = $true
} else {
$force = $false
}
if ($env:ChocolateyForceX86) {
$force_x86 = $true
} else {
$force_x86 = $false
}
#$process_env = Get-EnvironmentVariableNames -Scope Process
#$env_vars = @{}
#foreach ($name in $process_env) {
# $env_vars.$name = Get-EnvironmentVariable -Name $name -Scope Process
#}
$timeout = $env:chocolateyResponseTimeout
$package_info = @{
allow_empty_checksums = $allow_empty_checksums
#env_vars = $env_vars
force = $force
force_x86 = $force_x86
ignore_checksums = $ignore_checksums
install_args = $env:ChocolateyInstallArguments
package_params = Get-PackageParameters
proxy_url = $env:ChocolateyProxyLocation
source = $source
timeout = $timeout
}
$package_json = ConvertTo-Json -InputObject $package_info
[System.IO.File]::WriteAllText($install_path, $package_json)

View File

@@ -1,65 +1,105 @@
# test code for the win_chocolatey module
# (c) 2017, Dag Wieers <dag@wieers.com>
# This file is part of Ansible
#
# 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: install chocolatey-core.extension
---
- name: ensure test package is uninstalled
win_chocolatey:
name: chocolatey-core.extension
state: present
register: install
- name: verify install chocolatey-core.extension
assert:
that:
- 'install.changed == true'
- install.rc == 0
- name: install chocolatey-core.extension again
win_chocolatey:
name: chocolatey-core.extension
state: present
register: install_again
- name: verify install chocolatey-core.extension again
assert:
that:
- 'install_again.changed == false'
- install.rc == 0
- name: remove chocolatey-core.extension
win_chocolatey:
name: chocolatey-core.extension
name: '{{ test_choco_packages }}'
state: absent
register: remove
- name: verify remove chocolatey-core.extension
assert:
that:
- 'remove.changed == true'
- install.rc == 0
- name: ensure testing dir is cleaned
win_file:
path: '{{ test_choco_path }}'
state: '{{ item }}'
with_items:
- absent
- directory
- name: remove chocolatey-core.extension again
win_chocolatey:
name: chocolatey-core.extension
state: absent
register: remove_again
- name: copy template package files
win_copy:
src: files/
dest: '{{ test_choco_path }}'
- name: verify remove chocolatey-core.extension again
assert:
that:
- 'remove_again.changed == false'
- install.rc == 0
# run the setup in 1 shell script to save on test time
- name: set up packages
win_shell: |
$ErrorActionPreference = "Stop"
$root_path = '{{ test_choco_path }}'
$packages_path = '{{ test_choco_source }}'
$packages_path_override = '{{ test_choco_source2 }}'
$packages = @(
@{ name = "ansible"; version = "0.0.1"; override = $false },
@{ name = "ansible"; version = "0.1.0"; override = $false },
@{ name = "ansible"; version = "0.1.0"; override = $true },
@{ name = "ansible-test"; version = "1.0.0"; override = $false },
@{ name = "ansible-test"; version = "1.0.1-beta1"; override = $false }
)
$nuspec_src = "$root_path\package.nuspec"
$install_src = "$root_path\tools\chocolateyinstall.ps1"
$uninstall_src = "$root_path\tools\chocolateyUninstall.ps1"
New-Item -Path $packages_path -ItemType Directory > $null
New-Item -Path $packages_path_override -ItemType Directory > $null
foreach ($package in $packages) {
$package_dir = "$root_path\$($package.name)-$($package.version)"
New-Item -Path $package_dir -ItemType Directory > $null
New-Item -Path "$package_dir\tools" -ItemType Directory > $null
if ($package.override) {
$out_path = $packages_path_override
$source_value = "override"
} else {
$out_path = $packages_path
$source_value = "normal"
}
$nuspec_text = ([System.IO.File]::ReadAllLines($nuspec_src) -join "`r`n")
$nuspec_text = $nuspec_text.Replace('--- NAME ---', $package.name).Replace('--- VERSION ---', $package.version)
$install_text = ([System.IO.File]::ReadAllLines($install_src) -join "`r`n")
$install_text = $install_text.Replace('--- PATH ---', $root_path).Replace('--- SOURCE ---', $source_value)
$uninstall_text = ([System.IO.File]::ReadAllLines($uninstall_src) -join "`r`n")
$uninstall_text = $uninstall_text.Replace('--- PATH ---', $root_path)
$utf8 = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false
$utf8_bom = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $true
[System.IO.File]::WriteAllText("$package_dir\$($package.name).nuspec", $nuspec_text, $utf8)
[System.IO.File]::WriteAllText("$package_dir\tools\chocolateyinstall.ps1", $install_text, $utf8_bom)
[System.IO.File]::WriteAllText("$package_dir\tools\chocolateyUninstall.ps1", $uninstall_text, $utf8_bom)
&choco.exe pack --out $out_path --no-progress --limit-output "$package_dir\$($package.name).nuspec"
Remove-Item -Path $package_dir -Force -Recurse > $null
}
Remove-Item -Path "$root_path\tools" -Force -Recurse > $null
Remove-Item -Path $nuspec_src > $null
- name: set up Chocolatey sources
win_chocolatey_source:
name: '{{ item.name }}'
priority: '{{ item.priority }}'
source: '{{ item.src }}'
state: present
with_items:
- name: ansible-test
priority: 1
src: '{{ test_choco_source }}'
- name: ansible-test-override
priority: 2
src: '{{ test_choco_source2 }}'
- block:
- name: run tests
include_tasks: tests.yml
always:
- name: remove test sources
win_chocolatey_source:
name: '{{ item }}'
state: absent
with_items:
- ansible-test
- ansible-test-override
- name: remove testing dir
win_file:
path: '{{ test_choco_path }}'
state: absent

View File

@@ -0,0 +1,416 @@
---
- name: install package (check mode)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
check_mode: yes
register: install_check
- name: get result of install package (check mode)
win_command: choco.exe list --local-only --exact --limit-output {{ test_choco_package1|quote }}
register: install_actual_check
- name: assert install package (check mode)
assert:
that:
- install_check is changed
- install_actual_check.stdout_lines == []
- name: install package
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
register: install
- name: get result of install package
win_command: choco.exe list --local-only --exact --limit-output {{ test_choco_package1|quote }}
register: install_actual
- name: get package info of install package
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt' -Raw
register: install_actual_info
- name: assert install package
assert:
that:
- install is changed
- install_actual.stdout_lines == [test_choco_package1 + "|0.1.0"]
- (install_actual_info.stdout|from_json).allow_empty_checksums == False
- (install_actual_info.stdout|from_json).force == False
- (install_actual_info.stdout|from_json).force_x86 == False
- (install_actual_info.stdout|from_json).ignore_checksums == False
- (install_actual_info.stdout|from_json).install_args == None
- (install_actual_info.stdout|from_json).package_params == {}
- (install_actual_info.stdout|from_json).proxy_url == None
- (install_actual_info.stdout|from_json).source == "normal"
- (install_actual_info.stdout|from_json).timeout == "2700000"
- name: install package (idempotent)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
register: install_again
- name: assert install package (idempotent)
assert:
that:
- not install_again is changed
- name: remove package (check mode)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: absent
check_mode: yes
register: remove_check
- name: get result of remove package (check mode)
win_command: choco.exe list --local-only --exact --limit-output {{ test_choco_package1|quote }}
register: remove_actual_check
- name: assert remove package (check mode)
assert:
that:
- remove_check is changed
- remove_actual_check.stdout_lines == [test_choco_package1 + "|0.1.0"]
- name: remove package
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: absent
register: remove
- name: get result of remove package
win_command: choco.exe list --local-only --exact --limit-output {{ test_choco_package1|quote }}
register: remove_actual
- name: check if removed package file still exists
win_stat:
path: '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt'
register: remove_actual_info
- name: assert remove package
assert:
that:
- remove is changed
- remove_actual.stdout_lines == []
- remove_actual_info.stat.exists == False
- name: remove package (idempotent)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: absent
register: remove_again
- name: assert remove_package (idempotent)
assert:
that:
- not remove_again is changed
- name: install multiple packages with timeout
win_chocolatey:
name: '{{ test_choco_packages }}'
state: present
timeout: 1000
register: install_multiple
- name: get list of installed packages with timeout
win_command: choco.exe list --local-only --limit-output ansible
register: install_multiple_actual
- name: get info on package 1
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt' -Raw
register: install_multiple_package1
- name: get info on package 2
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package2 }}-1.0.0.txt' -Raw
register: install_multiple_package2
- name: assert install multiple packages with timeout
assert:
that:
- install_multiple is changed
- install_multiple_actual.stdout_lines == [test_choco_package1 + "|0.1.0", test_choco_package2 + "|1.0.0"]
- (install_multiple_package1.stdout|from_json).allow_empty_checksums == False
- (install_multiple_package1.stdout|from_json).force == False
- (install_multiple_package1.stdout|from_json).force_x86 == False
- (install_multiple_package1.stdout|from_json).ignore_checksums == False
- (install_multiple_package1.stdout|from_json).install_args == None
- (install_multiple_package1.stdout|from_json).package_params == {}
- (install_multiple_package1.stdout|from_json).proxy_url == None
- (install_multiple_package1.stdout|from_json).source == "normal"
- (install_multiple_package1.stdout|from_json).timeout == "1000000"
- (install_multiple_package2.stdout|from_json).allow_empty_checksums == False
- (install_multiple_package2.stdout|from_json).force == False
- (install_multiple_package2.stdout|from_json).force_x86 == False
- (install_multiple_package2.stdout|from_json).ignore_checksums == False
- (install_multiple_package2.stdout|from_json).install_args == None
- (install_multiple_package2.stdout|from_json).package_params == {}
- (install_multiple_package2.stdout|from_json).proxy_url == None
- (install_multiple_package2.stdout|from_json).source == "normal"
- (install_multiple_package2.stdout|from_json).timeout == "1000000"
- name: install multiple packages (idempotent)
win_chocolatey:
name: '{{ test_choco_packages }}'
state: present
register: install_multiple_again
- name: assert install multiple packages (idempotent)
assert:
that:
- not install_multiple_again is changed
- name: remove multiple packages
win_chocolatey:
name: '{{ test_choco_packages }}'
state: absent
register: remove_multiple
- name: get list of installed packages after removal
win_command: choco.exe list --local-only --limit-output ansible
register: remove_multiple_actual
- name: get info on package 1
win_stat:
path: '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt'
register: remove_multiple_package1
- name: get info on package 2
win_stat:
path: '{{ test_choco_path }}\{{ test_choco_package2 }}-1.0.0.txt'
register: remove_multiple_package2
- name: assert remove multiple packages
assert:
that:
- remove_multiple is changed
- remove_multiple_actual.stdout_lines == []
- remove_multiple_package1.stat.exists == False
- remove_multiple_package2.stat.exists == False
- name: remove multiple packages (idempotent)
win_chocolatey:
name: '{{ test_choco_packages }}'
state: absent
register: remove_multiple_again
- name: assert remove multiple packages (idempotent)
assert:
that:
- not remove_multiple_again is changed
- name: install package with params
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
install_args: /install_arg 1 /install_arg 2
package_params: /param1 /param2:value
allow_empty_checksums: yes
architecture: x86
force: yes
ignore_checksums: yes
proxy_url: http://proxyhost
version: 0.0.1
register: install_params
- name: get result of install package with params
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: install_params_actual
- name: get info of install package with params
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package1 }}-0.0.1.txt'
register: install_params_info
- name: assert install package with params
assert:
that:
- install_params is changed
- install_params_actual.stdout_lines == [test_choco_package1 + "|0.0.1"]
- (install_params_info.stdout|from_json).allow_empty_checksums == True
- (install_params_info.stdout|from_json).force == True
- (install_params_info.stdout|from_json).force_x86 == True
- (install_params_info.stdout|from_json).ignore_checksums == True
- (install_params_info.stdout|from_json).install_args == "/install_arg 1 /install_arg 2"
- (install_params_info.stdout|from_json).package_params.keys()|count == 2
- (install_params_info.stdout|from_json).package_params.param1 == True
- (install_params_info.stdout|from_json).package_params.param2 == "value"
- (install_params_info.stdout|from_json).proxy_url == "http://proxyhost"
- (install_params_info.stdout|from_json).source == "normal"
- (install_params_info.stdout|from_json).timeout == "2700000"
- name: install package with version (idempotent)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
version: 0.0.1
register: install_with_version
- name: assert install package with version (idempotent)
assert:
that:
- not install_with_version is changed
- name: fail to install side by side package
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
version: 0.1.0
register: fail_multiple_versions
failed_when: fail_multiple_versions.msg != "Chocolatey package '" + test_choco_package1 + "' is already installed at version '0.0.1' but was expecting '0.1.0'. Either change the expected version, set state=latest, set allow_multiple_versions=yes, or set force=yes to continue"
- name: force the upgrade of an existing version
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
version: 0.1.0
force: yes
register: force_different_version
- name: get result of force the upgrade of an existing version
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: force_different_version_actual
- name: get result of forced package install file
win_stat:
path: '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt'
register: force_different_version_info
- name: assert force the upgrade of an existing version
assert:
that:
- force_different_version is changed
- force_different_version_actual.stdout_lines == [test_choco_package1 + "|0.1.0"]
- force_different_version_info.stat.exists
- name: remove package after force clobbered everything
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: absent
ignore_errors: yes # the mock package created doesn't really handle force well
- name: install package with reference to source name
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
source: ansible-test-override
register: install_source_name
- name: get result of install package with reference to source name
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: install_source_name_actual
- name: get result fo installed package with reference to source name info
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt' -Raw
register: install_source_name_info
- name: assert install package with reference to source name
assert:
that:
- install_source_name is changed
- install_source_name_actual.stdout_lines == [test_choco_package1 + "|0.1.0"]
- (install_source_name_info.stdout|from_json).source == "override"
- name: reinstall package without source override
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: reinstalled
register: reinstalled_package
- name: get result of reinstalled package without source override
win_shell: Get-Content -Path '{{ test_choco_path }}\{{ test_choco_package1 }}-0.1.0.txt' -Raw
register: reinstalled_package_info
- name: assert reinstall package without source override
assert:
that:
- reinstalled_package is changed
- (reinstalled_package_info.stdout|from_json).source == "normal"
- name: downgrade package
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: downgrade
version: 0.0.1
register: downgraded_package
- name: get result of downgrade package
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: downgraded_package_actual
- name: assert downgrade package
assert:
that:
- downgraded_package is changed
- downgraded_package_actual.stdout_lines == [test_choco_package1 + "|0.0.1"]
- name: downgrade package (idempotent)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: downgrade
version: 0.0.1
register: downgraded_package_again
- name: assert downgrade package (idempotent)
assert:
that:
- not downgraded_package_again is changed
- name: downgrade package without version specified
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: downgrade
register: downgrade_without_version
- name: get result of downgrade without version
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: downgrade_without_version_actual
- name: assert downgrade package without version specified
assert:
that:
- not downgrade_without_version is changed
- downgrade_without_version_actual.stdout_lines == [test_choco_package1 + "|0.0.1"]
- name: upgrade package
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: latest
register: upgrade_package
- name: get result of upgrade package
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package1|quote }}
register: upgrade_package_actual
- name: assert upgrade package
assert:
that:
- upgrade_package is changed
- upgrade_package_actual.stdout_lines == [test_choco_package1 + "|0.1.0"]
- name: upgrade package (idempotent)
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: latest
register: upgrade_package_again
- name: assert upgrade package (idempotent)
assert:
that:
- not upgrade_package_again is changed
- name: install prerelease package
win_chocolatey:
name: '{{ test_choco_package2 }}'
state: present
allow_prerelease: yes
register: install_prerelease
- name: get result of install prerelease package
win_command: choco.exe list --local-only --limit-output --exact {{ test_choco_package2|quote }}
register: install_prerelease_actual
- name: assert install prerelease package
assert:
that:
- install_prerelease is changed
- install_prerelease_actual.stdout_lines == [test_choco_package2 + "|1.0.1-beta1"]

View File

@@ -13,12 +13,6 @@ lib/ansible/modules/windows/setup.ps1 PSAvoidUsingCmdletAliases
lib/ansible/modules/windows/setup.ps1 PSAvoidUsingEmptyCatchBlock
lib/ansible/modules/windows/setup.ps1 PSUseDeclaredVarsMoreThanAssignments
lib/ansible/modules/windows/win_certificate_store.ps1 PSAvoidUsingPlainTextForPassword
lib/ansible/modules/windows/win_chocolatey.ps1 PSAvoidUsingConvertToSecureStringWithPlainText
lib/ansible/modules/windows/win_chocolatey.ps1 PSAvoidUsingPlainTextForPassword
lib/ansible/modules/windows/win_chocolatey.ps1 PSAvoidUsingUserNameAndPassWordParams
lib/ansible/modules/windows/win_chocolatey.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_chocolatey.ps1 PSUseDeclaredVarsMoreThanAssignments
lib/ansible/modules/windows/win_chocolatey.ps1 PSUseOutputTypeCorrectly
lib/ansible/modules/windows/win_copy.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_copy.ps1 PSUseDeclaredVarsMoreThanAssignments
lib/ansible/modules/windows/win_dns_client.ps1 PSAvoidGlobalVars