Fix plugin management with Jenkins restart
- change plugin managent logic from per-plugin management to plugin set
- for plugin set management add two parameters:
* jenkins.client.plugin_remove_unwanted - to remove plugins not listed
in jenkins.client.plugin
* jenkins.client.plugin_force_remove - to forcible remove plugins
including dependants but taking into account dependencies of installed
plugins
- update state waiting for jenkins availability
- change error catching in API crumb getting to not fail on 50x errors,
to be able to handle exception in state(s)
Change-Id: Ia62af392b30f92c7fdff87ea17fce2cf284d6818
diff --git a/_states/jenkins_plugin.py b/_states/jenkins_plugin.py
index 0f80d51..a96afed 100644
--- a/_states/jenkins_plugin.py
+++ b/_states/jenkins_plugin.py
@@ -1,81 +1,9 @@
+import json
import logging
+import time
-logger = logging.getLogger(__name__)
-install_plugin_groovy = """\
-import jenkins.model.*
-import java.util.logging.Logger
-
-def logger = Logger.getLogger("")
-def installed = false
-def exists = false
-def pluginName="${plugin}"
-def instance = Jenkins.getInstance()
-def pm = instance.getPluginManager()
-def uc = instance.getUpdateCenter()
-def needUpdateSites(maxOldInSec = 1800){
- long oldestTs = 0
- for (UpdateSite s : Jenkins.instance.updateCenter.siteList) {
- if(oldestTs == 0 || s.getDataTimestamp()<oldestTs){
- oldestTs = s.getDataTimestamp()
- }
- }
- return (System.currentTimeMillis()-oldestTs)/1000 > maxOldInSec
-}
-
-if (!pm.getPlugin(pluginName)) {
- if(needUpdateSites()) {
- uc.updateAllSites()
- }
- def plugin = uc.getPlugin(pluginName)
- if (plugin) {
- plugin.deploy()
- installed = true
- }
-}else{
- exists = true
- print("EXISTS")
-}
-if (installed) {
- instance.save()
- if(${restart}){
- instance.doSafeRestart()
- }
- print("INSTALLED")
-}else if(!exists){
- print("FAILED")
-}
-""" # noqa
-
-remove_plugin_groovy = """
-import jenkins.model.*
-import java.util.logging.Logger
-
-def logger = Logger.getLogger("")
-def installed = false
-def initialized = false
-
-def pluginName="${plugin}"
-def instance = Jenkins.getInstance()
-def pm = instance.getPluginManager()
-
-def actPlugin = pm.getPlugin(pluginName)
-if (!actPlugin) {
- def pluginToInstall = Jenkins.instance.updateCenter.getPlugin(pluginName)
- if(!pluginToInstall){
- print("FAILED")
- }else{
- print("NOT PRESENT")
- }
-} else {
- actPlugin.disable()
- actPlugin.archive.delete()
- if({restart}){
- instance.doSafeRestart()
- }
- print("REMOVED")
-}
-""" # noqa
+log = logging.getLogger(__name__)
def __virtual__():
@@ -85,63 +13,46 @@
if 'jenkins_common.call_groovy_script' not in __salt__:
return (
False,
- 'The jenkins_plugin state module cannot be loaded: '
+ 'The jenkins_node state module cannot be loaded: '
'jenkins_common not found')
return True
-
-def present(name, restart=False):
+def managed(name, plugins, remove_unwanted=False, force_remove=False):
"""
- Jenkins plugin present state method, for installing plugins
+ Manage jenkins plugins
- :param name: plugin name
- :param restart: do you want to restart jenkins after plugin install?
+ :param name: salt resource name (usually 'jenkins_plugin_manage')
+ :param plugins: map containing plugin names and parameters
+ :param remove_unwanted: whether to remove not listed plugins
+ :param force_remove: force removing plugins recursively with all dependent plugins
:returns: salt-specified state dict
"""
- return _plugin_call(name, restart, install_plugin_groovy, [
- "INSTALLED", "EXISTS"])
+ log.info('Managing jenkins plugins')
+ template = __salt__['jenkins_common.load_template'](
+ 'salt://jenkins/files/groovy/plugin.template',
+ __env__)
+ result = __salt__['jenkins_common.api_call'](name, template,
+ [ 'UPDATED', 'NO CHANGES' ],
+ {
+ 'plugin_list': json.dumps(plugins),
+ 'clean_unwanted': remove_unwanted,
+ 'force_remove': force_remove
+ },
+ 'Manage Jenkins plugins')
+ log.debug('Got result: ' + json.dumps(result))
+ log.info('Checking if restart is required...')
+ # While next code is successful, we should wait for jenkins shutdown
+ # either:
+ # - false returned by isQuietingDown()
+ # - any error meaning that jenkins is unavailable (restarting)
+ wait = { 'result': True }
+ while (wait['result']):
+ wait = __salt__['jenkins_common.api_call']('jenkins_restart_wait',
+ 'println Jenkins.instance.isQuietingDown()', [ 'true' ], {},
+ 'Wait for jenkins restart')
+ if (wait['result']):
+ log.debug('Jenkins restart is required. Waiting...')
+ time.sleep(5)
-def absent(name, restart=False):
- """
- Jenkins plugin absent state method, for removing plugins
-
- :param name: plugin name
- :param restart: do you want to restart jenkins after plugin remove?
- :returns: salt-specified state dict
- """
- return _plugin_call(name, restart, remove_plugin_groovy, [
- "REMOVED", "NOT PRESENT"])
-
-
-def _plugin_call(name, restart, template, success_msgs):
- test = __opts__['test'] # noqa
- ret = {
- 'name': name,
- 'changes': {},
- 'result': False,
- 'comment': '',
- }
- result = False
- if test:
- status = success_msgs[0]
- ret['changes'][name] = status
- ret['comment'] = 'Jenkins plugin %s %s' % (name, status.lower())
- else:
- call_result = __salt__['jenkins_common.call_groovy_script'](
- template, {"plugin": name, "restart": "true" if restart else "false"})
- if call_result["code"] == 200 and call_result["msg"] in success_msgs:
- status = call_result["msg"]
- if status == success_msgs[0]:
- ret['changes'][name] = status
- ret['comment'] = 'Jenkins plugin %s %s%s' % (name, status.lower(
- ), ", jenkins restarted" if status == success_msgs[0] and restart else "")
- result = True
- else:
- status = 'FAILED'
- logger.error(
- "Jenkins plugin API call failure: %s", call_result["msg"])
- ret['comment'] = 'Jenkins plugin API call failure: %s' % (call_result[
- "msg"])
- ret['result'] = None if test else result
- return ret
+ return result