Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jenkins_plugin: fix sanity checks #5565

Merged
merged 6 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/BOTMETA.yml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ files:
$module_utils/ipa.py:
labels: ipa
maintainers: $team_ipa
$module_utils/jenkins.py:
labels: jenkins
maintainers: russoz
$module_utils/manageiq.py:
labels: manageiq
maintainers: $team_manageiq
Expand Down
2 changes: 2 additions & 0 deletions changelogs/fragments/5565-jenkins-plugin-sanity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- jenkins_plugin - refactor code to module util to fix sanity check (https://github.com/ansible-collections/community.general/pull/5565).
35 changes: 35 additions & 0 deletions plugins/module_utils/jenkins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-

# Copyright (c) 2022, Alexei Znamensky <russoz@gmail.com>
#
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import absolute_import, division, print_function
__metaclass__ = type


import os
import time


def download_updates_file(updates_expiration):
updates_filename = 'jenkins-plugin-cache.json'
updates_dir = os.path.expanduser('~/.ansible/tmp')
updates_file = os.path.join(updates_dir, updates_filename)
download_updates = True

# Make sure the destination directory exists
if not os.path.isdir(updates_dir):
os.makedirs(updates_dir, 0o700)

# Check if we need to download new updates file
if os.path.isfile(updates_file):
# Get timestamp when the file was changed last time
ts_file = os.stat(updates_file).st_mtime
ts_now = time.time()

if ts_now - ts_file < updates_expiration:
download_updates = False

return updates_file, download_updates
85 changes: 31 additions & 54 deletions plugins/modules/jenkins_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,19 +290,22 @@
sample: "present"
'''

from ansible.module_utils.basic import AnsibleModule, to_bytes
from ansible.module_utils.six.moves import http_cookiejar as cookiejar
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.urls import fetch_url, url_argument_spec
from ansible.module_utils.six import text_type, binary_type
from ansible.module_utils.common.text.converters import to_native
import hashlib
import io
import json
import os
import tempfile
import time

from ansible.module_utils.basic import AnsibleModule, to_bytes
from ansible.module_utils.six.moves import http_cookiejar as cookiejar
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.urls import fetch_url, url_argument_spec
from ansible.module_utils.six import text_type, binary_type
from ansible.module_utils.common.text.converters import to_native

from ansible_collections.community.general.plugins.module_utils.jenkins import download_updates_file


class FailedInstallingWithPluginManager(Exception):
pass
Expand Down Expand Up @@ -605,21 +608,12 @@ def _get_update_center_urls(self):
return urls

def _download_updates(self):
updates_filename = 'jenkins-plugin-cache.json'
updates_dir = os.path.expanduser('~/.ansible/tmp')
updates_file = "%s/%s" % (updates_dir, updates_filename)
download_updates = True

# Check if we need to download new updates file
if os.path.isfile(updates_file):
# Get timestamp when the file was changed last time
ts_file = os.stat(updates_file).st_mtime
ts_now = time.time()

if ts_now - ts_file < self.params['updates_expiration']:
download_updates = False

updates_file_orig = updates_file
try:
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))

# Download the updates file if needed
if download_updates:
Expand All @@ -632,56 +626,39 @@ def _download_updates(self):
msg_exception="Updates download failed.")

# Write the updates file
update_fd, updates_file = tempfile.mkstemp()
os.write(update_fd, r.read())
tmp_update_fd, tmp_updates_file = tempfile.mkstemp()
os.write(tmp_update_fd, r.read())

try:
os.close(update_fd)
os.close(tmp_update_fd)
except IOError as e:
self.module.fail_json(
msg="Cannot close the tmp updates file %s." % updates_file,
msg="Cannot close the tmp updates file %s." % tmp_updates_file,
details=to_native(e))

# Open the updates file
try:
f = io.open(updates_file, encoding='utf-8')
f = io.open(tmp_updates_file, encoding='utf-8')

# Read only the second line
dummy = f.readline()
data = json.loads(f.readline())
felixfontein marked this conversation as resolved.
Show resolved Hide resolved
except IOError as e:
self.module.fail_json(
msg="Cannot open temporal updates file.",
details=to_native(e))

i = 0
for line in f:
# Read only the second line
if i == 1:
try:
data = json.loads(line)
except Exception as e:
self.module.fail_json(
msg="Cannot load JSON data from the tmp updates file.",
details=to_native(e))

break

i += 1
except Exception as e:
self.module.fail_json(
msg="Cannot load JSON data from the tmp updates file.",
details=to_native(e))

# Move the updates file to the right place if we could read it
if download_updates:
# Make sure the destination directory exists
if not os.path.isdir(updates_dir):
try:
os.makedirs(updates_dir, int('0700', 8))
except OSError as e:
self.module.fail_json(
msg="Cannot create temporal directory.",
details=to_native(e))

self.module.atomic_move(updates_file, updates_file_orig)
self.module.atomic_move(tmp_updates_file, updates_file)

# Check if we have the plugin data available
if 'plugins' not in data or self.params['name'] not in data['plugins']:
self.module.fail_json(
msg="Cannot find plugin data in the updates file.")
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']]

Expand Down
1 change: 0 additions & 1 deletion tests/sanity/ignore-2.11.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ plugins/modules/consul.py validate-modules:undocumented-parameter
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
plugins/modules/gconftool2.py validate-modules:parameter-state-invalid-choice # state=get - removed in 8.0.0
plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/jenkins_plugin.py use-argspec-type-path
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/manageiq_policies.py validate-modules:parameter-state-invalid-choice
plugins/modules/manageiq_provider.py validate-modules:doc-choices-do-not-match-spec # missing docs on suboptions
Expand Down
1 change: 0 additions & 1 deletion tests/sanity/ignore-2.12.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ plugins/modules/consul.py validate-modules:undocumented-parameter
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
plugins/modules/gconftool2.py validate-modules:parameter-state-invalid-choice # state=get - removed in 8.0.0
plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/jenkins_plugin.py use-argspec-type-path
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/manageiq_policies.py validate-modules:parameter-state-invalid-choice
plugins/modules/manageiq_provider.py validate-modules:doc-choices-do-not-match-spec # missing docs on suboptions
Expand Down
1 change: 0 additions & 1 deletion tests/sanity/ignore-2.13.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ plugins/modules/consul.py validate-modules:undocumented-parameter
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
plugins/modules/gconftool2.py validate-modules:parameter-state-invalid-choice # state=get - removed in 8.0.0
plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/jenkins_plugin.py use-argspec-type-path
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/manageiq_policies.py validate-modules:parameter-state-invalid-choice
plugins/modules/manageiq_provider.py validate-modules:doc-choices-do-not-match-spec # missing docs on suboptions
Expand Down
1 change: 0 additions & 1 deletion tests/sanity/ignore-2.14.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choic
plugins/modules/gconftool2.py validate-modules:parameter-state-invalid-choice # state=get - removed in 8.0.0
plugins/modules/homectl.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/jenkins_plugin.py use-argspec-type-path
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/manageiq_policies.py validate-modules:parameter-state-invalid-choice
plugins/modules/manageiq_provider.py validate-modules:doc-choices-do-not-match-spec # missing docs on suboptions
Expand Down
1 change: 0 additions & 1 deletion tests/sanity/ignore-2.15.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choic
plugins/modules/gconftool2.py validate-modules:parameter-state-invalid-choice # state=get - removed in 8.0.0
plugins/modules/homectl.py import-3.11 # Uses deprecated stdlib library 'crypt'
plugins/modules/iptables_state.py validate-modules:undocumented-parameter
plugins/modules/jenkins_plugin.py use-argspec-type-path
plugins/modules/lxc_container.py validate-modules:use-run-command-not-popen
plugins/modules/manageiq_policies.py validate-modules:parameter-state-invalid-choice
plugins/modules/manageiq_provider.py validate-modules:doc-choices-do-not-match-spec # missing docs on suboptions
Expand Down