blob: 1d841549b1e240f06a5b9cc890afde77f5c730a4 [file] [log] [blame]
Kelley Spoond2c4a362022-04-07 15:08:12 -05001#!/usr/bin/python3
2
Benjamin Copeland4e096712020-08-11 16:09:55 +01003import argparse
4import yaml
5import os
6from jinja2 import FileSystemLoader, Environment
7import jenkins
8import logging
9
10
11class LoaderMeta(type):
12
13 def __new__(metacls, __name__, __bases__, __dict__):
14 """Add include constructer to class."""
15
16 # register the include constructor on the class
17 cls = super().__new__(metacls, __name__, __bases__, __dict__)
18 cls.add_constructor('!include', cls.construct_include)
19
20 return cls
21
22
23class Loader(yaml.Loader, metaclass=LoaderMeta):
24 """YAML Loader with `!include` constructor."""
25
26 def __init__(self, stream):
27 """Initialise Loader."""
28
29 try:
30 self._root = os.path.split(stream.name)[0]
31 except AttributeError:
32 self._root = os.path.curdir
33
34 super().__init__(stream)
35
36 def construct_include(self, node):
37 if isinstance(node, yaml.ScalarNode):
38 return self.extractFile(self.construct_scalar(node))
39
40 elif isinstance(node, yaml.SequenceNode):
41 result = []
42 for filename in self.construct_sequence(node):
43 result += self.extractFile(filename)
44 return result
45
46 elif isinstance(node, yaml.MappingNode):
47 result = {}
48 for k,v in self.construct_mapping(node).iteritems():
49 result[k] = self.extractFile(v)
50 return result
51
52 else:
Kelley Spoond2c4a362022-04-07 15:08:12 -050053 print("Error:: unrecognised node type in !include statement")
Benjamin Copeland4e096712020-08-11 16:09:55 +010054 raise yaml.constructor.ConstructorError
55
56
57 def extractFile(self, filename):
58 filepath = os.path.join(self._root, filename)
59 with open(filepath, 'r') as f:
60 return yaml.load(f, Loader=Loader)
61
62
63def jinja2_from_template(directory, template_name, data, dryrun=False):
64 loader = FileSystemLoader(directory)
65 env = Environment(loader=loader)
66 template = env.get_template(template_name)
67 return template.render(hosts=data, dryrun=dryrun)
68
69
70def get_parser():
71 parser = argparse.ArgumentParser()
72 parser.add_argument('-u', '--username', type=str,
73 default=os.environ.get('JJB_USER'),
74 help='Username for Jenkins server')
75 parser.add_argument('-p', '--password', type=str,
76 default=os.environ.get('JJB_PASSWORD'),
77 help='Password for Jenkins server')
78 parser.add_argument('-s', '--server', type=str,
79 default='http://localhost:8080',
80 help='Jenkins server URL. e.g. http://localhost:8080')
81 parser.add_argument('-i', '--inventory', type=str, default='hosts',
82 help='specify inventory host path')
83 parser.add_argument('-l', '--loglevel', default='INFO',
84 help="Setting logging level, default: %(default)s")
85 parser.add_argument('--dryrun', action='store_true',
86 help='Do not publish to Jenkins')
87 parser.add_argument('--local', action='store_true',
88 help='Create tmp file only, to be used with dryrun.')
89 return parser
90
91
92if __name__ == '__main__':
93 parser = get_parser()
94 args = parser.parse_args()
95 logging.basicConfig(level=args.loglevel)
96 with open(args.inventory, 'r') as f:
97 data = yaml.load(f, Loader=Loader)
98 logging.debug(data)
99 template_output = jinja2_from_template(
100 './templates',
101 'configure-yadocker-cloud.groovy.j2', data)
102
103 if not args.local:
104 server = jenkins.Jenkins(args.server, username=args.username,
105 password=args.password)
106 if args.dryrun:
107 with open('/tmp/configure-yadocker-cloud.groovy', 'w') as fw:
108 fw.write(template_output)
109 template_output = jinja2_from_template(
110 './templates',
111 'configure-yadocker-cloud.groovy.j2', data, args.dryrun)
112 if not args.local:
113 publishdry = server.run_script(template_output)
114 if 'error' in publishdry:
115 logging.info(publishdry)
116 exit(1)
117 logging.info(publishdry)
118 else:
119 logging.info('Template file created at \
120 /tmp/configure-yadocker-cloud.groovy')
121 else:
122 publish = server.run_script(template_output)
123 logging.info(publish)