mirror of https://github.com/ansible/ansible.git
Adding jenkins_plugin module (#1730)
parent
7fddb83f91
commit
3dc7bfa6b8
@ -0,0 +1,830 @@
|
||||
#!/usr/bin/python
|
||||
# encoding: utf-8
|
||||
|
||||
# (c) 2016, Jiri Tyr <jiri.tyr@gmail.com>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.pycompat24 import get_exception
|
||||
from ansible.module_utils.urls import fetch_url
|
||||
from ansible.module_utils.urls import url_argument_spec
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import urllib
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: jenkins_plugin
|
||||
author: Jiri Tyr (@jtyr)
|
||||
version_added: '2.2'
|
||||
short_description: Add or remove Jenkins plugin
|
||||
description:
|
||||
- Ansible module which helps to manage Jenkins plugins.
|
||||
|
||||
options:
|
||||
group:
|
||||
required: false
|
||||
default: jenkins
|
||||
description:
|
||||
- Name of the Jenkins group on the OS.
|
||||
jenkins_home:
|
||||
required: false
|
||||
default: /var/lib/jenkins
|
||||
description:
|
||||
- Home directory of the Jenkins user.
|
||||
mode:
|
||||
required: false
|
||||
default: '0664'
|
||||
description:
|
||||
- File mode applied on versioned plugins.
|
||||
name:
|
||||
required: true
|
||||
description:
|
||||
- Plugin name.
|
||||
owner:
|
||||
required: false
|
||||
default: jenkins
|
||||
description:
|
||||
- Name of the Jenkins user on the OS.
|
||||
params:
|
||||
required: false
|
||||
default: null
|
||||
description:
|
||||
- Option used to allow the user to overwrite any of the other options. To
|
||||
remove an option, set the value of the option to C(null).
|
||||
state:
|
||||
required: false
|
||||
choices: [absent, present, pinned, unpinned, enabled, disabled, latest]
|
||||
default: present
|
||||
description:
|
||||
- Desired plugin state.
|
||||
- If the C(latest) is set, the check for new version will be performed
|
||||
every time. This is suitable to keep the plugin up-to-date.
|
||||
timeout:
|
||||
required: false
|
||||
default: 30
|
||||
description:
|
||||
- Server connection timeout in secs.
|
||||
updates_expiration:
|
||||
required: false
|
||||
default: 86400
|
||||
description:
|
||||
- Number of seconds after which a new copy of the I(update-center.json)
|
||||
file is downloaded. This is used to avoid the need to download the
|
||||
plugin to calculate its checksum when C(latest) is specified.
|
||||
- Set it to C(0) if no cache file should be used. In that case, the
|
||||
plugin file will always be downloaded to calculate its checksum when
|
||||
C(latest) is specified.
|
||||
updates_url:
|
||||
required: false
|
||||
default: https://updates.jenkins-ci.org
|
||||
description:
|
||||
- URL of the Update Centre.
|
||||
- Used as the base URL to download the plugins and the
|
||||
I(update-center.json) JSON file.
|
||||
url:
|
||||
required: false
|
||||
default: http://localhost:8080
|
||||
description:
|
||||
- URL of the Jenkins server.
|
||||
version:
|
||||
required: false
|
||||
default: null
|
||||
description:
|
||||
- Plugin version number.
|
||||
- If this option is specified, all plugin dependencies must be installed
|
||||
manually.
|
||||
- It might take longer to verify that the correct version is installed.
|
||||
This is especially true if a specific version number is specified.
|
||||
with_dependencies:
|
||||
required: false
|
||||
choices: ['yes', 'no']
|
||||
default: 'yes'
|
||||
description:
|
||||
- Defines whether to install plugin dependencies.
|
||||
|
||||
notes:
|
||||
- Plugin installation shoud be run under root or the same user which owns
|
||||
the plugin files on the disk. Only if the plugin is not installed yet and
|
||||
no version is specified, the API installation is performed which requires
|
||||
only the Web UI credentials.
|
||||
- It's necessary to notify the handler or call the I(service) module to
|
||||
restart the Jenkins service after a new plugin was installed.
|
||||
- Pinning works only if the plugin is installed and Jenkis service was
|
||||
successfully restarted after the plugin installation.
|
||||
- It is not possible to run the module remotely by changing the I(url)
|
||||
parameter to point to the Jenkins server. The module must be used on the
|
||||
host where Jenkins runs as it needs direct access to the plugin files.
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Install plugin
|
||||
jenkins_plugin:
|
||||
name: build-pipeline-plugin
|
||||
|
||||
- name: Install plugin without its dependencies
|
||||
jenkins_plugin:
|
||||
name: build-pipeline-plugin
|
||||
with_dependencies: no
|
||||
|
||||
- name: Make sure the plugin is always up-to-date
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
state: latest
|
||||
|
||||
- name: Install specific version of the plugin
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
version: 1.15
|
||||
|
||||
- name: Pin the plugin
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
state: pinned
|
||||
|
||||
- name: Unpin the plugin
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
state: unpinned
|
||||
|
||||
- name: Enable the plugin
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
state: enabled
|
||||
|
||||
- name: Disable the plugin
|
||||
jenkins_plugin:
|
||||
name: token-macro
|
||||
state: disabled
|
||||
|
||||
- name: Uninstall plugin
|
||||
jenkins_plugin:
|
||||
name: build-pipeline-plugin
|
||||
state: absent
|
||||
|
||||
#
|
||||
# Example of how to use the params
|
||||
#
|
||||
# Define a variable and specify all default parameters you want to use across
|
||||
# all jenkins_plugin calls:
|
||||
#
|
||||
# my_jenkins_params:
|
||||
# url_username: admin
|
||||
# url_password: p4ssw0rd
|
||||
# url: http://localhost:8888
|
||||
#
|
||||
- name: Install plugin
|
||||
jenkins_plugin:
|
||||
name: build-pipeline-plugin
|
||||
params: "{{ my_jenkins_params }}"
|
||||
|
||||
#
|
||||
# Example of a Play which handles Jenkins restarts during the state changes
|
||||
#
|
||||
- name: Jenkins Master play
|
||||
hosts: jenkins-master
|
||||
vars:
|
||||
my_jenkins_plugins:
|
||||
token-macro:
|
||||
enabled: yes
|
||||
build-pipeline-plugin:
|
||||
version: 1.4.9
|
||||
pinned: no
|
||||
enabled: yes
|
||||
tasks:
|
||||
- name: Install plugins without a specific version
|
||||
jenkins_plugin:
|
||||
name: "{{ item.key }}"
|
||||
register: my_jenkins_plugin_unversioned
|
||||
when: >
|
||||
'version' not in item.value
|
||||
with_dict: my_jenkins_plugins
|
||||
|
||||
- name: Install plugins with a specific version
|
||||
jenkins_plugin:
|
||||
name: "{{ item.key }}"
|
||||
version: "{{ item.value['version'] }}"
|
||||
register: my_jenkins_plugin_versioned
|
||||
when: >
|
||||
'version' in item.value
|
||||
with_dict: my_jenkins_plugins
|
||||
|
||||
- name: Initiate the fact
|
||||
set_fact:
|
||||
jenkins_restart_required: no
|
||||
|
||||
- name: Check if restart is required by any of the versioned plugins
|
||||
set_fact:
|
||||
jenkins_restart_required: yes
|
||||
when: item.changed
|
||||
with_items: my_jenkins_plugin_versioned.results
|
||||
|
||||
- name: Check if restart is required by any of the unversioned plugins
|
||||
set_fact:
|
||||
jenkins_restart_required: yes
|
||||
when: item.changed
|
||||
with_items: my_jenkins_plugin_unversioned.results
|
||||
|
||||
- name: Restart Jenkins if required
|
||||
service:
|
||||
name: jenkins
|
||||
state: restarted
|
||||
when: jenkins_restart_required
|
||||
|
||||
# Requires python-httplib2 to be installed on the guest
|
||||
- name: Wait for Jenkins to start up
|
||||
uri:
|
||||
url: http://localhost:8080
|
||||
status_code: 200
|
||||
timeout: 5
|
||||
register: jenkins_service_status
|
||||
# Keep trying for 5 mins in 5 sec intervals
|
||||
retries: 60
|
||||
delay: 5
|
||||
until: >
|
||||
'status' in jenkins_service_status and
|
||||
jenkins_service_status['status'] == 200
|
||||
when: jenkins_restart_required
|
||||
|
||||
- name: Reset the fact
|
||||
set_fact:
|
||||
jenkins_restart_required: no
|
||||
when: jenkins_restart_required
|
||||
|
||||
- name: Plugin pinning
|
||||
jenkins_plugin:
|
||||
name: "{{ item.key }}"
|
||||
state: "{{ 'pinned' if item.value['pinned'] else 'unpinned'}}"
|
||||
when: >
|
||||
'pinned' in item.value
|
||||
with_dict: my_jenkins_plugins
|
||||
|
||||
- name: Plugin enabling
|
||||
jenkins_plugin:
|
||||
name: "{{ item.key }}"
|
||||
state: "{{ 'enabled' if item.value['enabled'] else 'disabled'}}"
|
||||
when: >
|
||||
'enabled' in item.value
|
||||
with_dict: my_jenkins_plugins
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
plugin:
|
||||
description: plugin name
|
||||
returned: success
|
||||
type: string
|
||||
sample: build-pipeline-plugin
|
||||
state:
|
||||
description: state of the target, after execution
|
||||
returned: success
|
||||
type: string
|
||||
sample: "present"
|
||||
'''
|
||||
|
||||
|
||||
class JenkinsPlugin(object):
|
||||
def __init__(self, module):
|
||||
# To be able to call fail_json
|
||||
self.module = module
|
||||
|
||||
# Shortcuts for the params
|
||||
self.params = self.module.params
|
||||
self.url = self.params['url']
|
||||
self.timeout = self.params['timeout']
|
||||
|
||||
# Crumb
|
||||
self.crumb = {}
|
||||
|
||||
if self._csrf_enabled():
|
||||
self.crumb = self._get_crumb()
|
||||
|
||||
# Get list of installed plugins
|
||||
self._get_installed_plugins()
|
||||
|
||||
def _csrf_enabled(self):
|
||||
csrf_data = self._get_json_data(
|
||||
"%s/%s" % (self.url, "api/json"), 'CSRF')
|
||||
|
||||
return csrf_data["useCrumbs"]
|
||||
|
||||
def _get_json_data(self, url, what, **kwargs):
|
||||
# Get the JSON data
|
||||
r = self._get_url_data(url, what, **kwargs)
|
||||
|
||||
# Parse the JSON data
|
||||
try:
|
||||
json_data = json.load(r)
|
||||
except Exception:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot parse %s JSON data." % what,
|
||||
details=e.message)
|
||||
|
||||
return json_data
|
||||
|
||||
def _get_url_data(
|
||||
self, url, what=None, msg_status=None, msg_exception=None,
|
||||
**kwargs):
|
||||
# Compose default messages
|
||||
if msg_status is None:
|
||||
msg_status = "Cannot get %s" % what
|
||||
|
||||
if msg_exception is None:
|
||||
msg_exception = "Retrieval of %s failed." % what
|
||||
|
||||
# Get the URL data
|
||||
try:
|
||||
response, info = fetch_url(
|
||||
self.module, url, timeout=self.timeout, **kwargs)
|
||||
|
||||
if info['status'] != 200:
|
||||
self.module.fail_json(msg=msg_status, details=info['msg'])
|
||||
except Exception:
|
||||
e = get_exception()
|
||||
self.module.fail_json(msg=msg_exception, details=e.message)
|
||||
|
||||
return response
|
||||
|
||||
def _get_crumb(self):
|
||||
crumb_data = self._get_json_data(
|
||||
"%s/%s" % (self.url, "crumbIssuer/api/json"), 'Crumb')
|
||||
|
||||
if 'crumbRequestField' in crumb_data and 'crumb' in crumb_data:
|
||||
ret = {
|
||||
crumb_data['crumbRequestField']: crumb_data['crumb']
|
||||
}
|
||||
else:
|
||||
self.module.fail_json(
|
||||
msg="Required fields not found in the Crum response.",
|
||||
details=crumb_data)
|
||||
|
||||
return ret
|
||||
|
||||
def _get_installed_plugins(self):
|
||||
plugins_data = self._get_json_data(
|
||||
"%s/%s" % (self.url, "pluginManager/api/json?depth=1"),
|
||||
'list of plugins')
|
||||
|
||||
# Check if we got valid 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
|
||||
|
||||
for p in plugins_data['plugins']:
|
||||
if p['shortName'] == self.params['name']:
|
||||
self.is_installed = True
|
||||
|
||||
if p['pinned']:
|
||||
self.is_pinned = True
|
||||
|
||||
if p['enabled']:
|
||||
self.is_enabled = True
|
||||
|
||||
break
|
||||
|
||||
def install(self):
|
||||
changed = False
|
||||
plugin_file = (
|
||||
'%s/plugins/%s.jpi' % (
|
||||
self.params['jenkins_home'],
|
||||
self.params['name']))
|
||||
|
||||
if not self.is_installed and self.params['version'] is None:
|
||||
if not self.module.check_mode:
|
||||
# Install the plugin (with dependencies)
|
||||
install_script = (
|
||||
'd = Jenkins.instance.updateCenter.getPlugin("%s")'
|
||||
'.deploy(); d.get();' % self.params['name'])
|
||||
|
||||
if self.params['with_dependencies']:
|
||||
install_script = (
|
||||
'Jenkins.instance.updateCenter.getPlugin("%s")'
|
||||
'.getNeededDependencies().each{it.deploy()}; %s' % (
|
||||
self.params['name'], install_script))
|
||||
|
||||
script_data = {
|
||||
'script': install_script
|
||||
}
|
||||
script_data.update(self.crumb)
|
||||
data = urllib.urlencode(script_data)
|
||||
|
||||
# Send the installation request
|
||||
r = self._get_url_data(
|
||||
"%s/scriptText" % self.url,
|
||||
msg_status="Cannot install plugin.",
|
||||
msg_exception="Plugin installation has failed.",
|
||||
data=data)
|
||||
|
||||
changed = True
|
||||
else:
|
||||
# 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.")
|
||||
|
||||
md5sum_old = None
|
||||
if os.path.isfile(plugin_file):
|
||||
# Make the checksum of the currently installed plugin
|
||||
md5sum_old = hashlib.md5(
|
||||
open(plugin_file, 'rb').read()).hexdigest()
|
||||
|
||||
if self.params['version'] in [None, 'latest']:
|
||||
# Take latest version
|
||||
plugin_url = (
|
||||
"%s/latest/%s.hpi" % (
|
||||
self.params['updates_url'],
|
||||
self.params['name']))
|
||||
else:
|
||||
# Take specific version
|
||||
plugin_url = (
|
||||
"{0}/download/plugins/"
|
||||
"{1}/{2}/{1}.hpi".format(
|
||||
self.params['updates_url'],
|
||||
self.params['name'],
|
||||
self.params['version']))
|
||||
|
||||
if (
|
||||
self.params['updates_expiration'] == 0 or
|
||||
self.params['version'] not in [None, 'latest'] or
|
||||
md5sum_old is None):
|
||||
|
||||
# Download the plugin file directly
|
||||
r = self._download_plugin(plugin_url)
|
||||
|
||||
# Write downloaded plugin into file if checksums don't match
|
||||
if md5sum_old is None:
|
||||
# No previously installed plugin
|
||||
if not self.module.check_mode:
|
||||
self._write_file(plugin_file, r)
|
||||
|
||||
changed = True
|
||||
else:
|
||||
# Get data for the MD5
|
||||
data = r.read()
|
||||
|
||||
# Make new checksum
|
||||
md5sum_new = hashlib.md5(data).hexdigest()
|
||||
|
||||
# If the checksum is different from the currently installed
|
||||
# plugin, store the new plugin
|
||||
if md5sum_old != md5sum_new:
|
||||
if not self.module.check_mode:
|
||||
self._write_file(plugin_file, data)
|
||||
|
||||
changed = True
|
||||
else:
|
||||
# Check for update from the updates JSON file
|
||||
plugin_data = self._download_updates()
|
||||
|
||||
try:
|
||||
sha1_old = hashlib.sha1(open(plugin_file, 'rb').read())
|
||||
except Exception:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot calculate SHA1 of the old plugin.",
|
||||
details=e.message)
|
||||
|
||||
sha1sum_old = base64.b64encode(sha1_old.digest())
|
||||
|
||||
# If the latest version changed, download it
|
||||
if sha1sum_old != plugin_data['sha1']:
|
||||
if not self.module.check_mode:
|
||||
r = self._download_plugin(plugin_url)
|
||||
self._write_file(plugin_file, r)
|
||||
|
||||
changed = True
|
||||
|
||||
# Change file attributes if needed
|
||||
if os.path.isfile(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)
|
||||
else:
|
||||
# See the comment above
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
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
|
||||
|
||||
# Download the updates file if needed
|
||||
if download_updates:
|
||||
url = "%s/update-center.json" % self.params['updates_url']
|
||||
|
||||
# Get the data
|
||||
r = self._get_url_data(
|
||||
url,
|
||||
msg_status="Remote updates not found.",
|
||||
msg_exception="Updates download failed.")
|
||||
|
||||
# Write the updates file
|
||||
updates_file = tempfile.mktemp()
|
||||
|
||||
try:
|
||||
fd = open(updates_file, 'wb')
|
||||
except IOError:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot open the tmp updates file %s." % updates_file,
|
||||
details=str(e))
|
||||
|
||||
fd.write(r.read())
|
||||
|
||||
try:
|
||||
fd.close()
|
||||
except IOError:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot close the tmp updates file %s." % updates_file,
|
||||
detail=str(e))
|
||||
|
||||
# Open the updates file
|
||||
try:
|
||||
f = open(updates_file)
|
||||
except IOError:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot open temporal updates file.",
|
||||
details=str(e))
|
||||
|
||||
i = 0
|
||||
for line in f:
|
||||
# Read only the second line
|
||||
if i == 1:
|
||||
try:
|
||||
data = json.loads(line)
|
||||
except Exception:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot load JSON data from the tmp updates file.",
|
||||
details=e.message)
|
||||
|
||||
break
|
||||
|
||||
i += 1
|
||||
|
||||
# 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:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg="Cannot create temporal directory.",
|
||||
details=e.message)
|
||||
|
||||
self.module.atomic_move(updates_file, updates_file_orig)
|
||||
|
||||
# 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.")
|
||||
|
||||
return data['plugins'][self.params['name']]
|
||||
|
||||
def _download_plugin(self, plugin_url):
|
||||
# Download the plugin
|
||||
r = self._get_url_data(
|
||||
plugin_url,
|
||||
msg_status="Plugin not found.",
|
||||
msg_exception="Plugin download failed.")
|
||||
|
||||
return r
|
||||
|
||||
def _write_file(self, f, data):
|
||||
# Store the plugin into a temp file and then move it
|
||||
tmp_f = tempfile.mktemp()
|
||||
|
||||
try:
|
||||
fd = open(tmp_f, 'wb')
|
||||
except IOError:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg='Cannot open the temporal plugin file %s.' % tmp_f,
|
||||
details=str(e))
|
||||
|
||||
if isinstance(data, str):
|
||||
d = data
|
||||
else:
|
||||
d = data.read()
|
||||
|
||||
fd.write(d)
|
||||
|
||||
try:
|
||||
fd.close()
|
||||
except IOError:
|
||||
e = get_exception()
|
||||
self.module.fail_json(
|
||||
msg='Cannot close the temporal plugin file %s.' % tmp_f,
|
||||
details=str(e))
|
||||
|
||||
# Move the file onto the right place
|
||||
self.module.atomic_move(tmp_f, f)
|
||||
|
||||
def uninstall(self):
|
||||
changed = False
|
||||
|
||||
# Perform the action
|
||||
if self.is_installed:
|
||||
if not self.module.check_mode:
|
||||
self._pm_query('doUninstall', 'Uninstallation')
|
||||
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
def pin(self):
|
||||
return self._pinning('pin')
|
||||
|
||||
def unpin(self):
|
||||
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):
|
||||
|
||||
# Perform the action
|
||||
if not self.module.check_mode:
|
||||
self._pm_query(action, "%sning" % action.capitalize())
|
||||
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
def enable(self):
|
||||
return self._enabling('enable')
|
||||
|
||||
def disable(self):
|
||||
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):
|
||||
|
||||
# Perform the action
|
||||
if not self.module.check_mode:
|
||||
self._pm_query(
|
||||
"make%sd" % action.capitalize(),
|
||||
"%sing" % action[:-1].capitalize())
|
||||
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
def _pm_query(self, action, msg):
|
||||
url = "%s/pluginManager/plugin/%s/%s" % (
|
||||
self.params['url'], self.params['name'], action)
|
||||
data = urllib.urlencode(self.crumb)
|
||||
|
||||
# Send the request
|
||||
self._get_url_data(
|
||||
url,
|
||||
msg_status="Plugin not found. %s" % url,
|
||||
msg_exception="%s has failed." % msg,
|
||||
data=data)
|
||||
|
||||
|
||||
def main():
|
||||
# Module arguments
|
||||
argument_spec = url_argument_spec()
|
||||
argument_spec.update(
|
||||
group=dict(default='jenkins'),
|
||||
jenkins_home=dict(default='/var/lib/jenkins'),
|
||||
mode=dict(default='0644', type='raw'),
|
||||
name=dict(required=True),
|
||||
owner=dict(default='jenkins'),
|
||||
params=dict(type='dict'),
|
||||
state=dict(
|
||||
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(default='https://updates.jenkins-ci.org'),
|
||||
url=dict(default='http://localhost:8080'),
|
||||
url_password=dict(no_log=True),
|
||||
version=dict(),
|
||||
with_dependencies=dict(default=True, type='bool'),
|
||||
)
|
||||
# Module settings
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
add_file_common_args=True,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
# Update module parameters by user's parameters if defined
|
||||
if 'params' in module.params and isinstance(module.params['params'], dict):
|
||||
module.params.update(module.params['params'])
|
||||
# Remove the params
|
||||
module.params.pop('params', None)
|
||||
|
||||
# Force basic authentication
|
||||
module.params['force_basic_auth'] = True
|
||||
|
||||
# Convert timeout to float
|
||||
try:
|
||||
module.params['timeout'] = float(module.params['timeout'])
|
||||
except ValueError:
|
||||
e = get_exception()
|
||||
module.fail_json(
|
||||
msg='Cannot convert %s to float.' % module.params['timeout'],
|
||||
details=str(e))
|
||||
|
||||
# Set version to latest if state is latest
|
||||
if module.params['state'] == 'latest':
|
||||
module.params['state'] = 'present'
|
||||
module.params['version'] = 'latest'
|
||||
|
||||
# Create some shortcuts
|
||||
name = module.params['name']
|
||||
state = module.params['state']
|
||||
|
||||
# Initial change state of the task
|
||||
changed = False
|
||||
|
||||
# Instantiate the JenkinsPlugin object
|
||||
jp = JenkinsPlugin(module)
|
||||
|
||||
# Perform action depending on the requested state
|
||||
if state == 'present':
|
||||
changed = jp.install()
|
||||
elif state == 'absent':
|
||||
changed = jp.uninstall()
|
||||
elif state == 'pinned':
|
||||
changed = jp.pin()
|
||||
elif state == 'unpinned':
|
||||
changed = jp.unpin()
|
||||
elif state == 'enabled':
|
||||
changed = jp.enable()
|
||||
elif state == 'disabled':
|
||||
changed = jp.disable()
|
||||
|
||||
# Print status of the change
|
||||
module.exit_json(changed=changed, plugin=name, state=state)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue