1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 4# Copyright: (c) 2017 John Kwiatkoski (@JayKayy) <jkwiat40@gmail.com> 5# Copyright: (c) 2018 Alexander Bethke (@oolongbrothers) <oolongbrothers@gmx.net> 6# Copyright: (c) 2017 Ansible Project 7# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 8 9 10# ATTENTION CONTRIBUTORS! 11# 12# TL;DR: Run this module's integration tests manually before opening a pull request 13# 14# Long explanation: 15# The integration tests for this module are currently NOT run on the Ansible project's continuous 16# delivery pipeline. So please: When you make changes to this module, make sure that you run the 17# included integration tests manually for both Python 2 and Python 3: 18# 19# Python 2: 20# ansible-test integration -v --docker fedora28 --docker-privileged --allow-unsupported --python 2.7 flatpak_remote 21# Python 3: 22# ansible-test integration -v --docker fedora28 --docker-privileged --allow-unsupported --python 3.6 flatpak_remote 23# 24# Because of external dependencies, the current integration tests are somewhat too slow and brittle 25# to be included right now. I have plans to rewrite the integration tests based on a local flatpak 26# repository so that they can be included into the normal CI pipeline. 27# //oolongbrothers 28 29 30from __future__ import (absolute_import, division, print_function) 31__metaclass__ = type 32 33ANSIBLE_METADATA = {'metadata_version': '1.1', 34 'status': ['preview'], 35 'supported_by': 'community'} 36 37DOCUMENTATION = r''' 38--- 39module: flatpak_remote 40version_added: '2.6' 41short_description: Manage flatpak repository remotes 42description: 43- Allows users to add or remove flatpak remotes. 44- The flatpak remotes concept is comparable to what is called repositories in other packaging 45 formats. 46- Currently, remote addition is only supported via I(flatpakrepo) file URLs. 47- Existing remotes will not be updated. 48- See the M(flatpak) module for managing flatpaks. 49author: 50- John Kwiatkoski (@JayKayy) 51- Alexander Bethke (@oolongbrothers) 52requirements: 53- flatpak 54options: 55 executable: 56 description: 57 - The path to the C(flatpak) executable to use. 58 - By default, this module looks for the C(flatpak) executable on the path. 59 default: flatpak 60 flatpakrepo_url: 61 description: 62 - The URL to the I(flatpakrepo) file representing the repository remote to add. 63 - When used with I(state=present), the flatpak remote specified under the I(flatpakrepo_url) 64 is added using the specified installation C(method). 65 - When used with I(state=absent), this is not required. 66 - Required when I(state=present). 67 method: 68 description: 69 - The installation method to use. 70 - Defines if the I(flatpak) is supposed to be installed globally for the whole C(system) 71 or only for the current C(user). 72 choices: [ system, user ] 73 default: system 74 name: 75 description: 76 - The desired name for the flatpak remote to be registered under on the managed host. 77 - When used with I(state=present), the remote will be added to the managed host under 78 the specified I(name). 79 - When used with I(state=absent) the remote with that name will be removed. 80 required: true 81 state: 82 description: 83 - Indicates the desired package state. 84 choices: [ absent, present ] 85 default: present 86''' 87 88EXAMPLES = r''' 89- name: Add the Gnome flatpak remote to the system installation 90 flatpak_remote: 91 name: gnome 92 state: present 93 flatpakrepo_url: https://sdk.gnome.org/gnome-apps.flatpakrepo 94 95- name: Add the flathub flatpak repository remote to the user installation 96 flatpak_remote: 97 name: flathub 98 state: present 99 flatpakrepo_url: https://dl.flathub.org/repo/flathub.flatpakrepo 100 method: user 101 102- name: Remove the Gnome flatpak remote from the user installation 103 flatpak_remote: 104 name: gnome 105 state: absent 106 method: user 107 108- name: Remove the flathub remote from the system installation 109 flatpak_remote: 110 name: flathub 111 state: absent 112''' 113 114RETURN = r''' 115command: 116 description: The exact flatpak command that was executed 117 returned: When a flatpak command has been executed 118 type: str 119 sample: "/usr/bin/flatpak remote-add --system flatpak-test https://dl.flathub.org/repo/flathub.flatpakrepo" 120msg: 121 description: Module error message 122 returned: failure 123 type: str 124 sample: "Executable '/usr/local/bin/flatpak' was not found on the system." 125rc: 126 description: Return code from flatpak binary 127 returned: When a flatpak command has been executed 128 type: int 129 sample: 0 130stderr: 131 description: Error output from flatpak binary 132 returned: When a flatpak command has been executed 133 type: str 134 sample: "error: GPG verification enabled, but no summary found (check that the configured URL in remote config is correct)\n" 135stdout: 136 description: Output from flatpak binary 137 returned: When a flatpak command has been executed 138 type: str 139 sample: "flathub\tFlathub\thttps://dl.flathub.org/repo/\t1\t\n" 140''' 141 142import subprocess 143from ansible.module_utils.basic import AnsibleModule 144from ansible.module_utils._text import to_bytes, to_native 145 146 147def add_remote(module, binary, name, flatpakrepo_url, method): 148 """Add a new remote.""" 149 global result 150 command = "{0} remote-add --{1} {2} {3}".format( 151 binary, method, name, flatpakrepo_url) 152 _flatpak_command(module, module.check_mode, command) 153 result['changed'] = True 154 155 156def remove_remote(module, binary, name, method): 157 """Remove an existing remote.""" 158 global result 159 command = "{0} remote-delete --{1} --force {2} ".format( 160 binary, method, name) 161 _flatpak_command(module, module.check_mode, command) 162 result['changed'] = True 163 164 165def remote_exists(module, binary, name, method): 166 """Check if the remote exists.""" 167 command = "{0} remote-list -d --{1}".format(binary, method) 168 # The query operation for the remote needs to be run even in check mode 169 output = _flatpak_command(module, False, command) 170 for line in output.splitlines(): 171 listed_remote = line.split() 172 if len(listed_remote) == 0: 173 continue 174 if listed_remote[0] == to_native(name): 175 return True 176 return False 177 178 179def _flatpak_command(module, noop, command): 180 global result 181 if noop: 182 result['rc'] = 0 183 result['command'] = command 184 return "" 185 186 process = subprocess.Popen( 187 command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) 188 stdout_data, stderr_data = process.communicate() 189 result['rc'] = process.returncode 190 result['command'] = command 191 result['stdout'] = stdout_data 192 result['stderr'] = stderr_data 193 if result['rc'] != 0: 194 module.fail_json(msg="Failed to execute flatpak command", **result) 195 return to_native(stdout_data) 196 197 198def main(): 199 module = AnsibleModule( 200 argument_spec=dict( 201 name=dict(type='str', required=True), 202 flatpakrepo_url=dict(type='str'), 203 method=dict(type='str', default='system', 204 choices=['user', 'system']), 205 state=dict(type='str', default="present", 206 choices=['absent', 'present']), 207 executable=dict(type='str', default="flatpak") 208 ), 209 # This module supports check mode 210 supports_check_mode=True, 211 ) 212 213 name = module.params['name'] 214 flatpakrepo_url = module.params['flatpakrepo_url'] 215 method = module.params['method'] 216 state = module.params['state'] 217 executable = module.params['executable'] 218 binary = module.get_bin_path(executable, None) 219 220 if flatpakrepo_url is None: 221 flatpakrepo_url = '' 222 223 global result 224 result = dict( 225 changed=False 226 ) 227 228 # If the binary was not found, fail the operation 229 if not binary: 230 module.fail_json(msg="Executable '%s' was not found on the system." % executable, **result) 231 232 remote_already_exists = remote_exists(module, binary, to_bytes(name), method) 233 234 if state == 'present' and not remote_already_exists: 235 add_remote(module, binary, name, flatpakrepo_url, method) 236 elif state == 'absent' and remote_already_exists: 237 remove_remote(module, binary, name, method) 238 239 module.exit_json(**result) 240 241 242if __name__ == '__main__': 243 main() 244