| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- #!/usr/bin/env python
- import os
- import argparse
- import json
- import sys
- from string import Template
- from subprocess import call
- import tempfile
- import time
- STORAGE = '/opt/docker/etc/.registry/provision.json'
- PROVISION_DIR = '/opt/docker/provision/'
- PLAYBOOK_TAGS=['bootstrap', 'build', 'onbuild', 'entrypoint']
- PLAYBOOK = Template(
- """---
- - hosts: all
- vars_files:
- - ./variables-webdevops.yml
- - ./variables.yml
- roles:
- - $roles
- """)
- def readJson():
- ret = {}
- # create registry directory if it doesn't exists
- if not os.path.exists(os.path.dirname(STORAGE)):
- os.mkdir(os.path.dirname(STORAGE))
- # try to read file
- if os.path.isfile(STORAGE):
- f=open(STORAGE).read()
- ret = json.loads(f)
- return ret
- def saveJson(data):
- with open(STORAGE, 'w') as f:
- json.dump(data, f)
- def buildRoleList(tags):
- json = readJson()
- roleList = {}
- # fetch roles list for each tag
- for tag in tags:
- if tag in json:
- for role in json[tag]:
- roleRow = json[tag][role]
- if role not in roleList:
- roleList[role] = {}
- if 'tags' not in roleList[role]:
- roleList[role]['tags'] = {}
- roleList[role]['role'] = role
- roleList[role]['added'] = roleRow['added']
- roleList[role]['priority'] = roleRow['priority']
- roleList[role]['tags'][tag] = tag
- return roleList
- def buildSortedRoleList(tags):
- roleList = buildRoleList(tags)
- # sort list
- roleList = sorted(roleList, key=lambda x: (roleList[x]['priority'], roleList[x]['added']))
- return roleList
- def buildPlaybook(roleList):
- ## build playbook
- ret = PLAYBOOK.substitute(
- roles = "\n - ".join(roleList)
- )
- return ret
- def buildPlaybookFromArgs(args):
- roleList = []
- ## add roles from tag (if use registry is active)
- if args.useRegistry and args.tags:
- roleList.extend(buildSortedRoleList(args.tags))
- ## add roles from command arguments
- if args.roles:
- for role in args.roles:
- roleList.extend(role.split(','))
- if roleList:
- return buildPlaybook(roleList)
- else:
- return False
- def actionRun(args):
- if args.playbook:
- ## predefined playbook
- playbook = args.playbook
- else:
- ## dynamic playbook
- playbookContent = buildPlaybookFromArgs(args)
- if playbookContent:
- f = tempfile.NamedTemporaryFile(dir=PROVISION_DIR, prefix='playbook.', suffix='.yml', delete=False)
- f.write(playbookContent)
- f.close()
- playbook = f.name
- else:
- ## nothing to do
- sys.exit(0)
- ## build ansible command with args
- cmd = [
- 'ansible-playbook',
- playbook,
- '-i', 'localhost,',
- '--connection=local',
- ]
- if args.tags:
- cmd.extend([
- '--tags=' + ','.join(args.tags)
- ])
- if args.args:
- cmd.extend(args.args)
- ## run ansible
- retval = call(cmd)
- ## cleanup dynamic playbook
- if not args.playbook:
- os.unlink(playbook)
- sys.exit(retval)
- def actionPlaybook(args):
- playbook = buildPlaybookFromArgs(args)
- if playbook:
- print playbook
- else:
- sys.exit(1)
- def actionList(args):
- json = readJson()
- list = {}
- for tag in args.tags:
- if tag in json:
- for role in json[tag]:
- print role
- def actionAdd(args):
- json = readJson()
- for tag in args.tags:
- for role in args.role:
- if tag not in json:
- json[tag] = {}
- json[tag][role] = {
- 'name': role,
- 'added': int(time.time()),
- 'priority': args.priority
- }
- saveJson(json)
- def actionSummary(args):
- # list all roles in each possible tag
- for tag in PLAYBOOK_TAGS:
- roleList = buildRoleList([tag])
- if roleList:
- maxLength = len(max(roleList.keys(), key=len))
- print "Roles in " + tag + ":"
- for role in roleList:
- print ' - ' + role.ljust(maxLength, ' ') + ' [priority: ' + str(roleList[role]['priority']) + ']'
- print ''
- def main(args):
- actions = {
- 'list': actionList,
- 'add': actionAdd,
- 'summary': actionSummary,
- 'playbook': actionPlaybook,
- 'run': actionRun
- }
- func = actions.get(args.action, lambda: "nothing")
- return func(args)
- if __name__ == '__main__':
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers(
- title='subcommands',
- dest='action'
- )
- ###################################
- ## SUMMARY command
- summary = subparsers.add_parser('summary')
- ###################################
- ## RUN command
- run = subparsers.add_parser('run')
- run.add_argument(
- '--tag',
- dest='tags',
- choices=PLAYBOOK_TAGS,
- required=True,
- action='append',
- help='Ansible tag'
- )
- run.add_argument(
- '--playbook',
- dest='playbook',
- help='Ansible playbook'
- )
- run.add_argument(
- '--use-registry',
- dest='useRegistry',
- action='store_true',
- help='Use registred roles'
- )
- run.add_argument(
- '--role',
- dest='roles',
- action='append',
- help='Ansible role'
- )
- run.add_argument('args', nargs=argparse.REMAINDER)
- ###################################
- ## PLAYBOOK command
- playbook = subparsers.add_parser('playbook')
- playbook.add_argument(
- '--tag',
- dest='tags',
- choices=PLAYBOOK_TAGS,
- required=True,
- action='append',
- help='Ansible tag'
- )
- playbook.add_argument(
- '--use-registry',
- dest='useRegistry',
- action='store_true',
- help='Use registred roles'
- )
- playbook.add_argument(
- '--role',
- dest='roles',
- action='append',
- help='Ansible tag'
- )
- playbook.add_argument('args', nargs=argparse.REMAINDER)
- ###################################
- ## LIST command
- list = subparsers.add_parser('list')
- list.add_argument(
- '--tag',
- dest='tags',
- choices=PLAYBOOK_TAGS,
- required=True,
- action='append',
- help='Ansible tag'
- )
- list.add_argument('args', nargs=argparse.REMAINDER)
- ###################################
- ## ADD command
- add = subparsers.add_parser('add')
- add.add_argument(
- '--tag',
- dest='tags',
- choices=PLAYBOOK_TAGS,
- required=True,
- action='append',
- help='Ansible tag'
- )
- add.add_argument(
- '--priority',
- type=int,
- default=100,
- dest='priority',
- help='Priority for role [default 100, 1 is most important]'
- )
- add.add_argument('role', metavar='roles', nargs='+', help='Ansible roles')
- add.add_argument('args', nargs=argparse.REMAINDER)
- ## Execute
- args = parser.parse_args()
- main(args)
|