Skip to content

Commit

Permalink
New module: Add module to install/remove/register/unregiser windows p…
Browse files Browse the repository at this point in the history
…owershell modules (windows/win_psmodule) (ansible#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
  • Loading branch information
dlazz authored and trondhindenes committed Jun 26, 2017
1 parent 1e8c585 commit 9d932b6
Show file tree
Hide file tree
Showing 6 changed files with 465 additions and 0 deletions.
186 changes: 186 additions & 0 deletions lib/ansible/modules/windows/win_psmodule.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#!powershell
# This file is part of Ansible
#
# Copyright 2017, Daniele Lazzari <[email protected]>
#
# 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 changes: 109 additions & 0 deletions lib/ansible/modules/windows/win_psmodule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# (c) 2017, Daniele Lazzari <[email protected]>
#
# 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 change: 1 addition & 0 deletions test/integration/targets/win_psmodule/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
windows/ci/group1
5 changes: 5 additions & 0 deletions test/integration/targets/win_psmodule/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

powershell_module: powershell-yaml
wrong_module: powershell_yaml
allow_clobber_module: PowerShellCookbook
28 changes: 28 additions & 0 deletions test/integration/targets/win_psmodule/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# test code for the win_psmodule module when using winrm connection
# (c) 2017, Daniele Lazzari <[email protected]>

# 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
Loading

0 comments on commit 9d932b6

Please sign in to comment.