blob: 468cdea367cc58916a096ae4fe2d5a01bad76db0 [file] [log] [blame]
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +04001import jenkins
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -05002from xml.dom import minidom
3from cvp_checks import utils
4import json
5import pytest
Mikhail Kraynov351e8412018-10-04 18:27:44 +04006import time
7import os
8from pygerrit2 import GerritRestAPI, HTTPBasicAuth
9from requests import HTTPError
10import git
mkraynov360c30d2018-09-27 17:02:45 +040011import ldap
12import ldap.modlist as modlist
Mikhail Kraynov351e8412018-10-04 18:27:44 +040013
14def join_to_gerrit(local_salt_client, gerrit_user, gerrit_password):
15 gerrit_port = local_salt_client.cmd(
16 'I@gerrit:client and not I@salt:master',
17 'pillar.get',
18 ['_param:haproxy_gerrit_bind_port'],
19 expr_form='compound').values()[0]
20 gerrit_address = local_salt_client.cmd(
21 'I@gerrit:client and not I@salt:master',
22 'pillar.get',
23 ['_param:haproxy_gerrit_bind_host'],
24 expr_form='compound').values()[0]
25 url = 'http://{0}:{1}'.format(gerrit_address,gerrit_port)
26 auth = HTTPBasicAuth(gerrit_user, gerrit_password)
27 rest = GerritRestAPI(url=url, auth=auth)
28 return rest
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -050029
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +040030def join_to_jenkins(local_salt_client, jenkins_user, jenkins_password):
31 jenkins_port = local_salt_client.cmd(
32 'I@jenkins:client and not I@salt:master',
33 'pillar.get',
34 ['_param:haproxy_jenkins_bind_port'],
35 expr_form='compound').values()[0]
36 jenkins_address = local_salt_client.cmd(
37 'I@jenkins:client and not I@salt:master',
38 'pillar.get',
39 ['_param:haproxy_jenkins_bind_host'],
40 expr_form='compound').values()[0]
41 jenkins_url = 'http://{0}:{1}'.format(jenkins_address,jenkins_port)
42 server = jenkins.Jenkins(jenkins_url, username=jenkins_user, password=jenkins_password)
43 return server
44
Mikhail Kraynov351e8412018-10-04 18:27:44 +040045def get_password(local_salt_client,service):
46 password = local_salt_client.cmd(
47 service,
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +040048 'pillar.get',
49 ['_param:openldap_admin_password'],
50 expr_form='pillar').values()[0]
Mikhail Kraynov351e8412018-10-04 18:27:44 +040051 return password
52
53def test_drivetrain_gerrit(local_salt_client):
54 gerrit_password = get_password(local_salt_client,'gerrit:client')
55 gerrit_error = ''
56 current_date = time.strftime("%Y%m%d-%H.%M.%S", time.localtime())
57 test_proj_name = "test-dt-{0}".format(current_date)
58 gerrit_port = local_salt_client.cmd(
59 'I@gerrit:client and not I@salt:master',
60 'pillar.get',
61 ['_param:haproxy_gerrit_bind_port'],
62 expr_form='compound').values()[0]
63 gerrit_address = local_salt_client.cmd(
64 'I@gerrit:client and not I@salt:master',
65 'pillar.get',
66 ['_param:haproxy_gerrit_bind_host'],
67 expr_form='compound').values()[0]
68 try:
69 #Connecting to gerrit and check connection
70 server = join_to_gerrit(local_salt_client,'admin',gerrit_password)
71 gerrit_check = server.get("/changes/?q=owner:self%20status:open")
72 #Check deleteproject plugin and skip test if the plugin is not installed
73 gerrit_plugins = server.get("/plugins/?all")
74 if 'deleteproject' not in gerrit_plugins:
75 pytest.skip("Delete-project plugin is not installed")
76 #Create test project and add description
77 server.put("/projects/"+test_proj_name)
78 server.put("/projects/"+test_proj_name+"/description",json={"description":"Test DriveTrain project","commit_message": "Update the project description"})
79 except HTTPError, e:
80 gerrit_error = e
81 try:
82 #Create test folder and init git
83 repo_dir = os.path.join(os.getcwd(),test_proj_name)
84 file_name = os.path.join(repo_dir, current_date)
85 repo = git.Repo.init(repo_dir)
86 #Add remote url for this git repo
87 origin = repo.create_remote('origin', 'http://admin:{1}@{2}:{3}/{0}.git'.format(test_proj_name,gerrit_password,gerrit_address,gerrit_port))
88 #Add commit-msg hook to automatically add Change-Id to our commit
89 os.system("curl -Lo {0}/.git/hooks/commit-msg 'http://admin:{1}@{2}:{3}/tools/hooks/commit-msg' > /dev/null 2>&1".format(repo_dir,gerrit_password,gerrit_address,gerrit_port))
90 os.system("chmod u+x {0}/.git/hooks/commit-msg".format(repo_dir))
91 #Create a test file
92 f = open(file_name, 'w+')
93 f.write("This is a test file for DriveTrain test")
94 f.close()
95 #Add file to git and commit it to Gerrit for review
96 repo.index.add([file_name])
97 repo.index.commit("This is a test commit for DriveTrain test")
98 repo.git.push("origin", "HEAD:refs/for/master")
99 #Get change id from Gerrit. Set Code-Review +2 and submit this change
100 changes = server.get("/changes/?q=project:{0}".format(test_proj_name))
101 last_change = changes[0].get('change_id')
102 server.post("/changes/{0}/revisions/1/review".format(last_change),json={"message":"All is good","labels":{"Code-Review":"+2"}})
103 server.post("/changes/{0}/submit".format(last_change))
104 except HTTPError, e:
105 gerrit_error = e
106 finally:
107 #Delete test project
108 server.post("/projects/"+test_proj_name+"/deleteproject~delete")
109 assert gerrit_error == '',\
110 'Something is wrong with Gerrit'.format(gerrit_error)
111
mkraynov360c30d2018-09-27 17:02:45 +0400112def test_drivetrain_openldap(local_salt_client):
113 '''Create a test user 'DT_test_user' in openldap,
114 add the user to admin group, login using the user to Jenkins.
115 Add the user to devops group in Gerrit and then login to Gerrit,
116 using test_user credentials. Finally, delete the user from admin
117 group and openldap
118 '''
119 ldap_password = get_password(local_salt_client,'openldap:client')
120 #Check that ldap_password is exists, otherwise skip test
121 if not ldap_password:
122 pytest.skip("Openldap service or openldap:client pillar \
123 are not found on this environment.")
124 ldap_port = local_salt_client.cmd(
125 'I@openldap:client and not I@salt:master',
126 'pillar.get',
127 ['_param:haproxy_openldap_bind_port'],
128 expr_form='compound').values()[0]
129 ldap_address = local_salt_client.cmd(
130 'I@openldap:client and not I@salt:master',
131 'pillar.get',
132 ['_param:haproxy_openldap_bind_host'],
133 expr_form='compound').values()[0]
134 ldap_dc = local_salt_client.cmd(
135 'openldap:client',
136 'pillar.get',
137 ['_param:openldap_dn'],
138 expr_form='pillar').values()[0]
139 ldap_con_admin = local_salt_client.cmd(
140 'openldap:client',
141 'pillar.get',
142 ['openldap:client:server:auth:user'],
143 expr_form='pillar').values()[0]
144 ldap_url = 'ldap://{0}:{1}'.format(ldap_address,ldap_port)
145 ldap_error = ''
146 ldap_result = ''
147 gerrit_result = ''
148 gerrit_error = ''
149 jenkins_error = ''
150 #Test user's CN
151 test_user_name = 'DT_test_user'
152 test_user = 'cn={0},ou=people,{1}'.format(test_user_name,ldap_dc)
153 #Admins group CN
154 admin_gr_dn = 'cn=admins,ou=groups,{0}'.format(ldap_dc)
155 #List of attributes for test user
156 attrs = {}
157 attrs['objectclass'] = ['organizationalRole','simpleSecurityObject','shadowAccount']
158 attrs['cn'] = test_user_name
159 attrs['uid'] = test_user_name
160 attrs['userPassword'] = 'aSecretPassw'
161 attrs['description'] = 'Test user for CVP DT test'
162 searchFilter = 'cn={0}'.format(test_user_name)
163 #Get a test job name from config
164 config = utils.get_configuration()
mkraynov058ee122018-11-30 13:15:49 +0400165 jenkins_cvp_job = config['jenkins_cvp_job']
mkraynov360c30d2018-09-27 17:02:45 +0400166 #Open connection to ldap and creating test user in admins group
167 try:
168 ldap_server = ldap.initialize(ldap_url)
169 ldap_server.simple_bind_s(ldap_con_admin,ldap_password)
170 ldif = modlist.addModlist(attrs)
171 ldap_server.add_s(test_user,ldif)
172 ldap_server.modify_s(admin_gr_dn,[(ldap.MOD_ADD, 'memberUid', [test_user_name],)],)
173 #Check search test user in LDAP
174 searchScope = ldap.SCOPE_SUBTREE
175 ldap_result = ldap_server.search_s(ldap_dc, searchScope, searchFilter)
176 except ldap.LDAPError, e:
177 ldap_error = e
178 try:
179 #Check connection between Jenkins and LDAP
180 jenkins_server = join_to_jenkins(local_salt_client,test_user_name,'aSecretPassw')
mkraynov058ee122018-11-30 13:15:49 +0400181 jenkins_version = jenkins_server.get_job_name(jenkins_cvp_job)
mkraynov360c30d2018-09-27 17:02:45 +0400182 #Check connection between Gerrit and LDAP
183 gerrit_server = join_to_gerrit(local_salt_client,'admin',ldap_password)
184 gerrit_check = gerrit_server.get("/changes/?q=owner:self%20status:open")
185 #Add test user to devops-contrib group in Gerrit and check login
186 _link = "/groups/devops-contrib/members/{0}".format(test_user_name)
187 gerrit_add_user = gerrit_server.put(_link)
188 gerrit_server = join_to_gerrit(local_salt_client,test_user_name,'aSecretPassw')
189 gerrit_result = gerrit_server.get("/changes/?q=owner:self%20status:open")
190 except HTTPError, e:
191 gerrit_error = e
192 except jenkins.JenkinsException, e:
193 jenkins_error = e
194 finally:
195 ldap_server.modify_s(admin_gr_dn,[(ldap.MOD_DELETE, 'memberUid', [test_user_name],)],)
196 ldap_server.delete_s(test_user)
197 ldap_server.unbind_s()
198 assert ldap_error == '', \
199 '''Something is wrong with connection to LDAP:
200 {0}'''.format(e)
201 assert jenkins_error == '', \
202 '''Connection to Jenkins was not established:
203 {0}'''.format(e)
204 assert gerrit_error == '', \
205 '''Connection to Gerrit was not established:
206 {0}'''.format(e)
207 assert ldap_result !=[], \
208 '''Test user was not found'''
Mikhail Kraynov351e8412018-10-04 18:27:44 +0400209
210def test_drivetrain_jenkins_job(local_salt_client):
211 jenkins_password = get_password(local_salt_client,'jenkins:client')
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400212 server = join_to_jenkins(local_salt_client,'admin',jenkins_password)
213 #Getting Jenkins test job name from configuration
214 config = utils.get_configuration()
215 jenkins_test_job = config['jenkins_test_job']
mkraynov058ee122018-11-30 13:15:49 +0400216 if not server.get_job_name(jenkins_test_job):
217 server.create_job(jenkins_test_job, jenkins.EMPTY_CONFIG_XML)
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400218 if server.get_job_name(jenkins_test_job):
219 next_build_num = server.get_job_info(jenkins_test_job)['nextBuildNumber']
220 #If this is first build number skip building check
221 if next_build_num != 1:
222 #Check that test job is not running at this moment,
223 #Otherwise skip the test
224 last_build_num = server.get_job_info(jenkins_test_job)['lastBuild'].get('number')
225 last_build_status = server.get_build_info(jenkins_test_job,last_build_num)['building']
226 if last_build_status:
227 pytest.skip("Test job {0} is already running").format(jenkins_test_job)
mkraynov058ee122018-11-30 13:15:49 +0400228 server.build_job(jenkins_test_job)
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400229 timeout = 0
230 #Use job status True by default to exclude timeout between build job and start job.
231 job_status = True
232 while job_status and ( timeout < 180 ):
Mikhail Kraynov351e8412018-10-04 18:27:44 +0400233 time.sleep(10)
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400234 timeout += 10
235 job_status = server.get_build_info(jenkins_test_job,next_build_num)['building']
236 job_result = server.get_build_info(jenkins_test_job,next_build_num)['result']
237 else:
238 pytest.skip("The job {0} was not found").format(test_job_name)
239 assert job_result == 'SUCCESS', \
240 '''Test job '{0}' build was not successfull or timeout is too small
241 '''.format(jenkins_test_job)
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500242
243def test_drivetrain_services_replicas(local_salt_client):
244 salt_output = local_salt_client.cmd(
Oleksii Zhurba0aeedf72018-07-30 11:24:01 -0500245 'I@gerrit:client',
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500246 'cmd.run',
247 ['docker service ls'],
248 expr_form='compound')
249 wrong_items = []
250 for line in salt_output[salt_output.keys()[0]].split('\n'):
251 if line[line.find('/') - 1] != line[line.find('/') + 1] \
252 and 'replicated' in line:
253 wrong_items.append(line)
254 assert len(wrong_items) == 0, \
255 '''Some DriveTrain services doesn't have expected number of replicas:
256 {}'''.format(json.dumps(wrong_items, indent=4))
257
258
259def test_drivetrain_components_and_versions(local_salt_client):
260 config = utils.get_configuration()
Oleksii Zhurba7b705372019-01-15 18:40:29 -0600261 if not config['drivetrain_version']:
262 version = \
263 local_salt_client.cmd(
264 'I@salt:master',
265 'pillar.get',
266 ['_param:mcp_version'],
267 expr_form='compound').values()[0] or \
268 local_salt_client.cmd(
269 'I@salt:master',
270 'pillar.get',
271 ['_param:apt_mk_version'],
272 expr_form='compound').values()[0]
273 if not version:
274 pytest.skip("drivetrain_version is not defined. Skipping")
275 else:
276 version = config['drivetrain_version']
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500277 salt_output = local_salt_client.cmd(
Oleksii Zhurba0aeedf72018-07-30 11:24:01 -0500278 'I@gerrit:client',
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500279 'cmd.run',
280 ['docker service ls'],
281 expr_form='compound')
Hanna Arhipovab8d04d52018-12-28 13:19:17 +0200282 # 'ldap_server' removed because it is an external component now v 1.1.8
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500283 not_found_services = ['gerrit_db', 'gerrit_server', 'jenkins_master',
284 'jenkins_slave01', 'jenkins_slave02',
Oleksii Zhurba753a03e2019-01-15 17:35:25 -0600285 'jenkins_slave03', 'ldap_admin', 'docker_registry',
286 'docker_visualizer']
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500287 version_mismatch = []
288 for line in salt_output[salt_output.keys()[0]].split('\n'):
289 for service in not_found_services:
290 if service in line:
291 not_found_services.remove(service)
292 if version != line.split()[4].split(':')[1]:
293 version_mismatch.append("{0}: expected "
294 "version is {1}, actual - {2}".format(service,version,
295 line.split()[4].split(':')[1]))
296 continue
297 assert len(not_found_services) == 0, \
298 '''Some DriveTrain components are not found:
299 {}'''.format(json.dumps(not_found_services, indent=4))
300 assert len(version_mismatch) == 0, \
301 '''Version mismatch found:
302 {}'''.format(json.dumps(version_mismatch, indent=4))
303
304
305def test_jenkins_jobs_branch(local_salt_client):
306 config = utils.get_configuration()
307 expected_version = config['drivetrain_version'] or []
308 if not expected_version or expected_version == '':
309 pytest.skip("drivetrain_version is not defined. Skipping")
Mikhail Kraynov351e8412018-10-04 18:27:44 +0400310 jenkins_password = get_password(local_salt_client,'jenkins:client')
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500311 version_mismatch = []
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400312 server = join_to_jenkins(local_salt_client,'admin',jenkins_password)
313 for job_instance in server.get_jobs():
314 job_name = job_instance.get('name')
315 job_config = server.get_job_config(job_name)
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500316 xml_data = minidom.parseString(job_config)
317 BranchSpec = xml_data.getElementsByTagName('hudson.plugins.git.BranchSpec')
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400318 #We use master branch for pipeline-library in case of 'testing,stable,nighlty' versions
319 if expected_version in ['testing','nightly','stable']:
320 expected_version = 'master'
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500321 if BranchSpec:
322 actual_version = BranchSpec[0].getElementsByTagName('name')[0].childNodes[0].data
Oleksii Zhurba753a03e2019-01-15 17:35:25 -0600323 if ( actual_version != expected_version ) and ( job_name not in ['upgrade-mcp-release'] ) :
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500324 version_mismatch.append("Job {0} has {1} branch."
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400325 "Expected {2}".format(job_name,
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500326 actual_version,
327 expected_version))
328 assert len(version_mismatch) == 0, \
329 '''Some DriveTrain jobs have version/branch mismatch:
330 {}'''.format(json.dumps(version_mismatch, indent=4))