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:
parent
be7768efc7
commit
b74295d25f
4 changed files with 229 additions and 0 deletions
2
changelogs/fragments/win_chocolatey-pin.yaml
Normal file
2
changelogs/fragments/win_chocolatey-pin.yaml
Normal 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
|
|
@ -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()
|
||||
|
|
|
@ -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'''
|
||||
|
|
|
@ -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 }}'
|
||||
|
|
Loading…
Reference in a new issue