ansible: Add rootnodes in new cluster
[lttng-ci.git] / automation / ansible / scripts / update_jenkins_node.py
1 #!/usr/bin/python3
2
3 import argparse
4 import configparser
5 import json
6 import sys
7 import xml.etree.ElementTree
8
9 import jenkins
10
11 def get_argument_parser():
12 parser = argparse.ArgumentParser(
13 prog='update_jenkins_node.py',
14 description='Create, update, or delete Jenkins nodes'
15 )
16 parser.add_argument(
17 '-u', '--url', default=None,
18 help='Jenkins server URL including protocol'
19 )
20 parser.add_argument(
21 '--user', default=None,
22 help='Jenkins username'
23 )
24 parser.add_argument(
25 '--password', default=None,
26 help='Jenkins password'
27 )
28 parser.add_argument(
29 '-n', '--node', default=None, required=True,
30 help='The name of the node to manage in Jenkins'
31 )
32 parser.add_argument(
33 '-c', '--node-config', default=[], action='append',
34 help='An equals-separated set path=value[=attrib]. When attrib is not set, text is assumed'
35 )
36 parser.add_argument(
37 '-f', '--config-file', default=None, type=argparse.FileType('r'),
38 help='An INI config file as used by jenkins_jobs'
39 )
40 parser.add_argument(
41 '-s', '--state', default='online',
42 choices=['online', 'offline', 'absent'],
43 help='The state of the Jenkins node'
44 )
45 parser.add_argument(
46 '-m', '--message', default='',
47 help='A message to set for the offline reason of a node'
48 )
49 parser.add_argument(
50 '-j', '--json', default='',
51 help='Additional config in a json dictionary which will be appended after -c items',
52 )
53 return parser
54
55
56 def manage_node(url, user, password, node, state, offline_message='', config={}):
57 server = jenkins.Jenkins(url, username=user, password=password)
58 exists = server.node_exists(node)
59 node_info = {}
60 changed = False
61 if exists and state == 'absent':
62 server.delete_node(node)
63 changed = True
64 if not exists and state != 'absent':
65 server.create_node(node, numExecutors=1, remoteFS='/home/jenkins',
66 launcher=jenkins.LAUNCHER_SSH)
67 changed = True
68 if state != 'absent':
69 # Check configuration
70 updated = False
71 node_config = xml.etree.ElementTree.fromstring(server.get_node_config(node))
72 for key, value in config.items():
73 element = node_config.find(key)
74 new_element = None
75 current_key = key
76 while element is None:
77 head = key.rsplit('/', 1)[0] if '/' in current_key else None
78 tail = key.rsplit('/', 1)[1] if '/' in current_key else current_key
79 e = xml.etree.ElementTree.Element(tail)
80 if new_element is not None:
81 e.append(new_element)
82 new_element = None
83 if head is None:
84 node_config.append(e)
85 element = node_config.find(key)
86 else:
87 parent = node_config.find(head)
88 if parent:
89 parent.append(e)
90 element = node_config.find(key)
91 else:
92 new_element = e
93 current_key = head
94 continue
95
96 if value['attrib'] is None:
97 if element.text != value['value']:
98 updated = True
99 element.text = value['value']
100 else:
101 try:
102 if element.attrib[value['attrib']] != value['value']:
103 updated = True
104 element.attrib[value['attrib']] = value['value']
105 except KeyError:
106 element.attrib[value['attrib']] = value['value']
107 updated = True
108 if updated:
109 xml_string = xml.etree.ElementTree.tostring(
110 node_config,
111 xml_declaration=True,
112 encoding='unicode'
113 )
114 server.reconfig_node(node, xml_string)
115 changed = True
116 # Online/offline
117 node_info = server.get_node_info(node)
118 if node_info['offline'] and state == 'online':
119 server.enable_node(node)
120 changed = True
121 if not node_info['offline'] and state == 'offline':
122 server.disable_node(node, offline_message)
123 changed = True
124 return changed
125
126
127 if __name__ == '__main__':
128 parser = get_argument_parser()
129 args = parser.parse_args()
130 if args.config_file is not None:
131 config = configparser.ConfigParser()
132 config.read_file(args.config_file)
133 if 'jenkins' not in config.sections():
134 print("[jenkins] section not found")
135 sys.exit(1)
136 if args.url is None:
137 args.url = config.get('jenkins', 'url')
138 if args.user is None:
139 args.user = config['jenkins']['user']
140 if args.password is None:
141 args.password = config['jenkins']['password']
142 assert(args.user is not None)
143 assert(args.url is not None)
144 assert(args.password is not None)
145 node_config = {}
146 for entry in args.node_config:
147 key, value = entry.split('=', 1)
148 node_config[key] = {
149 'attrib': value.split('=', 1)[1] if '=' in value else None,
150 'value': value.split('=', 1)[0] if '=' in value else value,
151 }
152 if args.json:
153 for key, value in json.loads(args.json).items():
154 node_config[key] = {
155 'attrib': value.split('=', 1)[1] if '=' in value else None,
156 'value': value.split('=', 1)[0] if '=' in value else value,
157 }
158 manage_node(
159 args.url, args.user, args.password, args.node, args.state,
160 args.message, node_config
161 )
This page took 0.035353 seconds and 4 git commands to generate.