blob: bf3bb0109772fa4a1ae670aaad8535ef64568ded [file] [log] [blame]
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +03001#!/usr/bin/env python
2
3import argparse
4import os
5import sys
6
7import json
8
9sys.path.append(os.getcwd())
10try:
11 from tcp_tests.managers.jenkins.client import JenkinsClient
12except ImportError:
13 print("ImportError: Run the application from the tcp-qa directory or "
14 "set the PYTHONPATH environment variable to directory which contains"
15 " ./tcp_tests")
16 sys.exit(1)
17
18
19EXIT_CODES = {
20 "SUCCESS": 0,
21 # 1 - python runtime execution error
22 # 2 - job unknown status
23 "FAILURE": 3,
24 "UNSTABLE": 4,
25 "ABORTED": 5,
26 "DISABLED": 6
27 # 10 - invalid cli options
28}
29
30
31def load_params():
32 """
33 Parse CLI arguments and environment variables
34
35 Returns: ArgumentParser instance
36 """
37 env_host = os.environ.get('JENKINS_URL', None)
38 env_username = os.environ.get('JENKINS_USER', None)
39 env_password = os.environ.get('JENKINS_PASS', None)
40 env_start_timeout = os.environ.get('JENKINS_START_TIMEOUT', 1800)
41 env_build_timeout = os.environ.get('JENKINS_BUILD_TIMEOUT', 3600 * 4)
42
43 parser = argparse.ArgumentParser(description=(
44 'Host, username and password may be specified either by the command '
45 'line arguments or using environment variables: JENKINS_URL, '
46 'JENKINS_USER, JENKINS_PASS, JENKINS_START_TIMEOUT, '
47 'JENKINS_BUILD_TIMEOUT. \nCommand line arguments have the highest '
48 'priority, after that the environment variables are used as defaults.'
49 ))
50 parser.add_argument('--host',
51 metavar='JENKINS_URL',
52 help='Jenkins Host',
53 default=env_host)
54 parser.add_argument('--username',
55 metavar='JENKINS_USER',
56 help='Jenkins Username', default=env_username)
57 parser.add_argument('--password',
58 metavar='JENKINS_PASS',
59 help='Jenkins Password or API token',
60 default=env_password)
61 parser.add_argument('--start-timeout',
62 metavar='JENKINS_START_TIMEOUT',
63 help='Timeout waiting until build is started',
64 default=env_start_timeout,
65 type=int)
66 parser.add_argument('--build-timeout',
67 metavar='JENKINS_BUILD_TIMEOUT',
68 help='Timeout waiting until build is finished',
69 default=env_build_timeout,
70 type=int)
71 parser.add_argument('--job-name',
72 help='Jenkins job name to run',
73 default=None)
74 parser.add_argument('--job-parameters',
75 metavar='json-dict',
76 help=('Job parameters to use instead of default '
77 'values, as a json string, for example: '
78 '--job-parameters=\'{"SALT_MASTER_URL": '
79 '"http://localhost:6969"}\''),
80 default={}, type=json.loads)
81 parser.add_argument('--job-output-prefix',
82 help=('Jenkins job output prefix for each line in the '
83 'output, if --verbose is enabled. Useful for the'
84 ' pipelines that use multiple different runs of '
85 'jobs. The string is a template for python '
86 'format() function where the following arguments'
87 ' are allowed: job_name, build_number. '
88 'Example: --job-output-prefix=\"[ {job_name} '
89 '#{build_number}, core ]\"'),
90 default='',
91 type=str)
92 parser.add_argument('--verbose',
93 action='store_const',
94 const=True,
95 help='Show build console output',
96 default=False)
97 return parser
98
99
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200100def print_build_header(build, job_params, build_timeout):
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300101 print('\n#############################################################')
102 print('##### Building job [{0}] #{1} (timeout={2}) with the following '
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200103 'parameters:'.format(build[0], build[1], build_timeout))
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300104 print('##### ' + '\n##### '.join(
105 [str(key) + ": " + str(val) for key, val in job_params.iteritems()]
106 ))
107 print('#############################################################')
108
109
110def print_build_footer(build, result, url):
111 print('\n\n#############################################################')
112 print('##### Completed job [{0}] #{1} at {2}: {3}'
113 .format(build[0], build[1], url, result))
114 print('#############################################################\n')
115
116
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200117def run_job(host, username, password,
118 job_name, job_parameters=None, job_output_prefix='',
119 start_timeout=1800, build_timeout=3600 * 4, verbose=False):
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300120
121 jenkins = JenkinsClient(
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200122 host=host,
123 username=username,
124 password=password)
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300125
Hanna Arhipova874c68f2021-03-29 15:57:19 +0300126 job_params = jenkins.make_defaults_params(job_name)
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200127 if job_parameters is not None: # job_parameters = {}
128 job_params.update(job_parameters)
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300129
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200130 build = jenkins.run_build(job_name,
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300131 job_params,
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200132 verbose=verbose,
133 timeout=start_timeout)
134 if verbose:
135 print_build_header(build, job_params, build_timeout)
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300136
Dennis Dmitriev13e804b2018-10-09 19:25:14 +0300137 try:
138 jenkins.wait_end_of_build(
139 name=build[0],
140 build_id=build[1],
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200141 timeout=build_timeout,
Dennis Dmitriev13e804b2018-10-09 19:25:14 +0300142 interval=1,
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200143 verbose=verbose,
144 job_output_prefix=job_output_prefix)
Dennis Dmitrievefe5c0b2018-10-24 20:35:26 +0300145 except Exception as e:
Dennis Dmitriev13e804b2018-10-09 19:25:14 +0300146 print(str(e))
147 raise
148
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300149 result = jenkins.build_info(name=build[0],
150 build_id=build[1])['result']
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200151 if verbose:
152 print_build_footer(build, result, host)
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300153
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200154 return result
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300155
156
157def main(args=None):
158 parser = load_params()
159 opts = parser.parse_args()
160
161 if opts.host is None or opts.job_name is None:
162 print("JENKINS_URL and a job name are required!")
163 parser.print_help()
164 return 10
165 else:
Dennis Dmitriev2a498732018-12-21 18:30:23 +0200166 result = run_job(
167 opts.host,
168 opts.username,
169 opts.password,
170 opts.job_name,
171 opts.job_parameters,
172 opts.job_output_prefix,
173 opts.start_timeout,
174 opts.build_timeout,
175 opts.verbose)
176 return EXIT_CODES.get(result, 2)
Dennis Dmitriev3ec2e532018-06-08 04:33:34 +0300177
178
179if __name__ == "__main__":
180 sys.exit(main())