From e4a3e73b15d52f919253df677f79cde46ac4b112 Mon Sep 17 00:00:00 2001 From: Wojciech Sciesinski Date: Tue, 4 Dec 2018 22:47:28 +0100 Subject: [PATCH] Add win_psrepository (#48828) * Add win_psrepository * Small corrections * Correct requiqurements - add NuGet * Extend tests * Post-review updates * Post-review - updates 2 * Add empty RETURN section in documentation * Add empty line at EOF * Post-review updates 3 * Update tests to run in check_mode too * Minor updates * Correct installing/updating NuGet * a few changes for review * Remove copyrights * Revert "Remove copyrights" This reverts commit 2d687ec6a691d8d71358ae447e0fdc828976a767. --- .../modules/windows/win_psrepository.ps1 | 58 +++++ .../modules/windows/win_psrepository.py | 68 ++++++ .../targets/win_psrepository/aliases | 1 + .../win_psrepository/defaults/main.yml | 4 + .../targets/win_psrepository/meta/main.yml | 2 + .../targets/win_psrepository/tasks/main.yml | 41 ++++ .../targets/win_psrepository/tasks/tests.yml | 200 ++++++++++++++++++ 7 files changed, 374 insertions(+) create mode 100644 lib/ansible/modules/windows/win_psrepository.ps1 create mode 100644 lib/ansible/modules/windows/win_psrepository.py create mode 100644 test/integration/targets/win_psrepository/aliases create mode 100644 test/integration/targets/win_psrepository/defaults/main.yml create mode 100644 test/integration/targets/win_psrepository/meta/main.yml create mode 100644 test/integration/targets/win_psrepository/tasks/main.yml create mode 100644 test/integration/targets/win_psrepository/tasks/tests.yml diff --git a/lib/ansible/modules/windows/win_psrepository.ps1 b/lib/ansible/modules/windows/win_psrepository.ps1 new file mode 100644 index 0000000000..7aec08fb24 --- /dev/null +++ b/lib/ansible/modules/windows/win_psrepository.ps1 @@ -0,0 +1,58 @@ +#!powershell + +# Copyright: (c) 2017, Daniele Lazzari +# Copyright: (c) 2018, Wojciech Sciesinski +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#Requires -Module Ansible.ModuleUtils.Legacy + +# win_psrepository (Windows PowerShell repositories Additions/Removals/Updates) + +$params = Parse-Args -arguments $args -supports_check_mode $true +$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false + +$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true +$source = Get-AnsibleParam -obj $params -name "source" -type "str" +$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present", "absent" +$installationpolicy = Get-AnsibleParam -obj $params -name "installation_policy" -type "str" -validateset "trusted", "untrusted" + +$result = @{"changed" = $false} + +$Repo = Get-PSRepository -Name $name -ErrorAction Ignore +if ($state -eq "present") { + if ($null -eq $Repo){ + if ($null -eq $installationpolicy) { + $installationpolicy = "trusted" + } + if (-not $check_mode) { + Register-PSRepository -Name $name -SourceLocation $source -InstallationPolicy $installationpolicy + } + $result.changed = $true + } + else { + $changed_properties = @{} + + if ($Repo.SourceLocation -ne $source) { + $changed_properties.SourceLocation = $source + } + + if ($null -ne $installationpolicy -and $Repo.InstallationPolicy -ne $installationpolicy) { + $changed_properties.InstallationPolicy = $installationpolicy + } + + if ($changed_properties.Count -gt 0) { + if (-not $check_mode) { + Set-PSRepository -Name $name @changed_properties + } + $result.changed = $true + } + } +} +elseif ($state -eq "absent" -and $null -ne $Repo) { + if (-not $check_mode) { + Unregister-PSRepository -Name $name + } + $result.changed = $true +} + +Exit-Json -obj $result diff --git a/lib/ansible/modules/windows/win_psrepository.py b/lib/ansible/modules/windows/win_psrepository.py new file mode 100644 index 0000000000..8a664129d2 --- /dev/null +++ b/lib/ansible/modules/windows/win_psrepository.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2018, Wojciech Sciesinski +# Copyright: (c) 2017, Daniele Lazzari +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# this is a windows documentation stub. actual code lives in the .ps1 +# file of the same name + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: win_psrepository +version_added: "2.8" +short_description: Adds, removes or updates a Windows PowerShell repository. +description: + - This module helps to add, remove and update Windows PowerShell repository on Windows-based systems. +options: + name: + description: + - Name of the repository to work with. + required: yes + source: + description: + - Specifies the URI for discovering and installing modules from this repository. + - A URI can be a NuGet server feed (most common situation), HTTP, HTTPS, FTP or file location. + state: + description: + - If C(present) a new repository is added or updated. + - If C(absent) a repository is removed. + choices: [ absent, present ] + default: present + installation_policy: + description: + - Sets the C(InstallationPolicy) of a repository. + - Will default to C(trusted) when creating a new repository. + choices: [ trusted, untrusted ] +notes: + - The PowerShellGet module (version 1.6.0 or newer) and the NuGet package provider (version 2.8.5.201 or newer) are required. + - See the examples on how to update the NuGet package provider. + - You can't use M(win_psrepository) to re-register (add) removed PSGallery, use the command C(Register-PSRepository -Default) instead. +author: +- Wojciech Sciesinski (@it-praktyk) +''' + +EXAMPLES = r''' +--- +- name: Ensure the required NuGet package provider version is installed + win_shell: Install-PackageProvider -Name NuGet -RequiredVersion 2.8.5.201 -Force + +- name: Add a PowerShell module and register a repository + win_psrepository: + name: MyRepository + source: https://myrepo.com + state: present + +- name: Remove a PowerShell repository + win_psrepository: + name: MyRepository + state: absent +''' + +RETURN = r''' +''' diff --git a/test/integration/targets/win_psrepository/aliases b/test/integration/targets/win_psrepository/aliases new file mode 100644 index 0000000000..423ce39108 --- /dev/null +++ b/test/integration/targets/win_psrepository/aliases @@ -0,0 +1 @@ +shippable/windows/group2 diff --git a/test/integration/targets/win_psrepository/defaults/main.yml b/test/integration/targets/win_psrepository/defaults/main.yml new file mode 100644 index 0000000000..58e1d90ca3 --- /dev/null +++ b/test/integration/targets/win_psrepository/defaults/main.yml @@ -0,0 +1,4 @@ +--- +repository_name: My Get +repository_sourcelocation: https://www.myget.org/F/powershellgetdemo/api/v2 +repository_sourcelocation2: '{{ win_output_dir }}' diff --git a/test/integration/targets/win_psrepository/meta/main.yml b/test/integration/targets/win_psrepository/meta/main.yml new file mode 100644 index 0000000000..bdea853d75 --- /dev/null +++ b/test/integration/targets/win_psrepository/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: +- prepare_win_tests diff --git a/test/integration/targets/win_psrepository/tasks/main.yml b/test/integration/targets/win_psrepository/tasks/main.yml new file mode 100644 index 0000000000..4667bbc7fd --- /dev/null +++ b/test/integration/targets/win_psrepository/tasks/main.yml @@ -0,0 +1,41 @@ +# This file is part of Ansible + +# Copyright: (c) 2018, Wojciech Sciesinski +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +--- + +- name: get PowerShell version + win_shell: '$PSVersionTable.PSVersion.Major' + register: powershell_major_version + +- name: Perform integration tests for Powershell 5+ + when: powershell_major_version.stdout | int >= 5 + block: + + - name: update NuGet version + win_shell: | + $nuget_exists = (Get-PackageProvider | Where-Object { $_.Name -eq 'Nuget' } | Measure-Object).Count -eq 1 + + if ( $nuget_exists ) { + $nuget_outdated = (Get-PackageProvider -Name NuGet -ErrorAction Ignore).Version -lt [Version]"2.8.5.201" + } + + if ( -not $nuget_exists -or $nuget_outdated ) { + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force + } + + - name: ensure test repository is deleted + win_psrepository: + name: '{{ repository_name }}' + state: absent + + - name: run all tests + include_tasks: tests.yml + + always: + + - name: ensure test repository is deleted after tests run + win_psrepository: + name: '{{ repository_name }}' + state: absent diff --git a/test/integration/targets/win_psrepository/tasks/tests.yml b/test/integration/targets/win_psrepository/tasks/tests.yml new file mode 100644 index 0000000000..5dc80fa9af --- /dev/null +++ b/test/integration/targets/win_psrepository/tasks/tests.yml @@ -0,0 +1,200 @@ +# This file is part of Ansible + +# Copyright: (c) 2018, Wojciech Sciesinski +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +--- + +- name: check adding of repository defaults - check mode + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + state: present + check_mode: True + register: adding_repository_check + +- name: get result of adding repository defaults - check mode + win_shell: (Get-PSRepository -Name {{ repository_name | quote }} -ErrorAction ignore | Measure-Object).Count + changed_when: false + register: result_adding_repository_check + +- name: test adding repository defaults - check mode + assert: + that: + - adding_repository_check is changed + - result_adding_repository_check.stdout_lines[0] == '0' + +- name: check adding repository defaults + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + state: present + register: adding_repository + +- name: get result of adding repository defaults + win_shell: | + $repo = Get-PSRepository -Name {{ repository_name | quote }} + ($repo | Measure-Object).Count + $repo.SourceLocation + $repo.InstallationPolicy + register: result_adding_repository + +- name: test adding repository defaults + assert: + that: + - adding_repository is changed + - result_adding_repository.stdout_lines[0] == '1' + - result_adding_repository.stdout_lines[1] == repository_sourcelocation + - result_adding_repository.stdout_lines[2] == 'Trusted' + +- name: check adding repository defaults - idempotent + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + state: present + register: adding_repository_again + +- name: test check adding repository defaults - idempotent + assert: + that: + - adding_repository_again is not changed + +- name: change InstallationPolicy - check mode + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + installation_policy: untrusted + check_mode: True + register: change_installation_policy_check + +- name: get result of change InstallationPolicy - check mode + win_shell: '(Get-PSRepository -Name {{ repository_name | quote }}).InstallationPolicy' + changed_when: false + register: result_change_installation_policy_check + +- name: test change InstallationPolicy - check mode + assert: + that: + - change_installation_policy_check is changed + - result_change_installation_policy_check.stdout | trim == 'Trusted' + +- name: change InstallationPolicy + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + installation_policy: untrusted + register: change_installation_policy + +- name: get result of change InstallationPolicy + win_shell: '(Get-PSRepository -Name {{ repository_name | quote }}).InstallationPolicy' + changed_when: false + register: result_change_installation_policy + +- name: test change InstallationPolicy + assert: + that: + - change_installation_policy is changed + - result_change_installation_policy.stdout | trim == 'Untrusted' + +- name: change InstallationPolicy - idempotent + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation }}" + installation_policy: untrusted + register: change_installation_policy_again + +- name: test change InstallationPolicy - idempotent + assert: + that: + - change_installation_policy_again is not changed + +- name: change source - check mode + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation2 }}" + state: present + check_mode: True + register: change_source_check + +- name: get result of change source - check mode + win_shell: | + $repo = Get-PSRepository -Name {{ repository_name | quote }} + $repo.SourceLocation + $repo.InstallationPolicy + changed_when: False + register: result_change_source_check + +- name: test change source - check mode + assert: + that: + - change_source_check is changed + - result_change_source_check.stdout_lines[0] == repository_sourcelocation + - result_change_source_check.stdout_lines[1] == 'Untrusted' + +- name: change source + win_psrepository: + name: "{{ repository_name }}" + source: "{{ repository_sourcelocation2 }}" + state: present + register: change_source + +- name: get result of change source + win_shell: | + $repo = Get-PSRepository -Name {{ repository_name | quote }} + $repo.SourceLocation + $repo.InstallationPolicy + changed_when: False + register: result_change_source + +- name: test change source + assert: + that: + - change_source is changed + - result_change_source.stdout_lines[0] == repository_sourcelocation2 + - result_change_source.stdout_lines[1] == 'Untrusted' + +- name: remove repository - check mode + win_psrepository: + name: "{{ repository_name }}" + state: absent + check_mode: True + register: removing_repository_check + +- name: get result of remove repository - check mode + win_shell: '(Get-PSRepository -Name {{ repository_name | quote }} -ErrorAction Ignore | Measure-Object).Count' + changed_when: false + register: result_removing_repository_check + +- name: test remove repository - check mode + assert: + that: + - removing_repository_check is changed + - result_removing_repository_check.stdout | trim == '1' + +- name: remove repository + win_psrepository: + name: "{{ repository_name }}" + state: absent + register: removing_repository + +- name: get result of remove repository + win_shell: '(Get-PSRepository -Name {{ repository_name | quote }} -ErrorAction Ignore | Measure-Object).Count' + changed_when: false + register: result_removing_repository + +- name: test remove repository + assert: + that: + - removing_repository is changed + - result_removing_repository.stdout | trim == '0' + +- name: remove repository - idempotent + win_psrepository: + name: "{{ repository_name }}" + state: absent + register: remove_repository_again + +- name: test remove repository - idempotent + assert: + that: + - remove_repository_again is not changed