aboutsummaryrefslogtreecommitdiff
path: root/yadp_builder.py
blob: 1d841549b1e240f06a5b9cc890afde77f5c730a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/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)