From 1e8713a50a7cefa0112593a72956c4858ba5833d Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Tue, 18 Jul 2017 22:32:06 +0200 Subject: [PATCH] win_shortcut: Fail when command is not absolute path (#26533) This PR ensures the user gets a proper error when the `src` is not an absolute path. And some cosmetic cleanup, and improve integration tests. --- lib/ansible/modules/windows/win_shortcut.ps1 | 11 +- lib/ansible/modules/windows/win_shortcut.py | 58 ++-- .../targets/win_shortcut/tasks/clean.yml | 27 ++ .../targets/win_shortcut/tasks/main.yml | 181 ++----------- .../targets/win_shortcut/tasks/tests.yml | 249 ++++++++++++++++++ 5 files changed, 345 insertions(+), 181 deletions(-) create mode 100644 test/integration/targets/win_shortcut/tasks/clean.yml create mode 100644 test/integration/targets/win_shortcut/tasks/tests.yml diff --git a/lib/ansible/modules/windows/win_shortcut.ps1 b/lib/ansible/modules/windows/win_shortcut.ps1 index 891fcc89d8e..d1459b5b8fd 100644 --- a/lib/ansible/modules/windows/win_shortcut.ps1 +++ b/lib/ansible/modules/windows/win_shortcut.ps1 @@ -28,13 +28,13 @@ $check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "b $src = Get-AnsibleParam -obj $params -name "src" $dest = Get-AnsibleParam -obj $params -name "dest" -type "path" -failifempty $true -$state = Get-AnsibleParam -obj $params -name "state" -type "string" -default "present" -validateset "present","absent" +$state = Get-AnsibleParam -obj $params -name "state" -type "string" -default "present" -validateset "absent","present" $orig_args = Get-AnsibleParam -obj $params -name "args" -type "string" $directory = Get-AnsibleParam -obj $params -name "directory" -type "path" $hotkey = Get-AnsibleParam -obj $params -name "hotkey" -type "string" $icon = Get-AnsibleParam -obj $params -name "icon" -type "path" $orig_description = Get-AnsibleParam -obj $params -name "description" -type "string" -$windowstyle = Get-AnsibleParam -obj $params -name "windowstyle" -type "string" -validateset "normal","maximized","minimized" +$windowstyle = Get-AnsibleParam -obj $params -name "windowstyle" -type "string" -validateset "maximized","minimized","normal" # Expand environment variables on non-path types $args = Expand-Environment($orig_args) @@ -63,7 +63,7 @@ If ($state -eq "absent") { Remove-Item -Path $dest -WhatIf:$check_mode } Catch { # Report removal failure - Fail-Json $result "Failed to remove shortcut $dest. (" + $_.Exception.Message + ")" + Fail-Json -obj $result -message "Failed to remove shortcut '$dest'. ($($_.Exception.Message))" } # Report removal success $result.changed = $true @@ -82,6 +82,9 @@ If ($state -eq "absent") { If (Get-Command -Name $src -Type Application -ErrorAction SilentlyContinue) { $src = (Get-Command -Name $src -Type Application).Definition } + If (-not (Split-Path -Path $src -IsAbsolute)) { + Fail-Json -obj $result -message "Source '$src' is not found in PATH and not an absolute path." + } } If ($src -ne $null -and $ShortCut.TargetPath -ne $src) { @@ -138,7 +141,7 @@ If ($state -eq "absent") { Try { $ShortCut.Save() } Catch { - Fail-Json $result "Failed to create shortcut $dest. (" + $_.Exception.Message + ")" + Fail-Json -obj $result -message "Failed to create shortcut '$dest'. ($($_.Exception.Message))" } } } diff --git a/lib/ansible/modules/windows/win_shortcut.py b/lib/ansible/modules/windows/win_shortcut.py index 903e21cd3be..c62d6ded603 100644 --- a/lib/ansible/modules/windows/win_shortcut.py +++ b/lib/ansible/modules/windows/win_shortcut.py @@ -34,6 +34,8 @@ options: src: description: - Executable or URL the shortcut points to. + - The executable needs to be in your PATH, or has to be an absolute + path to the executable. description: description: - Description for the shortcut. @@ -42,7 +44,7 @@ options: description: - Destination file for the shortcuting file. - File name should have a C(.lnk) or C(.url) extension. - required: true + required: yes args: description: - Additional arguments for the executable defined in C(src). @@ -51,7 +53,7 @@ options: - Working directory for executable defined in C(src). icon: description: - - Icon used for the shortcut + - Icon used for the shortcut. - File name should have a C(.ico) extension. - The file name is followed by a comma and the number in the library file (.dll) or use 0 for an image file. hotkey: @@ -61,50 +63,56 @@ options: description: - Influences how the application is displayed when it is launched. choices: - - default - maximized - minimized + - normal state: description: - When C(present), creates or updates the shortcut. When C(absent), removes the shortcut if it exists. choices: - - present - absent - default: 'present' -author: Dag Wieers (@dagwieers) + - present + default: present +author: +- Dag Wieers (@dagwieers) notes: - 'The following options can include Windows environment variables: C(dest), C(args), C(description), C(dest), C(directory), C(icon) C(src)' - 'Windows has two types of shortcuts: Application and URL shortcuts. URL shortcuts only consists of C(dest) and C(src)' ''' EXAMPLES = r''' -# Create an application shortcut on the desktop -- win_shortcut: +- name: Create an application shortcut on the desktop + win_shortcut: src: C:\Program Files\Mozilla Firefox\Firefox.exe dest: C:\Users\Public\Desktop\Mozilla Firefox.lnk icon: C:\Program Files\Mozilla Firefox\Firefox.exe,0 -# Create the same shortcut using environment variables -- win_shortcut: +- name: Create the same shortcut using environment variables + win_shortcut: description: The Mozilla Firefox web browser - src: '%PROGRAMFILES%\Mozilla Firefox\Firefox.exe' - dest: '%PUBLIC%\Desktop\Mozilla Firefox.lnk' - icon: '%PROGRAMFILES\Mozilla Firefox\Firefox.exe,0' - directory: '%PROGRAMFILES%\Mozilla Firefox' + src: '%ProgramFiles%\Mozilla Firefox\Firefox.exe' + dest: '%Public%\Desktop\Mozilla Firefox.lnk' + icon: '%ProgramFiles\Mozilla Firefox\Firefox.exe,0' + directory: '%ProgramFiles%\Mozilla Firefox' -# Create a URL shortcut to the Ansible website -- win_shortcut: - src: 'https://ansible.com/' - dest: '%PUBLIC%\Desktop\Ansible website.url' +- name: Create an application shortcut for an executable in PATH to your desktop + win_shortcut: + src: cmd.exe + dest: Desktop\Command prompt.lnk -# Create an application shortcut for the Ansible website -- win_shortcut: - src: '%PROGRAMFILES%\Google\Chrome\Application\chrome.exe' - dest: '%PUBLIC%\Desktop\Ansible website.lnk' - args: '--new-window https://ansible.com/' - directory: '%PROGRAMFILES%\Google\Chrome\Application' - icon: '%PROGRAMFILES%\Google\Chrome\Application\chrome.exe,0' +- name: Create an application shortcut for the Ansible website + win_shortcut: + src: '%ProgramFiles%\Google\Chrome\Application\chrome.exe' + dest: '%UserProfile%\Desktop\Ansible website.lnk' + args: --new-window https://ansible.com/ + directory: '%ProgramFiles%\Google\Chrome\Application' + icon: '%ProgramFiles%\Google\Chrome\Application\chrome.exe,0' + +- name: Create a URL shortcut for the Ansible website + win_shortcut: + src: https://ansible.com/ + dest: '%Public%\Desktop\Ansible website.url' ''' RETURN = ''' diff --git a/test/integration/targets/win_shortcut/tasks/clean.yml b/test/integration/targets/win_shortcut/tasks/clean.yml new file mode 100644 index 00000000000..a5205bca144 --- /dev/null +++ b/test/integration/targets/win_shortcut/tasks/clean.yml @@ -0,0 +1,27 @@ +# Test code for the file module. +# (c) 2017, Dag Wieers + +# 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 . + +- name: Clean up Ansible website link + win_file: + path: '%UserProfile%\Desktop\Ansible website.url' + state: absent + +- name: Clean up Registry Editor shortcut + win_file: + path: '%Public%\Desktop\Registry Editor.lnk' + state: absent diff --git a/test/integration/targets/win_shortcut/tasks/main.yml b/test/integration/targets/win_shortcut/tasks/main.yml index 26f6cd8f717..927ba37d247 100644 --- a/test/integration/targets/win_shortcut/tasks/main.yml +++ b/test/integration/targets/win_shortcut/tasks/main.yml @@ -1,157 +1,34 @@ -- name: Clean up Ansible website link - win_file: - path: '%UserProfile%\Desktop\Ansible website.url' - state: absent +# Test code for the file module. +# (c) 2017, Dag Wieers -- name: Add Ansible website link on the desktop - win_shortcut: - src: 'https://ansible.com/' - dest: '%UserProfile%\Desktop\Ansible website.url' - state: present - register: ansible_website_link_add +# 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 . -- name: Check there was a change - assert: - that: - - ansible_website_link_add.changed == true +- name: Clean slate + include: clean.yml -- name: Add Ansible website link on the desktop again - win_shortcut: - src: 'https://ansible.com/' - dest: '%UserProfile%\Desktop\Ansible website.url' - state: present - register: ansible_website_link_add_again +- name: Test in normal mode + include: tests.yml + vars: + in_check_mode: no -- name: Check there was no change - assert: - that: - - ansible_website_link_add_again.changed == false +- name: Clean slate + include: clean.yml -- name: Remove link - win_shortcut: - dest: '%UserProfile%\Desktop\Ansible website.url' - state: absent - register: ansible_website_link_remove - -- name: Check there was a change - assert: - that: - - ansible_website_link_remove.changed == true - -- name: Remove link again - win_shortcut: - dest: '%UserProfile%\Desktop\Ansible website.url' - state: absent - register: ansible_website_link_remove_again - -- name: Check there was no change - assert: - that: - - ansible_website_link_remove_again.changed == false - -- name: Clean up Registry Editor shortcut - win_file: - path: '%Public%\Desktop\Registry Editor.lnk' - state: absent - -- name: Add a regedit shortcut on the desktop - win_shortcut: - description: "Registry Editor" - src: regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - state: present - register: regedit_shortcut_add - -- name: Check there was a change - assert: - that: - - regedit_shortcut_add.changed == true - -- name: Add a regedit shortcut on the desktop again - win_shortcut: - description: "Registry Editor" - src: regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - state: present - register: regedit_shortcut_add_again - -- name: Check there was no change - assert: - that: - - regedit_shortcut_add_again.changed == false - -- name: Update a regedit shortcut on the desktop - win_shortcut: - description: "Registry Editor" - src: C:\BogusPath\regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - state: present - register: regedit_shortcut_update - -- name: Check there was a change - assert: - that: - - regedit_shortcut_update.changed == true - -- name: Update a regedit shortcut on the desktop again - win_shortcut: - description: "Registry Editor" - src: C:\BogusPath\regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - state: present - register: regedit_shortcut_update_again - -- name: Check there was no change - assert: - that: - - regedit_shortcut_update_again.changed == false - -- name: Add an (explicit) icon - win_shortcut: - description: "Registry Editor" - src: C:\Windows\regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - icon: 'C:\Windows\regedit.exe,0' - state: present - register: regedit_shortcut_add_icon - -- name: Check there was a change - assert: - that: - - regedit_shortcut_add_icon.changed == true - -- name: Add an (explicit) icon again - win_shortcut: - description: "Registry Editor" - src: C:\Windows\regedit.exe - dest: '%Public%\Desktop\Registry Editor.lnk' - icon: 'C:\Windows\regedit.exe,0' - state: present - register: regedit_shortcut_add_icon_again - -- name: Check there was no change - assert: - that: - - regedit_shortcut_add_icon_again.changed == false - -- name: Remove shortcut - win_shortcut: - dest: '%Public%\Desktop\Registry Editor.lnk' - state: absent - register: regedit_shortcut_remove - -- name: Check there was a change - assert: - that: - - regedit_shortcut_remove.changed == true - -- name: Remove shortcut again - win_shortcut: - dest: '%Public%\Desktop\Registry Editor.lnk' - state: absent - register: regedit_shortcut_remove_again - -- name: Check there was no change - assert: - that: - - regedit_shortcut_remove_again.changed == false \ No newline at end of file +- name: Test in check-mode + include: tests.yml + vars: + in_check_mode: yes + check_mode: yes diff --git a/test/integration/targets/win_shortcut/tasks/tests.yml b/test/integration/targets/win_shortcut/tasks/tests.yml new file mode 100644 index 00000000000..c0534d933f4 --- /dev/null +++ b/test/integration/targets/win_shortcut/tasks/tests.yml @@ -0,0 +1,249 @@ +# Test code for the file module. +# (c) 2017, Dag Wieers + +# 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 . + +- name: Add Ansible website link on the desktop + win_shortcut: + src: https://ansible.com/ + dest: '%UserProfile%\Desktop\Ansible website.url' + state: present + register: ansible_website_link_add + +- name: Check there was a change + assert: + that: + - ansible_website_link_add.changed == true + - ansible_website_link_add.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + - ansible_website_link_add.src == 'https://ansible.com/' + +- name: Add Ansible website link on the desktop again + win_shortcut: + src: https://ansible.com/ + dest: '%UserProfile%\Desktop\Ansible website.url' + state: present + register: ansible_website_link_add_again + +- name: Check there was no change (normal mode) + assert: + that: + - ansible_website_link_add_again.changed == false + - ansible_website_link_add_again.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + - ansible_website_link_add_again.src == 'https://ansible.com/' + when: not in_check_mode + +- name: Check there was a change (check-mode) + assert: + that: + - ansible_website_link_add_again.changed == true + - ansible_website_link_add_again.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + - ansible_website_link_add_again.src == 'https://ansible.com/' + when: in_check_mode + +- name: Remove link + win_shortcut: + dest: '%UserProfile%\Desktop\Ansible website.url' + state: absent + register: ansible_website_link_remove + +- name: Check there was a change (normal mode) + assert: + that: + - ansible_website_link_remove.changed == true + - ansible_website_link_remove.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + when: not in_check_mode + +- name: Check there was no change (check-mode) + assert: + that: + - ansible_website_link_remove.changed == false + - ansible_website_link_remove.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + when: in_check_mode + +- name: Remove link again + win_shortcut: + dest: '%UserProfile%\Desktop\Ansible website.url' + state: absent + register: ansible_website_link_remove_again + +- name: Check there was no change + assert: + that: + - ansible_website_link_remove_again.changed == false + - ansible_website_link_remove_again.dest == 'C:\\Users\\Administrator\\Desktop\\Ansible website.url' + +- name: Add a regedit shortcut on the desktop + win_shortcut: + description: "Registry Editor" + src: regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + state: present + register: regedit_shortcut_add + +- name: Check there was a change + assert: + that: + - regedit_shortcut_add.changed == true + - regedit_shortcut_add.description == 'Registry Editor' + - regedit_shortcut_add.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add.src == 'C:\\Windows\\regedit.exe' + +- name: Add a regedit shortcut on the desktop again + win_shortcut: + description: "Registry Editor" + src: regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + state: present + register: regedit_shortcut_add_again + +- name: Check there was no change (normal mode) + assert: + that: + - regedit_shortcut_add_again.changed == false + - regedit_shortcut_add_again.description == 'Registry Editor' + - regedit_shortcut_add_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add_again.src == 'C:\\Windows\\regedit.exe' + when: not in_check_mode + +- name: Check there was a change (check-mode) + assert: + that: + - regedit_shortcut_add_again.changed == true + - regedit_shortcut_add_again.description == 'Registry Editor' + - regedit_shortcut_add_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add_again.src == 'C:\\Windows\\regedit.exe' + when: in_check_mode + +- name: Update a regedit shortcut on the desktop + win_shortcut: + description: "Registry Editor" + src: C:\BogusPath\regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + state: present + register: regedit_shortcut_update + +- name: Check there was a change + assert: + that: + - regedit_shortcut_update.changed == true + - regedit_shortcut_update.description == 'Registry Editor' + - regedit_shortcut_update.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_update.src == 'C:\\BogusPath\\regedit.exe' + +- name: Update a regedit shortcut on the desktop again + win_shortcut: + description: "Registry Editor" + src: C:\BogusPath\regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + state: present + register: regedit_shortcut_update_again + +- name: Check there was no change (normal mode) + assert: + that: + - regedit_shortcut_update_again.changed == false + - regedit_shortcut_update_again.description == 'Registry Editor' + - regedit_shortcut_update_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_update_again.src == 'C:\\BogusPath\\regedit.exe' + when: not in_check_mode + +- name: Check there was a change (check-mode) + assert: + that: + - regedit_shortcut_update_again.changed == true + - regedit_shortcut_update_again.description == 'Registry Editor' + - regedit_shortcut_update_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_update_again.src == 'C:\\BogusPath\\regedit.exe' + when: in_check_mode + +- name: Add an (explicit) icon + win_shortcut: + description: "Registry Editor" + src: C:\Windows\regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + icon: 'C:\Windows\regedit.exe,0' + state: present + register: regedit_shortcut_add_icon + +- name: Check there was a change + assert: + that: + - regedit_shortcut_add_icon.changed == true + - regedit_shortcut_add_icon.description == 'Registry Editor' + - regedit_shortcut_add_icon.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add_icon.icon == 'C:\\Windows\\regedit.exe,0' + - regedit_shortcut_add_icon.src == 'C:\\Windows\\regedit.exe' + +- name: Add an (explicit) icon again + win_shortcut: + description: "Registry Editor" + src: C:\Windows\regedit.exe + dest: '%Public%\Desktop\Registry Editor.lnk' + icon: 'C:\Windows\regedit.exe,0' + state: present + register: regedit_shortcut_add_icon_again + +- name: Check there was no change (normal mode) + assert: + that: + - regedit_shortcut_add_icon_again.changed == false + - regedit_shortcut_add_icon_again.description == 'Registry Editor' + - regedit_shortcut_add_icon_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add_icon_again.icon == 'C:\\Windows\\regedit.exe,0' + - regedit_shortcut_add_icon_again.src == 'C:\\Windows\\regedit.exe' + when: not in_check_mode + +- name: Check there was a change (check-mode) + assert: + that: + - regedit_shortcut_add_icon_again.changed == true + - regedit_shortcut_add_icon_again.description == 'Registry Editor' + - regedit_shortcut_add_icon_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + - regedit_shortcut_add_icon_again.icon == 'C:\\Windows\\regedit.exe,0' + - regedit_shortcut_add_icon_again.src == 'C:\\Windows\\regedit.exe' + when: in_check_mode + +- name: Remove shortcut + win_shortcut: + dest: '%Public%\Desktop\Registry Editor.lnk' + state: absent + register: regedit_shortcut_remove + +- name: Check there was a change (normal mode) + assert: + that: + - regedit_shortcut_remove.changed == true + - regedit_shortcut_remove.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + when: not in_check_mode + +- name: Check there was no change (check-mode) + assert: + that: + - regedit_shortcut_remove.changed == false + - regedit_shortcut_remove.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk' + when: in_check_mode + +- name: Remove shortcut again + win_shortcut: + dest: '%Public%\Desktop\Registry Editor.lnk' + state: absent + register: regedit_shortcut_remove_again + +- name: Check there was no change + assert: + that: + - regedit_shortcut_remove_again.changed == false + - regedit_shortcut_remove_again.dest == 'C:\\Users\\Public\\Desktop\\Registry Editor.lnk'