1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-04-15 16:31:30 +00:00

Reformat everything.

This commit is contained in:
Felix Fontein 2025-11-01 12:08:41 +01:00
parent 3f2213791a
commit 340ff8586d
1008 changed files with 61301 additions and 58309 deletions

View file

@ -359,20 +359,22 @@ class JenkinsPlugin:
# Shortcuts for the params
self.params = self.module.params
self.url = self.params['url']
self.timeout = self.params['timeout']
self.url = self.params["url"]
self.timeout = self.params["timeout"]
# Authentication for non-Jenkins calls
self.updates_url_credentials = {}
if self.params.get('updates_url_username') and self.params.get('updates_url_password'):
self.updates_url_credentials["Authorization"] = basic_auth_header(self.params['updates_url_username'], self.params['updates_url_password'])
if self.params.get("updates_url_username") and self.params.get("updates_url_password"):
self.updates_url_credentials["Authorization"] = basic_auth_header(
self.params["updates_url_username"], self.params["updates_url_password"]
)
# Crumb
self.crumb = {}
# Authentication for Jenkins calls
if self.params.get('url_username') and self.params.get('url_password'):
self.crumb["Authorization"] = basic_auth_header(self.params['url_username'], self.params['url_password'])
if self.params.get("url_username") and self.params.get("url_password"):
self.crumb["Authorization"] = basic_auth_header(self.params["url_username"], self.params["url_password"])
# Cookie jar for crumb session
self.cookies = None
@ -385,15 +387,12 @@ class JenkinsPlugin:
self._get_installed_plugins()
def _csrf_enabled(self):
csrf_data = self._get_json_data(
f"{self.url}/api/json", 'CSRF')
csrf_data = self._get_json_data(f"{self.url}/api/json", "CSRF")
if 'useCrumbs' not in csrf_data:
self.module.fail_json(
msg="Required fields not found in the Crumbs response.",
details=csrf_data)
if "useCrumbs" not in csrf_data:
self.module.fail_json(msg="Required fields not found in the Crumbs response.", details=csrf_data)
return csrf_data['useCrumbs']
return csrf_data["useCrumbs"]
def _get_json_data(self, url, what, **kwargs):
# Get the JSON data
@ -403,9 +402,7 @@ class JenkinsPlugin:
try:
json_data = json.loads(to_native(r.read()))
except Exception as e:
self.module.fail_json(
msg=f"Cannot parse {what} JSON data.",
details=to_native(e))
self.module.fail_json(msg=f"Cannot parse {what} JSON data.", details=to_native(e))
return json_data
@ -424,17 +421,21 @@ class JenkinsPlugin:
self.module.debug(f"fetching url: {url}")
is_jenkins_call = url.startswith(self.url)
self.module.params['force_basic_auth'] = is_jenkins_call
self.module.params["force_basic_auth"] = is_jenkins_call
response, info = fetch_url(
self.module, url, timeout=self.timeout, cookies=self.cookies,
self.module,
url,
timeout=self.timeout,
cookies=self.cookies,
headers=self.crumb if is_jenkins_call else self.updates_url_credentials or self.crumb,
**kwargs)
if info['status'] == 200:
**kwargs,
)
if info["status"] == 200:
return response
else:
err_msg = f"{msg_status}. fetching url {url} failed. response code: {info['status']}"
if info['status'] > 400: # extend error message
if info["status"] > 400: # extend error message
err_msg = f"{err_msg}. response body: {info['body']}"
except Exception as e:
err_msg = f"{msg_status}. fetching url {url} failed. error msg: {e}"
@ -446,9 +447,7 @@ class JenkinsPlugin:
# failed on all urls
self.module.fail_json(msg=msg_exception, details=errors)
def _get_url_data(
self, url, what=None, msg_status=None, msg_exception=None,
dont_fail=False, **kwargs):
def _get_url_data(self, url, what=None, msg_status=None, msg_exception=None, dont_fail=False, **kwargs):
# Compose default messages
if msg_status is None:
msg_status = f"Cannot get {what}"
@ -459,18 +458,22 @@ class JenkinsPlugin:
# Get the URL data
try:
is_jenkins_call = url.startswith(self.url)
self.module.params['force_basic_auth'] = is_jenkins_call
self.module.params["force_basic_auth"] = is_jenkins_call
response, info = fetch_url(
self.module, url, timeout=self.timeout, cookies=self.cookies,
self.module,
url,
timeout=self.timeout,
cookies=self.cookies,
headers=self.crumb if is_jenkins_call else self.updates_url_credentials or self.crumb,
**kwargs)
**kwargs,
)
if info['status'] != 200:
if info["status"] != 200:
if dont_fail:
raise FailedInstallingWithPluginManager(info['msg'])
raise FailedInstallingWithPluginManager(info["msg"])
else:
self.module.fail_json(msg=msg_status, details=info['msg'])
self.module.fail_json(msg=msg_status, details=info["msg"])
except Exception as e:
if dont_fail:
raise FailedInstallingWithPluginManager(e)
@ -480,39 +483,34 @@ class JenkinsPlugin:
return response
def _get_crumb(self):
crumb_data = self._get_json_data(
f"{self.url}/crumbIssuer/api/json", 'Crumb')
crumb_data = self._get_json_data(f"{self.url}/crumbIssuer/api/json", "Crumb")
if 'crumbRequestField' in crumb_data and 'crumb' in crumb_data:
self.crumb[crumb_data['crumbRequestField']] = crumb_data['crumb']
if "crumbRequestField" in crumb_data and "crumb" in crumb_data:
self.crumb[crumb_data["crumbRequestField"]] = crumb_data["crumb"]
else:
self.module.fail_json(
msg="Required fields not found in the Crum response.",
details=crumb_data)
self.module.fail_json(msg="Required fields not found in the Crum response.", details=crumb_data)
def _get_installed_plugins(self):
plugins_data = self._get_json_data(
f"{self.url}/pluginManager/api/json?depth=1",
'list of plugins')
plugins_data = self._get_json_data(f"{self.url}/pluginManager/api/json?depth=1", "list of plugins")
# Check if we got valid data
if 'plugins' not in plugins_data:
if "plugins" not in plugins_data:
self.module.fail_json(msg="No valid plugin data found.")
# Create final list of installed/pined plugins
self.is_installed = False
self.is_pinned = False
self.is_enabled = False
self.installed_plugins = plugins_data['plugins']
self.installed_plugins = plugins_data["plugins"]
for p in plugins_data['plugins']:
if p['shortName'] == self.params['name']:
for p in plugins_data["plugins"]:
if p["shortName"] == self.params["name"]:
self.is_installed = True
if p['pinned']:
if p["pinned"]:
self.is_pinned = True
if p['enabled']:
if p["enabled"]:
self.is_enabled = True
break
@ -522,50 +520,36 @@ class JenkinsPlugin:
self.dependencies_states = []
for dep_name, dep_version in dependencies.items():
if not any(p['shortName'] == dep_name and p['version'] == dep_version for p in self.installed_plugins):
if not any(p["shortName"] == dep_name and p["version"] == dep_version for p in self.installed_plugins):
dep_params = self.params.copy()
dep_params['name'] = dep_name
dep_params['version'] = dep_version
dep_params["name"] = dep_name
dep_params["version"] = dep_version
dep_module = AnsibleModule(
argument_spec=self.module.argument_spec,
supports_check_mode=self.module.check_mode
argument_spec=self.module.argument_spec, supports_check_mode=self.module.check_mode
)
dep_module.params = dep_params
dep_plugin = JenkinsPlugin(dep_module)
if not dep_plugin.install():
self.dependencies_states.append(
{
'name': dep_name,
'version': dep_version,
'state': 'absent'})
self.dependencies_states.append({"name": dep_name, "version": dep_version, "state": "absent"})
else:
self.dependencies_states.append(
{
'name': dep_name,
'version': dep_version,
'state': 'present'})
self.dependencies_states.append({"name": dep_name, "version": dep_version, "state": "present"})
else:
self.dependencies_states.append(
{
'name': dep_name,
'version': dep_version,
'state': 'present'})
self.dependencies_states.append({"name": dep_name, "version": dep_version, "state": "present"})
def _install_with_plugin_manager(self):
if not self.module.check_mode:
# Install the plugin (with dependencies)
install_script = (
f"""d = Jenkins.instance.updateCenter.getPlugin("{self.params['name']}").deploy(); d.get();""")
f"""d = Jenkins.instance.updateCenter.getPlugin("{self.params["name"]}").deploy(); d.get();"""
)
if self.params['with_dependencies']:
if self.params["with_dependencies"]:
install_script = (
'Jenkins.instance.updateCenter.getPlugin("%s")'
'.getNeededDependencies().each{it.deploy()}; %s' % (
self.params['name'], install_script))
".getNeededDependencies().each{it.deploy()}; %s" % (self.params["name"], install_script)
)
script_data = {
'script': install_script
}
script_data = {"script": install_script}
data = urlencode(script_data)
# Send the installation request
@ -574,7 +558,8 @@ class JenkinsPlugin:
msg_status="Cannot install plugin.",
msg_exception="Plugin installation has failed.",
data=data,
dont_fail=True)
dont_fail=True,
)
hpi_file = f"{self.params['jenkins_home']}/plugins/{self.params['name']}.hpi"
@ -583,10 +568,9 @@ class JenkinsPlugin:
def install(self):
changed = False
plugin_file = (
f"{self.params['jenkins_home']}/plugins/{self.params['name']}.jpi")
plugin_file = f"{self.params['jenkins_home']}/plugins/{self.params['name']}.jpi"
if not self.is_installed and self.params['version'] in [None, 'latest']:
if not self.is_installed and self.params["version"] in [None, "latest"]:
try:
self._install_with_plugin_manager()
changed = True
@ -595,32 +579,31 @@ class JenkinsPlugin:
if not changed:
# Check if the plugin directory exists
if not os.path.isdir(self.params['jenkins_home']):
self.module.fail_json(
msg="Jenkins home directory doesn't exist.")
if not os.path.isdir(self.params["jenkins_home"]):
self.module.fail_json(msg="Jenkins home directory doesn't exist.")
checksum_old = None
if os.path.isfile(plugin_file):
# Make the checksum of the currently installed plugin
with open(plugin_file, 'rb') as plugin_fh:
with open(plugin_file, "rb") as plugin_fh:
plugin_content = plugin_fh.read()
checksum_old = hashlib.sha1(plugin_content).hexdigest()
# Install dependencies
if self.params['with_dependencies']:
if self.params["with_dependencies"]:
self._install_dependencies()
if self.params['version'] in [None, 'latest']:
if self.params["version"] in [None, "latest"]:
# Take latest version
plugin_urls = self._get_latest_plugin_urls()
else:
# Take specific version
plugin_urls = self._get_versioned_plugin_urls()
if (
self.params['updates_expiration'] == 0 or
self.params['version'] not in [None, 'latest'] or
checksum_old is None):
self.params["updates_expiration"] == 0
or self.params["version"] not in [None, "latest"]
or checksum_old is None
):
# Download the plugin file directly
r = self._download_plugin(plugin_urls)
@ -645,12 +628,12 @@ class JenkinsPlugin:
self._write_file(plugin_file, data)
changed = True
elif self.params['version'] == 'latest':
elif self.params["version"] == "latest":
# Check for update from the updates JSON file
plugin_data = self._download_updates()
# If the latest version changed, download it
if checksum_old != to_bytes(plugin_data['sha1']):
if checksum_old != to_bytes(plugin_data["sha1"]):
if not self.module.check_mode:
r = self._download_plugin(plugin_urls)
self._write_file(plugin_file, r)
@ -659,16 +642,13 @@ class JenkinsPlugin:
# Change file attributes if needed
if os.path.isfile(plugin_file):
params = {
'dest': plugin_file
}
params = {"dest": plugin_file}
params.update(self.params)
file_args = self.module.load_file_common_arguments(params)
if not self.module.check_mode:
# Not sure how to run this in the check mode
changed = self.module.set_fs_attributes_if_different(
file_args, changed)
changed = self.module.set_fs_attributes_if_different(file_args, changed)
else:
# See the comment above
changed = True
@ -677,22 +657,22 @@ class JenkinsPlugin:
def _get_latest_plugin_urls(self):
urls = []
for base_url in self.params['updates_url']:
for update_segment in self.params['latest_plugins_url_segments']:
for base_url in self.params["updates_url"]:
for update_segment in self.params["latest_plugins_url_segments"]:
urls.append(f"{base_url}/{update_segment}/{self.params['name']}.hpi")
return urls
def _get_latest_compatible_plugin_version(self, plugin_name=None):
if not hasattr(self, 'jenkins_version'):
self.module.params['force_basic_auth'] = True
if not hasattr(self, "jenkins_version"):
self.module.params["force_basic_auth"] = True
resp, info = fetch_url(self.module, self.url)
raw_version = info.get("x-jenkins")
self.jenkins_version = self.parse_version(raw_version)
name = plugin_name or self.params['name']
name = plugin_name or self.params["name"]
cache_path = f"{self.params['jenkins_home']}/ansible_jenkins_plugin_cache.json"
plugin_version_urls = []
for base_url in self.params['updates_url']:
for update_json in self.params['plugin_versions_url_segment']:
for base_url in self.params["updates_url"]:
for update_json in self.params["plugin_versions_url_segment"]:
plugin_version_urls.append(f"{base_url}/{update_json}")
try: # Check if file is saved localy
@ -727,29 +707,30 @@ class JenkinsPlugin:
for idx, (version_title, version_info) in enumerate(sorted_versions):
required_core = version_info.get("requiredCore", "0.0")
if self.parse_version(required_core) <= self.jenkins_version:
return 'latest' if idx == 0 else version_title
return "latest" if idx == 0 else version_title
self.module.warn(
f"No compatible version found for plugin '{name}'. Installing latest version.")
return 'latest'
self.module.warn(f"No compatible version found for plugin '{name}'. Installing latest version.")
return "latest"
def _get_versioned_plugin_urls(self):
urls = []
for base_url in self.params['updates_url']:
for versioned_segment in self.params['versioned_plugins_url_segments']:
urls.append(f"{base_url}/{versioned_segment}/{self.params['name']}/{self.params['version']}/{self.params['name']}.hpi")
for base_url in self.params["updates_url"]:
for versioned_segment in self.params["versioned_plugins_url_segments"]:
urls.append(
f"{base_url}/{versioned_segment}/{self.params['name']}/{self.params['version']}/{self.params['name']}.hpi"
)
return urls
def _get_update_center_urls(self):
urls = []
for base_url in self.params['updates_url']:
for update_json in self.params['update_json_url_segment']:
for base_url in self.params["updates_url"]:
for update_json in self.params["update_json_url_segment"]:
urls.append(f"{base_url}/{update_json}")
return urls
def _get_versioned_dependencies(self):
# Get dependencies for the specified plugin version
plugin_data = self._download_updates()['dependencies']
plugin_data = self._download_updates()["dependencies"]
dependencies_info = {
dep["name"]: self._get_latest_compatible_plugin_version(dep["name"])
@ -761,11 +742,9 @@ class JenkinsPlugin:
def _download_updates(self):
try:
updates_file, download_updates = download_updates_file(self.params['updates_expiration'])
updates_file, download_updates = download_updates_file(self.params["updates_expiration"])
except OSError as e:
self.module.fail_json(
msg="Cannot create temporal directory.",
details=to_native(e))
self.module.fail_json(msg="Cannot create temporal directory.", details=to_native(e))
# Download the updates file if needed
if download_updates:
@ -773,9 +752,8 @@ class JenkinsPlugin:
# Get the data
r = self._get_urls_data(
urls,
msg_status="Remote updates not found.",
msg_exception="Updates download failed.")
urls, msg_status="Remote updates not found.", msg_exception="Updates download failed."
)
# Write the updates file
tmp_update_fd, tmp_updates_file = tempfile.mkstemp()
@ -785,14 +763,14 @@ class JenkinsPlugin:
os.close(tmp_update_fd)
except IOError as e:
self.module.fail_json(
msg=f"Cannot close the tmp updates file {tmp_updates_file}.",
details=to_native(e))
msg=f"Cannot close the tmp updates file {tmp_updates_file}.", details=to_native(e)
)
else:
tmp_updates_file = updates_file
# Open the updates file
try:
f = io.open(tmp_updates_file, encoding='utf-8')
f = io.open(tmp_updates_file, encoding="utf-8")
# Read only the second line
dummy = f.readline()
@ -800,29 +778,28 @@ class JenkinsPlugin:
except IOError as e:
self.module.fail_json(
msg=f"Cannot open{' temporary' if tmp_updates_file != updates_file else ''} updates file.",
details=to_native(e))
details=to_native(e),
)
except Exception as e:
self.module.fail_json(
msg=f"Cannot load JSON data from the{' temporary' if tmp_updates_file != updates_file else ''} updates file.",
details=to_native(e))
details=to_native(e),
)
# Move the updates file to the right place if we could read it
if tmp_updates_file != updates_file:
self.module.atomic_move(os.path.abspath(tmp_updates_file), os.path.abspath(updates_file))
# Check if we have the plugin data available
if not data.get('plugins', {}).get(self.params['name']):
if not data.get("plugins", {}).get(self.params["name"]):
self.module.fail_json(msg="Cannot find plugin data in the updates file.")
return data['plugins'][self.params['name']]
return data["plugins"][self.params["name"]]
def _download_plugin(self, plugin_urls):
# Download the plugin
return self._get_urls_data(
plugin_urls,
msg_status="Plugin not found.",
msg_exception="Plugin download failed.")
return self._get_urls_data(plugin_urls, msg_status="Plugin not found.", msg_exception="Plugin download failed.")
def _write_file(self, f, data):
# Store the plugin into a temp file and then move it
@ -836,9 +813,7 @@ class JenkinsPlugin:
try:
os.close(tmp_f_fd)
except IOError as e:
self.module.fail_json(
msg=f'Cannot close the temporal plugin file {tmp_f}.',
details=to_native(e))
self.module.fail_json(msg=f"Cannot close the temporal plugin file {tmp_f}.", details=to_native(e))
# Move the file onto the right place
self.module.atomic_move(os.path.abspath(tmp_f), os.path.abspath(f))
@ -849,26 +824,23 @@ class JenkinsPlugin:
# Perform the action
if self.is_installed:
if not self.module.check_mode:
self._pm_query('doUninstall', 'Uninstallation')
self._pm_query("doUninstall", "Uninstallation")
changed = True
return changed
def pin(self):
return self._pinning('pin')
return self._pinning("pin")
def unpin(self):
return self._pinning('unpin')
return self._pinning("unpin")
def _pinning(self, action):
changed = False
# Check if the plugin is pinned/unpinned
if (
action == 'pin' and not self.is_pinned or
action == 'unpin' and self.is_pinned):
if action == "pin" and not self.is_pinned or action == "unpin" and self.is_pinned:
# Perform the action
if not self.module.check_mode:
self._pm_query(action, f"{action.capitalize()}ning")
@ -878,24 +850,19 @@ class JenkinsPlugin:
return changed
def enable(self):
return self._enabling('enable')
return self._enabling("enable")
def disable(self):
return self._enabling('disable')
return self._enabling("disable")
def _enabling(self, action):
changed = False
# Check if the plugin is pinned/unpinned
if (
action == 'enable' and not self.is_enabled or
action == 'disable' and self.is_enabled):
if action == "enable" and not self.is_enabled or action == "disable" and self.is_enabled:
# Perform the action
if not self.module.check_mode:
self._pm_query(
f"make{action.capitalize()}d",
f"{action[:-1].capitalize()}ing")
self._pm_query(f"make{action.capitalize()}d", f"{action[:-1].capitalize()}ing")
changed = True
@ -906,51 +873,45 @@ class JenkinsPlugin:
# Send the request
self._get_url_data(
url,
msg_status=f"Plugin not found. {url}",
msg_exception=f"{msg} has failed.",
method="POST")
url, msg_status=f"Plugin not found. {url}", msg_exception=f"{msg} has failed.", method="POST"
)
@staticmethod
def parse_version(version_str):
return tuple(int(x) for x in version_str.split('.'))
return tuple(int(x) for x in version_str.split("."))
def main():
# Module arguments
argument_spec = url_argument_spec()
argument_spec.update(
group=dict(type='str', default='jenkins'),
jenkins_home=dict(type='path', default='/var/lib/jenkins'),
mode=dict(default='0644', type='raw'),
name=dict(type='str', required=True),
owner=dict(type='str', default='jenkins'),
group=dict(type="str", default="jenkins"),
jenkins_home=dict(type="path", default="/var/lib/jenkins"),
mode=dict(default="0644", type="raw"),
name=dict(type="str", required=True),
owner=dict(type="str", default="jenkins"),
state=dict(
choices=[
'present',
'absent',
'pinned',
'unpinned',
'enabled',
'disabled',
'latest'],
default='present'),
choices=["present", "absent", "pinned", "unpinned", "enabled", "disabled", "latest"], default="present"
),
timeout=dict(default=30, type="int"),
updates_expiration=dict(default=86400, type="int"),
updates_url=dict(type="list", elements="str", default=['https://updates.jenkins.io',
'http://mirrors.jenkins.io']),
updates_url=dict(
type="list", elements="str", default=["https://updates.jenkins.io", "http://mirrors.jenkins.io"]
),
updates_url_username=dict(type="str"),
updates_url_password=dict(type="str", no_log=True),
update_json_url_segment=dict(type="list", elements="str", default=['update-center.json',
'updates/update-center.json']),
plugin_versions_url_segment=dict(type="list", elements="str", default=['plugin-versions.json',
'current/plugin-versions.json']),
latest_plugins_url_segments=dict(type="list", elements="str", default=['latest']),
versioned_plugins_url_segments=dict(type="list", elements="str", default=['download/plugins', 'plugins']),
url=dict(default='http://localhost:8080'),
update_json_url_segment=dict(
type="list", elements="str", default=["update-center.json", "updates/update-center.json"]
),
plugin_versions_url_segment=dict(
type="list", elements="str", default=["plugin-versions.json", "current/plugin-versions.json"]
),
latest_plugins_url_segments=dict(type="list", elements="str", default=["latest"]),
versioned_plugins_url_segments=dict(type="list", elements="str", default=["download/plugins", "plugins"]),
url=dict(default="http://localhost:8080"),
url_password=dict(no_log=True),
version=dict(),
with_dependencies=dict(default=True, type='bool'),
with_dependencies=dict(default=True, type="bool"),
)
# Module settings
module = AnsibleModule(
@ -961,47 +922,50 @@ def main():
# Convert timeout to float
try:
module.params['timeout'] = float(module.params['timeout'])
module.params["timeout"] = float(module.params["timeout"])
except ValueError as e:
module.fail_json(
msg=f"Cannot convert {module.params['timeout']} to float.",
details=to_native(e))
module.fail_json(msg=f"Cannot convert {module.params['timeout']} to float.", details=to_native(e))
# Instantiate the JenkinsPlugin object
jp = JenkinsPlugin(module)
# Set version to latest if state is latest
if module.params['state'] == 'latest':
module.params['state'] = 'present'
module.params['version'] = jp._get_latest_compatible_plugin_version()
if module.params["state"] == "latest":
module.params["state"] = "present"
module.params["version"] = jp._get_latest_compatible_plugin_version()
# Set version to latest compatible version if version is latest
if module.params['version'] == 'latest':
module.params['version'] = jp._get_latest_compatible_plugin_version()
if module.params["version"] == "latest":
module.params["version"] = jp._get_latest_compatible_plugin_version()
# Create some shortcuts
name = module.params['name']
state = module.params['state']
name = module.params["name"]
state = module.params["state"]
# Initial change state of the task
changed = False
# Perform action depending on the requested state
if state == 'present':
if state == "present":
changed = jp.install()
elif state == 'absent':
elif state == "absent":
changed = jp.uninstall()
elif state == 'pinned':
elif state == "pinned":
changed = jp.pin()
elif state == 'unpinned':
elif state == "unpinned":
changed = jp.unpin()
elif state == 'enabled':
elif state == "enabled":
changed = jp.enable()
elif state == 'disabled':
elif state == "disabled":
changed = jp.disable()
# Print status of the change
module.exit_json(changed=changed, plugin=name, state=state, dependencies=jp.dependencies_states if hasattr(jp, 'dependencies_states') else None)
module.exit_json(
changed=changed,
plugin=name,
state=state,
dependencies=jp.dependencies_states if hasattr(jp, "dependencies_states") else None,
)
if __name__ == '__main__':
if __name__ == "__main__":
main()