Extend ansible-pull to support other source repositories

This extends ansible-pull so that it can support using other
source_control modules for checking out a playbook repository
(issue #3372).  This will check to see if the module exists before
it attempts to do the checkout and will exit if the module is not found.
It requires that the module used to check out the repository support the
parameters 'name' and 'version'.  The option -C, --checkout is now
optional and defaults to the module's default behavior for selecting a
branch, tag, or commit value.  For git, this continues to be HEAD.

Other changes include:
* Remove git from help and use generic term(s) where needed.
* Use SortedOptParser from ansible.utils
* More abstraction of common options used between ansible and
  ansible-playbook.
This commit is contained in:
Stephen Fromm 2013-07-23 10:28:12 -07:00 committed by James Cammarata
parent cc58403e48
commit cc3651592b

View file

@ -14,8 +14,9 @@
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
# ansible-pull is a script that runs ansible in local mode # ansible-pull is a script that runs ansible in local mode
# after checking out a playbooks directory from git. There is an # after checking out a playbooks directory from source repo. There is an
# example playbook to bootstrap this script in the examples/ dir which # example playbook to bootstrap this script in the examples/ dir which
# installs ansible and sets it up to run on cron. # installs ansible and sets it up to run on cron.
@ -27,14 +28,14 @@
# the -d and -U arguments are required; the -C argument is optional. # the -d and -U arguments are required; the -C argument is optional.
# #
# ansible-pull accepts an optional argument to specify a playbook # ansible-pull accepts an optional argument to specify a playbook
# location underneath the workdir and then searches the git repo # location underneath the workdir and then searches the source repo
# for playbooks in the following order, stopping at the first match: # for playbooks in the following order, stopping at the first match:
# #
# 1. $workdir/path/playbook.yml, if specified # 1. $workdir/path/playbook.yml, if specified
# 2. $workdir/$hostname.yml # 2. $workdir/$hostname.yml
# 3. $workdir/local.yml # 3. $workdir/local.yml
# #
# the git repo must contain at least one of these playbooks. # the source repo must contain at least one of these playbooks.
import os import os
import shutil import shutil
@ -42,8 +43,9 @@ import subprocess
import sys import sys
import datetime import datetime
import socket import socket
from optparse import OptionParser from ansible import utils
DEFAULT_REPO_TYPE = 'git'
DEFAULT_PLAYBOOK = 'local.yml' DEFAULT_PLAYBOOK = 'local.yml'
PLAYBOOK_ERRORS = {1: 'File does not exist', PLAYBOOK_ERRORS = {1: 'File does not exist',
2: 'File is not readable'} 2: 'File is not readable'}
@ -96,20 +98,24 @@ def select_playbook(path, args):
def main(args): def main(args):
""" Set up and run a local playbook """ """ Set up and run a local playbook """
usage = "%prog [options] [playbook.yml]" usage = "%prog [options] [playbook.yml]"
parser = OptionParser(usage=usage) parser = utils.SortedOptParser(usage=usage)
parser.add_option('--purge', default=False, action='store_true', parser.add_option('--purge', default=False, action='store_true',
help='purge git checkout after playbook run') help='purge checkout after playbook run')
parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true', parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true',
help='only run the playbook if the repository has been updated') help='only run the playbook if the repository has been updated')
parser.add_option('-d', '--directory', dest='dest', default=None, parser.add_option('-d', '--directory', dest='dest', default=None,
help='directory to clone the git repository to') help='directory to checkout repository to')
parser.add_option('-U', '--url', dest='url', default=None, parser.add_option('-U', '--url', dest='url', default=None,
help='URL of the git repository') help='URL of the playbook repository')
parser.add_option('-C', '--checkout', dest='checkout', parser.add_option('-C', '--checkout', dest='checkout',
default="HEAD", help='branch/tag/commit to checkout. '
help='branch/tag/commit to checkout; defaults to HEAD') 'Defaults to behavior of repository module.')
parser.add_option('-i', '--inventory-file', dest='inventory', parser.add_option('-i', '--inventory-file', dest='inventory',
help="location of the inventory host file") help="location of the inventory host file")
parser.add_option('-m', '--module-name', dest='module_name',
default=DEFAULT_REPO_TYPE,
help='Module name used to check out repository. '
'Default is %s.' % DEFAULT_REPO_TYPE)
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
if not options.dest: if not options.dest:
@ -119,7 +125,7 @@ def main(args):
options.dest = os.path.abspath(options.dest) options.dest = os.path.abspath(options.dest)
if not options.url: if not options.url:
parser.error("URL for git repo not specified, use -h for help") parser.error("URL for repository not specified, use -h for help")
return 1 return 1
now = datetime.datetime.now() now = datetime.datetime.now()
@ -127,9 +133,16 @@ def main(args):
inv_opts = 'localhost,' inv_opts = 'localhost,'
limit_opts = 'localhost:%s:127.0.0.1' % socket.getfqdn() limit_opts = 'localhost:%s:127.0.0.1' % socket.getfqdn()
git_opts = "repo=%s dest=%s version=%s" % (options.url, options.dest, options.checkout) base_opts = '-c local --limit "%s"' % limit_opts
cmd = 'ansible all -c local -i "%s" --limit "%s" -m git -a "%s"' % ( repo_opts = "name=%s dest=%s" % (options.url, options.dest)
inv_opts, limit_opts, git_opts if options.checkout:
repo_opts += ' version=%s' % options.checkout
path = utils.plugins.module_finder.find_plugin(options.module_name)
if path is None:
sys.stderr.write("module '%s' not found.\n" % options.module_name)
return 1
cmd = 'ansible all -i "%s" %s -m %s -a "%s"' % (
inv_opts, base_opts, options.module_name, repo_opts
) )
rc, out = _run(cmd) rc, out = _run(cmd)
if rc != 0: if rc != 0:
@ -144,7 +157,7 @@ def main(args):
print >>sys.stderr, "Could not find a playbook to run." print >>sys.stderr, "Could not find a playbook to run."
return 1 return 1
cmd = 'ansible-playbook -c local --limit "%s" %s' % (limit_opts, playbook) cmd = 'ansible-playbook %s %s' % (base_opts, playbook)
if options.inventory: if options.inventory:
cmd += ' -i "%s"' % options.inventory cmd += ' -i "%s"' % options.inventory
os.chdir(options.dest) os.chdir(options.dest)