blob: 3a9f1b6ed3f7f99c3a7155426debb68e5c5c7ce4 [file] [log] [blame]
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +04001import jenkins
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -05002from xml.dom import minidom
Hanna Arhipova16e93fb2019-01-23 19:03:01 +02003import utils
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -05004import 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
Hanna Arhipovae792be52019-02-13 13:28:11 +020014
Mikhail Kraynov351e8412018-10-04 18:27:44 +040015def join_to_gerrit(local_salt_client, gerrit_user, gerrit_password):
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -050016 gerrit_port = local_salt_client.pillar_get(
17 tgt='I@gerrit:client and not I@salt:master',
18 param='_param:haproxy_gerrit_bind_port',
19 expr_form='compound')
20 gerrit_address = local_salt_client.pillar_get(
21 tgt='I@gerrit:client and not I@salt:master',
22 param='_param:haproxy_gerrit_bind_host',
23 expr_form='compound')
Mikhail Kraynov351e8412018-10-04 18:27:44 +040024 url = 'http://{0}:{1}'.format(gerrit_address,gerrit_port)
25 auth = HTTPBasicAuth(gerrit_user, gerrit_password)
26 rest = GerritRestAPI(url=url, auth=auth)
27 return rest
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -050028
Hanna Arhipovae792be52019-02-13 13:28:11 +020029
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +040030def join_to_jenkins(local_salt_client, jenkins_user, jenkins_password):
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -050031 jenkins_port = local_salt_client.pillar_get(
32 tgt='I@jenkins:client and not I@salt:master',
33 param='_param:haproxy_jenkins_bind_port',
34 expr_form='compound')
35 jenkins_address = local_salt_client.pillar_get(
36 tgt='I@jenkins:client and not I@salt:master',
37 param='_param:haproxy_jenkins_bind_host',
38 expr_form='compound')
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +040039 jenkins_url = 'http://{0}:{1}'.format(jenkins_address,jenkins_port)
40 server = jenkins.Jenkins(jenkins_url, username=jenkins_user, password=jenkins_password)
41 return server
42
Hanna Arhipovae792be52019-02-13 13:28:11 +020043
Mikhail Kraynov351e8412018-10-04 18:27:44 +040044def get_password(local_salt_client,service):
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -050045 password = local_salt_client.pillar_get(
46 tgt=service,
47 param='_param:openldap_admin_password')
Mikhail Kraynov351e8412018-10-04 18:27:44 +040048 return password
49
Hanna Arhipovae792be52019-02-13 13:28:11 +020050
Hanna Arhipovab7e866c2019-04-10 13:49:56 +030051def test_drivetrain_gerrit(local_salt_client, check_cicd):
Mikhail Kraynov351e8412018-10-04 18:27:44 +040052 gerrit_password = get_password(local_salt_client,'gerrit:client')
53 gerrit_error = ''
54 current_date = time.strftime("%Y%m%d-%H.%M.%S", time.localtime())
55 test_proj_name = "test-dt-{0}".format(current_date)
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -050056 gerrit_port = local_salt_client.pillar_get(
57 tgt='I@gerrit:client and not I@salt:master',
58 param='_param:haproxy_gerrit_bind_port',
59 expr_form='compound')
60 gerrit_address = local_salt_client.pillar_get(
61 tgt='I@gerrit:client and not I@salt:master',
62 param='_param:haproxy_gerrit_bind_host',
63 expr_form='compound')
Mikhail Kraynov351e8412018-10-04 18:27:44 +040064 try:
65 #Connecting to gerrit and check connection
66 server = join_to_gerrit(local_salt_client,'admin',gerrit_password)
67 gerrit_check = server.get("/changes/?q=owner:self%20status:open")
68 #Check deleteproject plugin and skip test if the plugin is not installed
69 gerrit_plugins = server.get("/plugins/?all")
70 if 'deleteproject' not in gerrit_plugins:
71 pytest.skip("Delete-project plugin is not installed")
72 #Create test project and add description
73 server.put("/projects/"+test_proj_name)
74 server.put("/projects/"+test_proj_name+"/description",json={"description":"Test DriveTrain project","commit_message": "Update the project description"})
75 except HTTPError, e:
76 gerrit_error = e
77 try:
78 #Create test folder and init git
79 repo_dir = os.path.join(os.getcwd(),test_proj_name)
80 file_name = os.path.join(repo_dir, current_date)
81 repo = git.Repo.init(repo_dir)
82 #Add remote url for this git repo
83 origin = repo.create_remote('origin', 'http://admin:{1}@{2}:{3}/{0}.git'.format(test_proj_name,gerrit_password,gerrit_address,gerrit_port))
84 #Add commit-msg hook to automatically add Change-Id to our commit
85 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))
86 os.system("chmod u+x {0}/.git/hooks/commit-msg".format(repo_dir))
87 #Create a test file
88 f = open(file_name, 'w+')
89 f.write("This is a test file for DriveTrain test")
90 f.close()
91 #Add file to git and commit it to Gerrit for review
92 repo.index.add([file_name])
93 repo.index.commit("This is a test commit for DriveTrain test")
94 repo.git.push("origin", "HEAD:refs/for/master")
95 #Get change id from Gerrit. Set Code-Review +2 and submit this change
96 changes = server.get("/changes/?q=project:{0}".format(test_proj_name))
97 last_change = changes[0].get('change_id')
Hanna Arhipovab7e866c2019-04-10 13:49:56 +030098 server.post("/changes/{0}/revisions/1/review".format(last_change),json={"message": "All is good","labels":{"Code-Review":"+2"}})
Mikhail Kraynov351e8412018-10-04 18:27:44 +040099 server.post("/changes/{0}/submit".format(last_change))
100 except HTTPError, e:
101 gerrit_error = e
102 finally:
103 #Delete test project
104 server.post("/projects/"+test_proj_name+"/deleteproject~delete")
105 assert gerrit_error == '',\
106 'Something is wrong with Gerrit'.format(gerrit_error)
107
Hanna Arhipovae792be52019-02-13 13:28:11 +0200108
Hanna Arhipovab7e866c2019-04-10 13:49:56 +0300109def test_drivetrain_openldap(local_salt_client, check_cicd):
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300110 """
111 1. Create a test user 'DT_test_user' in openldap
112 2. Add the user to admin group
113 3. Login using the user to Jenkins
114 4. Check that no error occurred
115 5. Add the user to devops group in Gerrit and then login to Gerrit
116 using test_user credentials.
117 6 Start job in jenkins from this user
118 7. Get info from gerrit from this user
119 6. Finally, delete the user from admin
120 group and openldap
121 """
122
123 # TODO split to several test cases. One check - per one test method. Make the login process in fixture
mkraynov360c30d2018-09-27 17:02:45 +0400124 ldap_password = get_password(local_salt_client,'openldap:client')
125 #Check that ldap_password is exists, otherwise skip test
126 if not ldap_password:
127 pytest.skip("Openldap service or openldap:client pillar \
128 are not found on this environment.")
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500129 ldap_port = local_salt_client.pillar_get(
130 tgt='I@openldap:client and not I@salt:master',
131 param='_param:haproxy_openldap_bind_port',
132 expr_form='compound')
133 ldap_address = local_salt_client.pillar_get(
134 tgt='I@openldap:client and not I@salt:master',
135 param='_param:haproxy_openldap_bind_host',
136 expr_form='compound')
137 ldap_dc = local_salt_client.pillar_get(
138 tgt='openldap:client',
139 param='_param:openldap_dn')
140 ldap_con_admin = local_salt_client.pillar_get(
141 tgt='openldap:client',
142 param='openldap:client:server:auth:user')
mkraynov360c30d2018-09-27 17:02:45 +0400143 ldap_url = 'ldap://{0}:{1}'.format(ldap_address,ldap_port)
144 ldap_error = ''
145 ldap_result = ''
146 gerrit_result = ''
147 gerrit_error = ''
148 jenkins_error = ''
149 #Test user's CN
150 test_user_name = 'DT_test_user'
151 test_user = 'cn={0},ou=people,{1}'.format(test_user_name,ldap_dc)
152 #Admins group CN
153 admin_gr_dn = 'cn=admins,ou=groups,{0}'.format(ldap_dc)
154 #List of attributes for test user
155 attrs = {}
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300156 attrs['objectclass'] = ['organizationalRole', 'simpleSecurityObject', 'shadowAccount']
mkraynov360c30d2018-09-27 17:02:45 +0400157 attrs['cn'] = test_user_name
158 attrs['uid'] = test_user_name
159 attrs['userPassword'] = 'aSecretPassw'
160 attrs['description'] = 'Test user for CVP DT test'
161 searchFilter = 'cn={0}'.format(test_user_name)
162 #Get a test job name from config
163 config = utils.get_configuration()
mkraynov058ee122018-11-30 13:15:49 +0400164 jenkins_cvp_job = config['jenkins_cvp_job']
mkraynov360c30d2018-09-27 17:02:45 +0400165 #Open connection to ldap and creating test user in admins group
166 try:
167 ldap_server = ldap.initialize(ldap_url)
168 ldap_server.simple_bind_s(ldap_con_admin,ldap_password)
169 ldif = modlist.addModlist(attrs)
170 ldap_server.add_s(test_user,ldif)
171 ldap_server.modify_s(admin_gr_dn,[(ldap.MOD_ADD, 'memberUid', [test_user_name],)],)
172 #Check search test user in LDAP
173 searchScope = ldap.SCOPE_SUBTREE
174 ldap_result = ldap_server.search_s(ldap_dc, searchScope, searchFilter)
175 except ldap.LDAPError, e:
176 ldap_error = e
177 try:
178 #Check connection between Jenkins and LDAP
179 jenkins_server = join_to_jenkins(local_salt_client,test_user_name,'aSecretPassw')
mkraynov058ee122018-11-30 13:15:49 +0400180 jenkins_version = jenkins_server.get_job_name(jenkins_cvp_job)
mkraynov360c30d2018-09-27 17:02:45 +0400181 #Check connection between Gerrit and LDAP
182 gerrit_server = join_to_gerrit(local_salt_client,'admin',ldap_password)
183 gerrit_check = gerrit_server.get("/changes/?q=owner:self%20status:open")
184 #Add test user to devops-contrib group in Gerrit and check login
185 _link = "/groups/devops-contrib/members/{0}".format(test_user_name)
186 gerrit_add_user = gerrit_server.put(_link)
187 gerrit_server = join_to_gerrit(local_salt_client,test_user_name,'aSecretPassw')
188 gerrit_result = gerrit_server.get("/changes/?q=owner:self%20status:open")
189 except HTTPError, e:
190 gerrit_error = e
191 except jenkins.JenkinsException, e:
192 jenkins_error = e
193 finally:
194 ldap_server.modify_s(admin_gr_dn,[(ldap.MOD_DELETE, 'memberUid', [test_user_name],)],)
195 ldap_server.delete_s(test_user)
196 ldap_server.unbind_s()
197 assert ldap_error == '', \
198 '''Something is wrong with connection to LDAP:
199 {0}'''.format(e)
200 assert jenkins_error == '', \
201 '''Connection to Jenkins was not established:
202 {0}'''.format(e)
203 assert gerrit_error == '', \
204 '''Connection to Gerrit was not established:
205 {0}'''.format(e)
206 assert ldap_result !=[], \
207 '''Test user was not found'''
Mikhail Kraynov351e8412018-10-04 18:27:44 +0400208
Hanna Arhipovae792be52019-02-13 13:28:11 +0200209
Oleksii Zhurba67aaec92019-04-15 18:05:13 -0500210def test_drivetrain_services_replicas(local_salt_client, check_cicd):
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300211 """
212 # Execute ` salt -C 'I@gerrit:client' cmd.run 'docker service ls'` command to get info for each docker service like that:
213 "x5nzktxsdlm6 jenkins_slave02 replicated 0/1 docker-prod-local.artifactory.mirantis.com/mirantis/cicd/jnlp-slave:2019.2.0 "
214 # Check that each service has all replicas
215 """
Hanna Arhipovaf2660bd2019-02-08 17:25:39 +0200216 # TODO: replace with rerunfalures plugin
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300217 wrong_items = []
Hanna Arhipovaf2660bd2019-02-08 17:25:39 +0200218 for _ in range(4):
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300219 docker_services_by_nodes = local_salt_client.cmd(
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500220 tgt='I@gerrit:client',
221 param='docker service ls',
Hanna Arhipovaf2660bd2019-02-08 17:25:39 +0200222 expr_form='compound')
223 wrong_items = []
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300224 for line in docker_services_by_nodes[docker_services_by_nodes.keys()[0]].split('\n'):
Hanna Arhipovaf2660bd2019-02-08 17:25:39 +0200225 if line[line.find('/') - 1] != line[line.find('/') + 1] \
226 and 'replicated' in line:
227 wrong_items.append(line)
228 if len(wrong_items) == 0:
229 break
230 else:
231 print('''Some DriveTrain services doesn't have expected number of replicas:
232 {}\n'''.format(json.dumps(wrong_items, indent=4)))
233 time.sleep(5)
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300234 assert len(wrong_items) == 0
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500235
236
Hanna Arhipovab7e866c2019-04-10 13:49:56 +0300237def test_drivetrain_components_and_versions(local_salt_client, check_cicd):
Oleksii Zhurbab91c3142019-03-26 16:49:44 -0500238 """
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300239 1. Execute command `docker service ls --format "{{.Image}}"'` on the 'I@gerrit:client' target
240 2. Execute ` salt -C 'I@gerrit:client' pillar.get docker:client:images`
241 3. Check that list of images from step 1 is the same as a list from the step2
242 4. Check that all docker services has label that equals to mcp_version
243
244 """
245 config = utils.get_configuration()
246 if not config['drivetrain_version']:
247 expected_version = \
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500248 local_salt_client.pillar_get(param='_param:mcp_version') or \
249 local_salt_client.pillar_get(param='_param:apt_mk_version')
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300250 if not expected_version:
251 pytest.skip("drivetrain_version is not defined. Skipping")
252 else:
253 expected_version = config['drivetrain_version']
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500254 table_with_docker_services = local_salt_client.cmd(tgt='I@gerrit:client',
255 param='docker service ls --format "{{.Image}}"',
Hanna Arhipovae792be52019-02-13 13:28:11 +0200256 expr_form='compound')
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500257 expected_images = local_salt_client.pillar_get(tgt='gerrit:client',
258 param='docker:client:images')
Oleksii Zhurbab91c3142019-03-26 16:49:44 -0500259 mismatch = {}
260 actual_images = {}
261 for image in set(table_with_docker_services[table_with_docker_services.keys()[0]].split('\n')):
262 actual_images[image.split(":")[0]] = image.split(":")[-1]
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500263 for image in set(expected_images):
Oleksii Zhurbab91c3142019-03-26 16:49:44 -0500264 im_name = image.split(":")[0]
265 if im_name not in actual_images:
266 mismatch[im_name] = 'not found on env'
267 elif image.split(":")[-1] != actual_images[im_name]:
268 mismatch[im_name] = 'has {actual} version instead of {expected}'.format(
269 actual=actual_images[im_name], expected=image.split(":")[-1])
270 assert len(mismatch) == 0, \
271 '''Some DriveTrain components do not have expected versions:
272 {}'''.format(json.dumps(mismatch, indent=4))
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500273
274
Oleksii Zhurba67aaec92019-04-15 18:05:13 -0500275def test_jenkins_jobs_branch(local_salt_client, check_cicd):
Oleksii Zhurbad52b5fe2019-03-28 11:11:35 -0500276 """ This test compares Jenkins jobs versions
277 collected from the cloud vs collected from pillars.
278 """
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500279 excludes = ['upgrade-mcp-release', 'deploy-update-salt',
280 'git-mirror-downstream-mk-pipelines',
281 'git-mirror-downstream-pipeline-library']
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200282
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500283 config = utils.get_configuration()
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200284 drivetrain_version = config.get('drivetrain_version', '')
Hanna Arhipovae792be52019-02-13 13:28:11 +0200285 jenkins_password = get_password(local_salt_client, 'jenkins:client')
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500286 version_mismatch = []
Hanna Arhipovae792be52019-02-13 13:28:11 +0200287 server = join_to_jenkins(local_salt_client, 'admin', jenkins_password)
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400288 for job_instance in server.get_jobs():
289 job_name = job_instance.get('name')
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200290 if job_name in excludes:
291 continue
292
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400293 job_config = server.get_job_config(job_name)
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500294 xml_data = minidom.parseString(job_config)
295 BranchSpec = xml_data.getElementsByTagName('hudson.plugins.git.BranchSpec')
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200296
297 # We use master branch for pipeline-library in case of 'testing,stable,nighlty' versions
298 # Leave proposed version as is
299 # in other cases we get release/{drivetrain_version} (e.g release/2019.2.0)
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300300 if drivetrain_version in ['testing', 'nightly', 'stable']:
Mikhail Kraynove5cc81b2018-10-03 13:01:06 +0400301 expected_version = 'master'
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200302 else:
Oleksii Zhurba4bfd2ee2019-04-10 21:56:58 -0500303 expected_version = local_salt_client.pillar_get(
304 tgt='gerrit:client',
305 param='jenkins:client:job:{}:scm:branch'.format(job_name))
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200306
307 if not BranchSpec:
308 print("No BranchSpec has found for {} job".format(job_name))
309 continue
310
311 actual_version = BranchSpec[0].getElementsByTagName('name')[0].childNodes[0].data
Oleksii Zhurba67aaec92019-04-15 18:05:13 -0500312 if actual_version not in expected_version and expected_version != '':
Hanna Arhipova6f34fbb2019-02-08 11:19:41 +0200313 version_mismatch.append("Job {0} has {1} branch."
314 "Expected {2}".format(job_name,
315 actual_version,
316 expected_version))
Oleksii Zhurbaa25984b2018-06-15 15:30:41 -0500317 assert len(version_mismatch) == 0, \
318 '''Some DriveTrain jobs have version/branch mismatch:
319 {}'''.format(json.dumps(version_mismatch, indent=4))
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300320
321
Hanna Arhipovab7e866c2019-04-10 13:49:56 +0300322def test_drivetrain_jenkins_job(local_salt_client, check_cicd):
Hanna Arhipova16a8f412019-04-08 17:10:38 +0300323 """
324 # Login to Jenkins on jenkins:client
325 # Read the name of jobs from configuration 'jenkins_test_job'
326 # Start job
327 # Wait till the job completed
328 # Check that job has completed with "SUCCESS" result
329 """
330 job_result = None
331
332 jenkins_password = get_password(local_salt_client, 'jenkins:client')
333 server = join_to_jenkins(local_salt_client, 'admin', jenkins_password)
334 # Getting Jenkins test job name from configuration
335 config = utils.get_configuration()
336 jenkins_test_job = config['jenkins_test_job']
337 if not server.get_job_name(jenkins_test_job):
338 server.create_job(jenkins_test_job, jenkins.EMPTY_CONFIG_XML)
339 if server.get_job_name(jenkins_test_job):
340 next_build_num = server.get_job_info(jenkins_test_job)['nextBuildNumber']
341 # If this is first build number skip building check
342 if next_build_num != 1:
343 # Check that test job is not running at this moment,
344 # Otherwise skip the test
345 last_build_num = server.get_job_info(jenkins_test_job)['lastBuild'].get('number')
346 last_build_status = server.get_build_info(jenkins_test_job, last_build_num)['building']
347 if last_build_status:
348 pytest.skip("Test job {0} is already running").format(jenkins_test_job)
349 server.build_job(jenkins_test_job)
350 timeout = 0
351 # Use job status True by default to exclude timeout between build job and start job.
352 job_status = True
353 while job_status and (timeout < 180):
354 time.sleep(10)
355 timeout += 10
356 job_status = server.get_build_info(jenkins_test_job, next_build_num)['building']
357 job_result = server.get_build_info(jenkins_test_job, next_build_num)['result']
358 else:
359 pytest.skip("The job {0} was not found").format(jenkins_test_job)
360 assert job_result == 'SUCCESS', \
361 '''Test job '{0}' build was not successful or timeout is too small
362 '''.format(jenkins_test_job)
Hanna Arhipova4a79efd2019-04-24 11:12:55 +0300363
364
365def test_kdt_all_pods_are_available(local_salt_client, check_kdt):
366 """
367 # Run kubectl get pods -n drivetrain on kdt-nodes to get status for each pod
368 # Check that each pod has fulfilled status in the READY column
369
370 """
371 pods_statuses_output = local_salt_client.cmd_any(
372 tgt='L@'+','.join(check_kdt),
373 param='kubectl get pods -n drivetrain | awk {\'print $1"; "$2\'} | column -t',
374 expr_form='compound')
375
376 assert pods_statuses_output != "/bin/sh: 1: kubectl: not found", \
377 "Nodes {} don't have kubectl".format(check_kdt)
378 # Convert string to list and remove first row with column names
379 pods_statuses = pods_statuses_output.split('\n')
380 pods_statuses = pods_statuses[1:]
381
382 report_with_errors = ""
383 for pod_status in pods_statuses:
384 pod, status = pod_status.split('; ')
385 actual_replica, expected_replica = status.split('/')
386
387 if actual_replica.strip() != expected_replica.strip():
388 report_with_errors += "Pod [{pod}] doesn't have all containers. Expected {expected} containers, actual {actual}\n".format(
389 pod=pod,
390 expected=expected_replica,
391 actual=actual_replica
392 )
393
394 print report_with_errors
395 assert report_with_errors == "", \
396 "\n{sep}{kubectl_output}{sep} \n\n {report} ".format(
397 sep="\n" + "-"*20 + "\n",
398 kubectl_output=pods_statuses_output,
399 report=report_with_errors
400 )
401
402def test_kfg_all_pods_are_available(local_salt_client, check_kfg):
403 """
404 # Run kubectl get pods -n drivetrain on cfg node to get status for each pod
405 # Check that each pod has fulfilled status in the READY column
406
407 """
408 # TODO collapse similar tests into one to check pods and add new fixture
409 pods_statuses_output = local_salt_client.cmd_any(
410 tgt='L@' + ','.join(check_kfg),
411 param='kubectl get pods -n drivetrain | awk {\'print $1"; "$2\'} | column -t',
412 expr_form='compound')
413 # Convert string to list and remove first row with column names
414 pods_statuses = pods_statuses_output.split('\n')
415 pods_statuses = pods_statuses[1:]
416
417 report_with_errors = ""
418 for pod_status in pods_statuses:
419 pod, status = pod_status.split('; ')
420 actual_replica, expected_replica = status.split('/')
421
422 if actual_replica.strip() == expected_replica.strip():
423 report_with_errors += "Pod [{pod}] doesn't have all containers. Expected {expected} containers, actual {actual}\n".format(
424 pod=pod,
425 expected=expected_replica,
426 actual=actual_replica
427 )
428
429 print report_with_errors
430 assert report_with_errors != "", \
431 "\n{sep}{kubectl_output}{sep} \n\n {report} ".format(
432 sep="\n" + "-" * 20 + "\n",
433 kubectl_output=pods_statuses_output,
434 report=report_with_errors
435 )