| #!/usr/bin/python3 |
| |
| import argparse |
| import yaml |
| import os |
| from jinja2 import FileSystemLoader, Environment |
| import jenkins |
| import logging |
| |
| |
| class LoaderMeta(type): |
| |
| def __new__(metacls, __name__, __bases__, __dict__): |
| """Add include constructer to class.""" |
| |
| # register the include constructor on the class |
| cls = super().__new__(metacls, __name__, __bases__, __dict__) |
| cls.add_constructor('!include', cls.construct_include) |
| |
| return cls |
| |
| |
| class Loader(yaml.Loader, metaclass=LoaderMeta): |
| """YAML Loader with `!include` constructor.""" |
| |
| def __init__(self, stream): |
| """Initialise Loader.""" |
| |
| try: |
| self._root = os.path.split(stream.name)[0] |
| except AttributeError: |
| self._root = os.path.curdir |
| |
| super().__init__(stream) |
| |
| def construct_include(self, node): |
| if isinstance(node, yaml.ScalarNode): |
| return self.extractFile(self.construct_scalar(node)) |
| |
| elif isinstance(node, yaml.SequenceNode): |
| result = [] |
| for filename in self.construct_sequence(node): |
| result += self.extractFile(filename) |
| return result |
| |
| elif isinstance(node, yaml.MappingNode): |
| result = {} |
| for k,v in self.construct_mapping(node).iteritems(): |
| result[k] = self.extractFile(v) |
| return result |
| |
| else: |
| print("Error:: unrecognised node type in !include statement") |
| raise yaml.constructor.ConstructorError |
| |
| |
| def extractFile(self, filename): |
| filepath = os.path.join(self._root, filename) |
| with open(filepath, 'r') as f: |
| return yaml.load(f, Loader=Loader) |
| |
| |
| def jinja2_from_template(directory, template_name, data, dryrun=False): |
| loader = FileSystemLoader(directory) |
| env = Environment(loader=loader) |
| template = env.get_template(template_name) |
| return template.render(hosts=data, dryrun=dryrun) |
| |
| |
| def get_parser(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('-u', '--username', type=str, |
| default=os.environ.get('JJB_USER'), |
| help='Username for Jenkins server') |
| parser.add_argument('-p', '--password', type=str, |
| default=os.environ.get('JJB_PASSWORD'), |
| help='Password for Jenkins server') |
| parser.add_argument('-s', '--server', type=str, |
| default='http://localhost:8080', |
| help='Jenkins server URL. e.g. http://localhost:8080') |
| parser.add_argument('-i', '--inventory', type=str, default='hosts', |
| help='specify inventory host path') |
| parser.add_argument('-l', '--loglevel', default='INFO', |
| help="Setting logging level, default: %(default)s") |
| parser.add_argument('--dryrun', action='store_true', |
| help='Do not publish to Jenkins') |
| parser.add_argument('--local', action='store_true', |
| help='Create tmp file only, to be used with dryrun.') |
| return parser |
| |
| |
| if __name__ == '__main__': |
| parser = get_parser() |
| args = parser.parse_args() |
| logging.basicConfig(level=args.loglevel) |
| with open(args.inventory, 'r') as f: |
| data = yaml.load(f, Loader=Loader) |
| logging.debug(data) |
| template_output = jinja2_from_template( |
| './templates', |
| 'configure-yadocker-cloud.groovy.j2', data) |
| |
| if not args.local: |
| server = jenkins.Jenkins(args.server, username=args.username, |
| password=args.password) |
| if args.dryrun: |
| with open('/tmp/configure-yadocker-cloud.groovy', 'w') as fw: |
| fw.write(template_output) |
| template_output = jinja2_from_template( |
| './templates', |
| 'configure-yadocker-cloud.groovy.j2', data, args.dryrun) |
| if not args.local: |
| publishdry = server.run_script(template_output) |
| if 'error' in publishdry: |
| logging.info(publishdry) |
| exit(1) |
| logging.info(publishdry) |
| else: |
| logging.info('Template file created at \ |
| /tmp/configure-yadocker-cloud.groovy') |
| else: |
| publish = server.run_script(template_output) |
| logging.info(publish) |