diff --git a/doc/source/execution.rst b/doc/source/execution.rst index 43a859372..1006e818b 100644 --- a/doc/source/execution.rst +++ b/doc/source/execution.rst @@ -313,6 +313,22 @@ To delete jobs/views that only have 'foo' in their name:: jenkins-jobs delete --path ./myjobs \*foo\* +Providing Plugins Info +^^^^^^^^^^^^^^^^^^^^^^ +With Jenkins LTS 1.651.1+ retrieving plugins info became a secure feature and +now requires Administrator rights to use [#f2]. This causes JJB to no longer be +able to work in situations where a user wants to publish jobs to Jenkins but is +not able to receive the Administrator permissions. In this case we can provide +a plugins_info.yaml file containing the plugin versions data needed by JJB to +parse the job templates. + +To generate a plugins info, using an account with Administrator rights: + + jenkins-jobs get-plugins-info -o plugins_info.yaml + +To run JJB update using the plugins_info.yaml: + + jenkins-jobs update -p plugins_info.yaml ./myjobs .. _command-reference: @@ -323,8 +339,11 @@ Command Reference .. program-output:: jenkins-jobs update --help .. program-output:: jenkins-jobs delete-all --help .. program-output:: jenkins-jobs delete --help +.. program-output:: jenkins-jobs get-plugins-info --help .. rubric:: Footnotes .. [#f1] The cache default location is at ``~/.cache/jenkins_jobs``, which can be overridden by setting the ``XDG_CACHE_HOME`` environment variable. +.. [#f2] Jenkins Security Advisory affecting plugins info retrieval + https://wiki.jenkins-ci.org/display/SECURITY/Jenkins+Security+Advisory+2016-05-11 diff --git a/doc/source/quick-start.rst b/doc/source/quick-start.rst index 6b1edba4e..64a3c38f5 100644 --- a/doc/source/quick-start.rst +++ b/doc/source/quick-start.rst @@ -80,6 +80,18 @@ To delete a job:: The above command deletes the job `simple` from the Jenkins master. +.. _use-case-5: + +Use Case 5: Providing plugins info +---------------------------------- + +To generate a plugins info, using an account with Administrator rights: + + jenkins-jobs get-plugins-info -o plugins_info.yaml + +To run JJB update using the plugins_info.yaml: + + jenkins-jobs update -p plugins_info.yaml ./myjobs Please refer to the jenkins-jobs :ref:`command-reference` and the diff --git a/jenkins_jobs/cli/subcommand/get_plugins_info.py b/jenkins_jobs/cli/subcommand/get_plugins_info.py new file mode 100644 index 000000000..748cbf6c9 --- /dev/null +++ b/jenkins_jobs/cli/subcommand/get_plugins_info.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# Copyright (C) 2017 Thanh Ha +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging + +import yaml + +from jenkins_jobs.builder import JenkinsManager +import jenkins_jobs.cli.subcommand.base as base + + +logger = logging.getLogger(__name__) + + +class GetPluginsInfoSubCommand(base.BaseSubCommand): + + def parse_args(self, subparser): + plugins_info = subparser.add_parser( + 'get-plugins-info', + help='get plugins info yaml by querying Jenkins server.') + + plugins_info.add_argument( + '-o', '--output-file', + default='plugins_info.yaml', + dest='plugins_info_file', + help='file to save output to.') + + def execute(self, options, jjb_config): + builder = JenkinsManager(jjb_config) + plugin_data = builder.jenkins.get_plugins_info() + plugins_info = [] + for plugin in plugin_data: + info = { + 'longName': str(plugin['longName']), + 'shortName': str(plugin['shortName']), + 'version': str(plugin['version']), + } + plugins_info.append(info) + + if options.plugins_info_file: + with open(options.plugins_info_file, 'w') as outfile: + outfile.write(yaml.dump(plugins_info)) + logger.info("Generated {} file".format(options.plugins_info_file)) + else: + print(yaml.dump(plugins_info)) diff --git a/jenkins_jobs/cli/subcommand/test.py b/jenkins_jobs/cli/subcommand/test.py index 3fe4b5b1e..ff31285e8 100644 --- a/jenkins_jobs/cli/subcommand/test.py +++ b/jenkins_jobs/cli/subcommand/test.py @@ -39,7 +39,7 @@ class TestSubCommand(update.UpdateSubCommand): default=False, help='use alternative output file layout using config.xml files') test.add_argument( - '-p', + '-p', '--plugin-info', dest='plugins_info_path', default=None, help='path to plugin info YAML file') diff --git a/jenkins_jobs/cli/subcommand/update.py b/jenkins_jobs/cli/subcommand/update.py index 03901c2f4..a7aefa54f 100644 --- a/jenkins_jobs/cli/subcommand/update.py +++ b/jenkins_jobs/cli/subcommand/update.py @@ -58,6 +58,13 @@ class UpdateSubCommand(base.BaseSubCommand): dest='delete_old', default=False, help='delete obsolete jobs') + update.add_argument( + '-p', '--plugin-info', + dest='plugins_info_path', + default=None, + help='path to plugin info YAML file. Can be used to provide ' + 'previously retrieved plugins info when connecting credentials ' + 'don\'t have permissions to query.') update.add_argument( '--workers', type=int, diff --git a/setup.cfg b/setup.cfg index eaeda0fcb..1d5a34aab 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,6 +40,7 @@ jjb.cli.subcommands = test=jenkins_jobs.cli.subcommand.test:TestSubCommand delete=jenkins_jobs.cli.subcommand.delete:DeleteSubCommand delete-all=jenkins_jobs.cli.subcommand.delete_all:DeleteAllSubCommand + get-plugins-info=jenkins_jobs.cli.subcommand.get_plugins_info:GetPluginsInfoSubCommand jenkins_jobs.projects = externaljob=jenkins_jobs.modules.project_externaljob:ExternalJob flow=jenkins_jobs.modules.project_flow:Flow