win_chocolatey - add ability to pin a package (#53157)

* win_chocolatey - add ability to pin a package

* fix typoe in changelog fragment
This commit is contained in:
Jordan Borean 2019-03-05 14:18:42 +10:00 committed by GitHub
parent be7768efc7
commit b74295d25f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 229 additions and 0 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- win_chocolatey - Added the ability to pin a package using the ``pinned`` option - https://github.com/ansible/ansible/issues/38526

View file

@ -25,6 +25,7 @@ $spec = @{
force = @{ type = "bool"; default = $false }
name = @{ type = "list"; elements = "str"; required = $true }
package_params = @{ type = "str"; aliases = "params" }
pinned = @{ type = "bool" }
proxy_url = @{ type = "str" }
proxy_username = @{ type = "str" }
proxy_password = @{ type = "str"; no_log = $true }
@ -51,6 +52,7 @@ $ignore_dependencies = $module.Params.ignore_dependencies
$force = $module.Params.force
$name = $module.Params.name
$package_params = $module.Params.package_params
$pinned = $module.Params.pinned
$proxy_url = $module.Params.proxy_url
$proxy_username = $module.Params.proxy_username
$proxy_password = $module.Params.proxy_password
@ -342,6 +344,75 @@ Function Get-ChocolateyPackageVersion {
return ,$versions
}
Function Get-ChocolateyPin {
param(
[Parameter(Mandatory=$true)][String]$choco_path
)
$command = Argv-ToString -arguments @($choco_path, "pin", "list", "--limit-output")
$res = Run-Command -command $command
if ($res.rc -ne 0) {
$module.Result.command = $command
$module.Result.rc = $res.rc
$module.Result.stdout = $res.stdout
$module.Result.stderr = $res.stderr
$module.FailJson("Error getting list of pinned packages")
}
$stdout = $res.stdout.Trim()
$pins = @{}
$stdout.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
$package = $_.Substring(0, $_.LastIndexOf("|"))
$version = $_.Substring($_.LastIndexOf("|") + 1)
if ($pins.ContainsKey($package)) {
$pinned_versions = $pins.$package
} else {
$pinned_versions = [System.Collections.Generic.List`1[String]]@()
}
$pinned_versions.Add($version)
$pins.$package = $pinned_versions
}
return ,$pins
}
Function Set-ChocolateyPin {
param(
[Parameter(Mandatory=$true)][String]$choco_path,
[Parameter(Mandatory=$true)][String]$name,
[Switch]$pin,
[String]$version
)
if ($pin) {
$action = "add"
$err_msg = "Error pinning package '$name'"
} else {
$action = "remove"
$err_msg = "Error unpinning package '$name'"
}
$arguments = [System.Collections.ArrayList]@($choco_path, "pin", $action, "--name", $name)
if ($version) {
$err_msg += " at '$version'"
$arguments.Add("--version") > $null
$arguments.Add($version) > $null
}
$common_args = Get-CommonChocolateyArguments
$arguments.AddRange($common_args)
$command = Argv-ToString -arguments $arguments
$res = Run-Command -command $command
if ($res.rc -ne 0) {
$module.Result.command = $command
$module.Result.rc = $res.rc
$module.Result.stdout = $res.stdout
$module.Result.stderr = $res.stderr
$module.FailJson($err_msg)
}
$module.result.changed = $true
}
Function Update-ChocolateyPackage {
param(
[Parameter(Mandatory=$true)][String]$choco_path,
@ -646,6 +717,30 @@ if ($state -in @("downgrade", "latest", "present", "reinstalled")) {
Update-ChocolateyPackage -packages $installed_packages @common_args
}
}
# Now we want to pin/unpin any packages now that it has been installed/upgraded
if ($null -ne $pinned) {
$pins = Get-ChocolateyPin -choco_path $choco_path
foreach ($package in $name) {
if ($pins.ContainsKey($package)) {
if (-not $pinned -and $null -eq $version) {
# No version is set and pinned=no, we want to remove all pins on the package. There is a bug in
# 'choco pin remove' with multiple versions where an older version might be pinned but
# 'choco pin remove' will still fail without an explicit version. Instead we take the literal
# interpretation that pinned=no and no version means the package has no pins at all
foreach ($v in $pins.$package) {
Set-ChocolateyPin -choco_path $choco_path -name $package -version $v
}
} elseif ($null -ne $version -and $pins.$package.Contains($version) -ne $pinned) {
Set-ChocolateyPin -choco_path $choco_path -name $package -pin:$pinned -version $version
}
} elseif ($pinned) {
# Package had no pins but pinned=yes is set.
Set-ChocolateyPin -choco_path $choco_path -name $package -pin -version $version
}
}
}
}
$module.ExitJson()

View file

@ -101,6 +101,17 @@ options:
type: str
version_added: '2.1'
aliases: [ params ]
pinned:
description:
- Whether to pin the Chocolatey package or not.
- If omitted then no checks on package pins are done.
- Will pin/unpin the specific version if I(version) is set.
- Will pin the latest version of a package if C(yes), I(version) is not set
and and no pin already exists.
- Will unpin all versions of a package if C(no) and I(version) is not set.
- This is ignored when C(state=absent).
type: bool
version_added: '2.8'
proxy_url:
description:
- Proxy URL used to install chocolatey and the package.
@ -328,6 +339,19 @@ EXAMPLES = r'''
become: yes
become_user: Administrator
become_method: runas
- name: install and pin Notepad++ at 7.6.3
win_chocolatey:
name: notepadplusplus
version: 7.6.3
pinned: yes
state: present
- name: remove all pins for Notepad++ on all versions
win_chocolatey:
name: notepadplusplus
pinned: no
state: present
'''
RETURN = r'''

View file

@ -474,6 +474,114 @@
- allow_multiple is changed
- allow_multiple_actual.stdout == "ansible|0.1.0\r\nansible|0.0.1\r\n"
- name: pin 2 packages (check mode)
win_chocolatey:
name:
- '{{ test_choco_package1 }}'
- '{{ test_choco_package2 }}'
state: present
pinned: yes
register: pin_multiple_check
check_mode: True
- name: get result of pin 2 packages (check mode)
win_command: choco.exe pin list --limit-output
register: pin_multiple_actual_check
- name: assert pin 2 packages (check mode)
assert:
that:
- pin_multiple_check is changed
- pin_multiple_actual_check.stdout == ""
- name: pin 2 packages
win_chocolatey:
name:
- '{{ test_choco_package1 }}'
- '{{ test_choco_package2 }}'
state: present
pinned: yes
register: pin_multiple
- name: get result of pin 2 packages
win_command: choco.exe pin list --limit-output
register: pin_multiple_actual
- name: assert pin 2 packages
assert:
that:
- pin_multiple is changed
- pin_multiple_actual.stdout_lines == ["ansible|0.1.0", "ansible-test|1.0.1-beta1"]
- name: pin 2 packages (idempotent)
win_chocolatey:
name:
- '{{ test_choco_package1 }}'
- '{{ test_choco_package2 }}'
state: present
pinned: yes
register: pin_multiple_again
- name: assert pin 2 packages (idempoent)
assert:
that:
- not pin_multiple_again is changed
- name: pin specific older version
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
pinned: yes
version: '0.0.1'
register: pin_older
- name: get result of pin specific older version
win_command: choco.exe pin list --limit-output
register: pin_older_actual
- name: assert pin specific older version
assert:
that:
- pin_older is changed
- pin_older_actual.stdout_lines == ["ansible|0.1.0", "ansible|0.0.1", "ansible-test|1.0.1-beta1"]
- name: unpin package at version
win_chocolatey:
name: '{{ test_choco_package1 }}'
state: present
pinned: no
version: '0.1.0'
register: unpin_version
- name: get result of unpin package at version
win_command: choco.exe pin list --limit-output
register: unpin_version_actual
- name: assert unpin package at version
assert:
that:
- unpin_version is changed
- unpin_version_actual.stdout_lines == ["ansible|0.0.1", "ansible-test|1.0.1-beta1"]
- name: unpin multiple packages without a version
win_chocolatey:
name:
- '{{ test_choco_package1 }}'
- '{{ test_choco_package2 }}'
state: present
pinned: no
register: unpin_multiple
- name: get result of unpin multiple packages without a version
win_command: choco.exe pin list --limit-output
register: unpin_multiple_actual
- name: assert unpin multiple packages without a version
assert:
that:
- unpin_multiple is changed
- unpin_multiple_actual.stdout == ""
- name: uninstall specific version installed with allow_multiple
win_chocolatey:
name: '{{ test_choco_package1 }}'