New module: Add module to install/remove/register/unregiser windows powershell modules (windows/win_psmodule) (#23604)
* Add new windows module win_psmodule * Add checkmode, allow_clobber parameter, integration tests * Add aliases, replace win_raw with win_shell * restore original test_win_group1.yml, add powershel version test * fix var type * add conditional on assert * integration tests conditional tasks review * documentation fix, test fix, adds result.change * fix yml * fix railing whitespace * add nuget_changed and repository_changed in result
This commit is contained in:
parent
1e8c58519e
commit
9d932b64f0
6 changed files with 465 additions and 0 deletions
186
lib/ansible/modules/windows/win_psmodule.ps1
Normal file
186
lib/ansible/modules/windows/win_psmodule.ps1
Normal file
|
@ -0,0 +1,186 @@
|
|||
#!powershell
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Copyright 2017, Daniele Lazzari <lazzari@mailup.com>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# WANT_JSON
|
||||
# POWERSHELL_COMMON
|
||||
|
||||
# win_psmodule (Powershell modules Additions/Removal)
|
||||
|
||||
$params = Parse-Args $args -supports_check_mode $true
|
||||
|
||||
$name = Get-AnsibleParam -obj $params "name" -type "str" -failifempty $true
|
||||
$repo = Get-AnsibleParam -obj $params "repository" -type "str"
|
||||
$url = Get-AnsibleParam -obj $params "url" -type "str"
|
||||
$state = Get-AnsibleParam -obj $params "state" -type "str" -default "present" -validateset "present", "absent"
|
||||
$allow_clobber = Get-AnsibleParam -obj $params "allow_clobber" -type "bool" -default $false
|
||||
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false
|
||||
|
||||
$result = @{"changed" = $false
|
||||
"output" = ""
|
||||
"nuget_changed" = $false
|
||||
"repository_changed" = $false}
|
||||
|
||||
Function Install-NugetProvider {
|
||||
param(
|
||||
[bool]$CheckMode
|
||||
)
|
||||
$PackageProvider = Get-PackageProvider -ListAvailable|?{($_.name -eq 'Nuget') -and ($_.version -ge "2.8.5.201")}
|
||||
if (!($PackageProvider)){
|
||||
try{
|
||||
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction Stop -WhatIf:$CheckMode | out-null
|
||||
$result.changed = $true
|
||||
$result.nuget_changed = $true
|
||||
}
|
||||
catch{
|
||||
$ErrorMessage = "Problems adding package provider: $($_.Exception.Message)"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function Install-Repository {
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Name,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Url,
|
||||
[bool]$CheckMode
|
||||
)
|
||||
$Repo = (Get-PSRepository).SourceLocation
|
||||
|
||||
# If repository isn't already present, try to register it as trusted.
|
||||
if ($Repo -notcontains $Url){
|
||||
try {
|
||||
if (!($CheckMode)) {
|
||||
Register-PSRepository -Name $Name -SourceLocation $Url -InstallationPolicy Trusted -ErrorAction Stop
|
||||
}
|
||||
$result.changed = $true
|
||||
$result.repository_changed = $true
|
||||
}
|
||||
catch {
|
||||
$ErrorMessage = "Problems adding $($Name) repository: $($_.Exception.Message)"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function Remove-Repository{
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Name,
|
||||
[bool]$CheckMode
|
||||
)
|
||||
|
||||
$Repo = (Get-PSRepository).SourceLocation
|
||||
|
||||
# Try to remove the repository
|
||||
if ($Repo -contains $Name){
|
||||
try {
|
||||
if (!($CheckMode)) {
|
||||
Unregister-PSRepository -Name $Name -ErrorAction Stop
|
||||
}
|
||||
$result.changed = $true
|
||||
$result.repository_changed = $true
|
||||
}
|
||||
catch {
|
||||
$ErrorMessage = "Problems removing $($Name)repository: $($_.Exception.Message)"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function Install-PsModule {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Name,
|
||||
[bool]$AllowClobber,
|
||||
[bool]$CheckMode
|
||||
)
|
||||
if (Get-Module -Listavailable|?{$_.name -eq $Name}){
|
||||
$result.output = "Module $($Name) already present"
|
||||
}
|
||||
else {
|
||||
try{
|
||||
# Install NuGet Provider if needed
|
||||
Install-NugetProvider -CheckMode $CheckMode
|
||||
|
||||
# Check Powershell Version (-AllowClobber was introduced in early version only)
|
||||
if ($PsVersion.Minor -ge 1){
|
||||
Install-Module -Name $Name -Force -ErrorAction Stop -Whatif:$CheckMode -AllowClobber:$AllowClobber | out-null
|
||||
}
|
||||
else {
|
||||
Install-Module -Name $Name -Force -ErrorAction Stop -Whatif:$CheckMode | out-null
|
||||
}
|
||||
$result.output = "Module $($Name) installed"
|
||||
$result.changed = $true
|
||||
}
|
||||
catch{
|
||||
$ErrorMessage = "Problems installing $($Name) module: $($_.Exception.Message)"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Function Remove-PsModule {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Name,
|
||||
[bool]$CheckMode
|
||||
)
|
||||
# If module is present, unistalls it.
|
||||
if (Get-Module -Listavailable|?{$_.name -eq $Name}){
|
||||
try{
|
||||
Uninstall-Module -Name $Name -Confirm:$false -Force -ErrorAction Stop -WhatIf:$CheckMode | out-null
|
||||
$result.output = "Module $($Name) removed"
|
||||
$result.changed = $true
|
||||
}
|
||||
catch{
|
||||
$ErrorMessage = "Problems removing $($Name) module: $($_.Exception.Message)"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
$result.output = "Module $($Name) not present"
|
||||
}
|
||||
}
|
||||
|
||||
# Check powershell version, fail if < 5.0
|
||||
$PsVersion = $PSVersionTable.PSVersion
|
||||
if ($PsVersion.Major -lt 5){
|
||||
$ErrorMessage = "Powershell 5.0 or higher is needed"
|
||||
Fail-Json $result $ErrorMessage
|
||||
}
|
||||
|
||||
if ($state -eq "present") {
|
||||
if (($repo) -and ($url)) {
|
||||
Install-Repository -Name $repo -Url $url -CheckMode $check_mode
|
||||
}
|
||||
else {
|
||||
$ErrorMessage = "Repository Name and Url are mandatory if you want to add a new repository"
|
||||
}
|
||||
Install-PsModule -Name $Name -CheckMode $check_mode -AllowClobber $allow_clobber
|
||||
}
|
||||
else {
|
||||
if ($repo) {
|
||||
Remove-Repository -Name $repo -CheckMode $check_mode
|
||||
}
|
||||
Remove-PsModule -Name $Name -CheckMode $check_mode
|
||||
}
|
||||
|
||||
Exit-Json $result
|
109
lib/ansible/modules/windows/win_psmodule.py
Normal file
109
lib/ansible/modules/windows/win_psmodule.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2017, Daniele Lazzari <lazzari@mailup.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/>.
|
||||
|
||||
# this is a windows documentation stub. actual code lives in the .ps1
|
||||
# file of the same name
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: win_psmodule
|
||||
version_added: "2.4"
|
||||
short_description: Adds or removes a Powershell Module.
|
||||
description:
|
||||
- This module helps to install Powershell modules and register custom modules repository on Windows Server.
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of the powershell module that has to be installed.
|
||||
required: true
|
||||
allow_clobber:
|
||||
description:
|
||||
- If yes imports all commands, even if they have the same names as commands that already exists. Available only in Powershell 5.1 or higher.
|
||||
default: no
|
||||
choices:
|
||||
- no
|
||||
- yes
|
||||
repository:
|
||||
description:
|
||||
- Name of the custom repository to register.
|
||||
url:
|
||||
description:
|
||||
- Url of the custom repository.
|
||||
state:
|
||||
description:
|
||||
- If present a new module is installed. If absent a module is removed.
|
||||
default: present
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
notes:
|
||||
- Powershell 5.0 or higer is needed.
|
||||
|
||||
author: Daniele Lazzari
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
---
|
||||
- name: Add a powershell module
|
||||
win_psmodule:
|
||||
name: PowershellModule
|
||||
state: present
|
||||
|
||||
- name: Add a powershell module and register a repository
|
||||
win_psmodule:
|
||||
name: MyCustomModule
|
||||
repository: MyRepository
|
||||
url: https://myrepo.com
|
||||
state: present
|
||||
|
||||
- name: Remove a powershell module
|
||||
win_psmodule:
|
||||
name: PowershellModule
|
||||
state: absent
|
||||
|
||||
- name: Remove a powershell module and a repository
|
||||
win_psmodule:
|
||||
name: MyCustomModule
|
||||
repository: MyRepository
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
output:
|
||||
description: a message describing the task result.
|
||||
returned: always
|
||||
sample: "Module PowerShellCookbook installed"
|
||||
type: string
|
||||
nuget_changed:
|
||||
description: true when Nuget package provider is installed
|
||||
returned: always
|
||||
type: boolean
|
||||
sample: True
|
||||
repository_changed:
|
||||
description: true when a custom repository is installed or removed
|
||||
returned: always
|
||||
type: boolean
|
||||
sample: True
|
||||
'''
|
1
test/integration/targets/win_psmodule/aliases
Normal file
1
test/integration/targets/win_psmodule/aliases
Normal file
|
@ -0,0 +1 @@
|
|||
windows/ci/group1
|
5
test/integration/targets/win_psmodule/defaults/main.yml
Normal file
5
test/integration/targets/win_psmodule/defaults/main.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
|
||||
powershell_module: powershell-yaml
|
||||
wrong_module: powershell_yaml
|
||||
allow_clobber_module: PowerShellCookbook
|
28
test/integration/targets/win_psmodule/tasks/main.yml
Normal file
28
test/integration/targets/win_psmodule/tasks/main.yml
Normal file
|
@ -0,0 +1,28 @@
|
|||
# test code for the win_psmodule module when using winrm connection
|
||||
# (c) 2017, Daniele Lazzari <lazzari@mailup.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: get facts
|
||||
setup:
|
||||
|
||||
- name: Perform integration tests for Powershell 5+
|
||||
when: ansible_powershell_version >= 5
|
||||
block:
|
||||
|
||||
- name: run all tasks
|
||||
include: test.yml
|
136
test/integration/targets/win_psmodule/tasks/test.yml
Normal file
136
test/integration/targets/win_psmodule/tasks/test.yml
Normal file
|
@ -0,0 +1,136 @@
|
|||
---
|
||||
|
||||
- name: install module from Powershell Gallery
|
||||
win_psmodule:
|
||||
name: "{{ powershell_module }}"
|
||||
state: present
|
||||
register: module_setup
|
||||
|
||||
- name: test Powershell Gallery module setup
|
||||
assert:
|
||||
that:
|
||||
- "module_setup|changed"
|
||||
- "module_setup.output == 'Module {{ powershell_module }} installed'"
|
||||
|
||||
- name: check idempotency reinstalling module
|
||||
win_psmodule:
|
||||
name: "{{ powershell_module }}"
|
||||
state: present
|
||||
register: module_reinstall
|
||||
|
||||
- name: test win_psmodule idempotency
|
||||
assert:
|
||||
that:
|
||||
- "not module_reinstall|changed"
|
||||
|
||||
- name: check module install with allow_clobber not active
|
||||
win_psmodule:
|
||||
name: "{{ allow_clobber_module }}"
|
||||
register: fail_allow_clobber
|
||||
ignore_errors: yes
|
||||
|
||||
- name: test allow_clobber has failed
|
||||
assert:
|
||||
that:
|
||||
- "fail_allow_clobber|failed"
|
||||
|
||||
- name: check module install with allow_clobber active
|
||||
win_psmodule:
|
||||
name: "{{ allow_clobber_module }}"
|
||||
allow_clobber: yes
|
||||
register: ok_allow_clobber
|
||||
|
||||
- name: test module install with allow_clobber active
|
||||
assert:
|
||||
that:
|
||||
- "ok_allow_clobber|changed"
|
||||
|
||||
- name: check wrong module install attempt
|
||||
win_psmodule:
|
||||
name: "{{ wrong_module }}"
|
||||
state: present
|
||||
ignore_errors: yes
|
||||
register: module_fail
|
||||
|
||||
- name: test module setup fails
|
||||
assert:
|
||||
that:
|
||||
- "module_fail|failed"
|
||||
|
||||
- name: check fake custom ps repository registration attempt
|
||||
win_psmodule:
|
||||
name: "{{ wrong_module }}"
|
||||
repository: Fake repository
|
||||
url: http://my_fake_repo.com/repo/
|
||||
ignore_errors: yes
|
||||
register: repo_fail
|
||||
|
||||
- name: test fake custom ps repository registration attempt
|
||||
assert:
|
||||
that:
|
||||
- "repo_fail|failed"
|
||||
|
||||
- name: check module is installed
|
||||
win_shell: (Get-Module -Name {{ powershell_module }} -ListAvailable).Name
|
||||
register: module_check
|
||||
|
||||
- name: test module is installed
|
||||
assert:
|
||||
that:
|
||||
- "module_check.stdout_lines[0] == '{{ powershell_module }}'"
|
||||
|
||||
- name: check allow_clobber module is installed
|
||||
win_shell: (Get-Module -Name {{ allow_clobber_module }} -ListAvailable).Name
|
||||
register: allow_clobber_check
|
||||
|
||||
- name: test allow_clobber module is installed
|
||||
assert:
|
||||
that:
|
||||
- "allow_clobber_check.stdout_lines[0] == '{{ allow_clobber_module }}'"
|
||||
|
||||
- name: remove installed powershell module
|
||||
win_psmodule:
|
||||
name: powershell-yaml
|
||||
state: absent
|
||||
register: module_uninstall
|
||||
|
||||
- name: test powershell module removal
|
||||
assert:
|
||||
that:
|
||||
- "module_uninstall|changed"
|
||||
- "module_uninstall.output == 'Module {{ powershell_module }} removed'"
|
||||
|
||||
- name: check module is uninstalled
|
||||
win_shell: (Get-Module -Name {{ powershell_module }} -ListAvailable).Name
|
||||
register: module_check
|
||||
|
||||
- name: test module is no more present
|
||||
assert:
|
||||
that:
|
||||
- "module_check.stdout == ''"
|
||||
|
||||
- name: check idempotency re-removing module
|
||||
win_psmodule:
|
||||
name: "{{ powershell_module }}"
|
||||
state: absent
|
||||
register: module_uninstall_2
|
||||
|
||||
- name: test idempotency
|
||||
assert:
|
||||
that:
|
||||
- "not module_uninstall_2|changed"
|
||||
|
||||
- name: check removing allow_clobber module
|
||||
win_psmodule:
|
||||
name: "{{ allow_clobber_module }}"
|
||||
state: absent
|
||||
register: module_uninstall_3
|
||||
|
||||
- name: test removing allow_clobber module
|
||||
assert:
|
||||
that:
|
||||
- "not module_uninstall_2|changed"
|
||||
- "module_uninstall_3|changed"
|
||||
|
||||
|
||||
|
Loading…
Reference in a new issue