Skip to content

Commit 1baa82c

Browse files
committed
revamped
Signed-off-by: Matthias Büchse <[email protected]>
1 parent 2bac015 commit 1baa82c

File tree

2 files changed

+41
-100
lines changed

2 files changed

+41
-100
lines changed

Tests/kaas/sonobuoy_handler/run_sonobuoy.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
@click.option("-c", "--check", "check_name", type=str, default="sonobuoy_executor", help="this MUST be the same name as the id in 'scs-compatible-kaas.yaml'",)
1818
@click.option("-a", "--arg", "args", multiple=True)
1919
def sonobuoy_run(kubeconfig, result_dir_name, check_name, args):
20-
logger.info("Run sonobuoy_executor")
2120
sonobuoy_handler = SonobuoyHandler(check_name, kubeconfig, result_dir_name, args)
22-
return_code = sonobuoy_handler.run()
23-
sys.exit(return_code)
21+
sys.exit(sonobuoy_handler.run())
2422

2523

2624
if __name__ == "__main__":

Tests/kaas/sonobuoy_handler/sonobuoy_handler.py

Lines changed: 40 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1+
from collections import Counter
12
import json
23
import logging
34
import os
5+
import shlex
6+
import shutil
47
import subprocess
58

6-
from kubernetes import client, config
79
from junitparser import JUnitXml
810

911
logger = logging.getLogger(__name__)
1012

1113

12-
def setup_k8s_client(kubeconfigfile=None):
13-
if not kubeconfigfile:
14-
logger.error("no kubeconfig file provided")
15-
return # XXX smelly: why not raise an exception here?
16-
logger.debug(f"loading kubeconfig file '{kubeconfigfile}'")
17-
config.load_kube_config(kubeconfigfile)
18-
logger.info("kubeconfigfile loaded successfully")
19-
return client.CoreV1Api()
20-
21-
2214
class SonobuoyHandler:
2315
"""
2416
A class that handles both the execution of sonobuoy and
@@ -33,101 +25,59 @@ def __init__(
3325
check_name="sonobuoy_handler",
3426
kubeconfig=None,
3527
result_dir_name="sonobuoy_results",
36-
args=None,
28+
args=(),
3729
):
3830
self.check_name = check_name
39-
logger.info(f"Inital {__name__} for {self.check_name}")
4031
logger.debug(f"kubeconfig: {kubeconfig} ")
4132
if kubeconfig is None:
4233
raise Exception("No kubeconfig provided")
4334
else:
4435
self.kubeconfig_path = kubeconfig
4536
self.working_directory = os.getcwd()
4637
self.result_dir_name = result_dir_name
47-
logger.debug(
48-
f"Working from {self.working_directory} placing results at {self.result_dir_name}"
49-
)
50-
self.args = args
38+
self.sonobuoy = shutil.which('sonobuoy')
39+
logger.debug(f"working from {self.working_directory}")
40+
logger.debug(f"placing results at {self.result_dir_name}")
41+
logger.debug(f"sonobuoy executable at {self.sonobuoy}")
42+
self.args = (arg0 for arg in args for arg0 in shlex.split(str(arg)))
5143

52-
def _build_command(self, process, *args):
53-
return " ".join(
54-
("sonobuoy", "--kubeconfig", self.kubeconfig_path, process) + args
55-
)
44+
def _invoke_sonobuoy(self, *args, **kwargs):
45+
inv_args = (self.sonobuoy, "--kubeconfig", self.kubeconfig_path) + args
46+
logger.debug(f'invoking {" ".join(inv_args)}')
47+
return subprocess.run(args=inv_args, capture_output=True, check=True, **kwargs)
5648

5749
def _sonobuoy_run(self):
58-
logger.debug("sonobuoy run")
59-
check_args = ["--wait"]
60-
check_args += [str(arg) for arg in self.args]
61-
subprocess.run(
62-
self._build_command("run", *check_args),
63-
shell=True,
64-
capture_output=True,
65-
check=True,
66-
)
50+
self._invoke_sonobuoy("run", "--wait", *self.args)
6751

6852
def _sonobuoy_delete(self):
69-
logger.info("removing sonobuoy resources from cluster")
70-
subprocess.run(
71-
self._build_command("delete", "--wait"),
72-
shell=True,
73-
capture_output=True,
74-
check=True,
75-
)
53+
self._invoke_sonobuoy("delete", "--wait")
7654

7755
def _sonobuoy_status_result(self):
78-
logger.debug("sonobuoy status")
79-
process = subprocess.run(
80-
self._build_command("status", "--json"),
81-
shell=True,
82-
capture_output=True,
83-
check=True,
84-
)
56+
process = self._invoke_sonobuoy("status", "--json")
8557
json_data = json.loads(process.stdout)
58+
counter = Counter()
8659
for entry in json_data["plugins"]:
87-
print(f"plugin:{entry['plugin']}:{entry['result-status']}")
88-
failed_test_cases = 0
89-
passed_test_cases = 0
90-
skipped_test_cases = 0
91-
for result, count in json_data["plugins"][0]["result-counts"].items():
92-
if result == "passed":
93-
passed_test_cases = count
94-
if result == "failed":
95-
failed_test_cases = count
96-
logger.error(f"ERROR: failed: {count}")
97-
if result == "skipped":
98-
skipped_test_cases = count
99-
logger.error(f"ERROR: skipped: {count}")
100-
result_message = f" {passed_test_cases} passed, {failed_test_cases} failed, {skipped_test_cases} skipped"
101-
if failed_test_cases == 0 and skipped_test_cases == 0:
60+
logger.debug(f"plugin:{entry['plugin']}:{entry['result-status']}")
61+
for result, count in entry["result-counts"].items():
62+
counter[result] += count
63+
return counter
64+
65+
def _eval_result(self, counter):
66+
result_str = ', '.join(f"{counter[key]} {key}" for key in ('passed', 'failed', 'skipped'))
67+
result_message = f"sonobuoy reports {result_str}"
68+
if counter['failed']:
69+
logger.error(result_message)
70+
self.return_code = 3
71+
else:
10272
logger.info(result_message)
10373
self.return_code = 0
104-
else:
105-
logger.error("ERROR:" + result_message)
106-
self.return_code = 3
10774

10875
def _preflight_check(self):
10976
"""
11077
Preflight test to ensure that everything is set up correctly for execution
11178
"""
112-
logger.info("check kubeconfig")
113-
self.k8s_api_client = setup_k8s_client(self.kubeconfig_path)
114-
115-
for api in client.ApisApi().get_api_versions().groups:
116-
versions = []
117-
for v in api.versions:
118-
name = ""
119-
if v.version == api.preferred_version.version and len(api.versions) > 1:
120-
name += "*"
121-
name += v.version
122-
versions.append(name)
123-
logger.info(f"[supported api]: {api.name:<40} {','.join(versions)}")
124-
125-
logger.debug("checks if sonobuoy is available")
126-
return_value = os.system(
127-
f"sonobuoy version --kubeconfig='{self.kubeconfig_path}'"
128-
)
129-
if return_value != 0:
130-
raise Exception("sonobuoy is not installed")
79+
if not self.sonobuoy:
80+
raise RuntimeError("sonobuoy executable not found; is it in PATH?")
13181

13282
def _sonobuoy_retrieve_result(self):
13383
"""
@@ -141,6 +91,7 @@ def _sonobuoy_retrieve_result(self):
14191
raise Exception("result directory already existing")
14292
os.mkdir(result_dir)
14393

94+
# XXX use self._invoke_sonobuoy
14495
os.system(
14596
# ~ f"sonobuoy retrieve {result_dir} -x --filename='{result_dir}' --kubeconfig='{self.kubeconfig_path}'"
14697
f"sonobuoy retrieve {result_dir} --kubeconfig='{self.kubeconfig_path}'"
@@ -149,35 +100,27 @@ def _sonobuoy_retrieve_result(self):
149100
f"parsing JUnit result from {result_dir + '/plugins/e2e/results/global/junit_01.xml'} "
150101
)
151102
xml = JUnitXml.fromfile(result_dir + "/plugins/e2e/results/global/junit_01.xml")
152-
failed_test_cases = 0
153-
passed_test_cases = 0
154-
skipped_test_cases = 0
103+
counter = Counter()
155104
for suite in xml:
156105
for case in suite:
157-
if case.is_passed is True:
158-
passed_test_cases += 1
106+
if case.is_passed is True: # XXX why `is True`???
107+
counter['passed'] += 1
159108
elif case.is_skipped is True:
160-
skipped_test_cases += 1
109+
counter['skipped'] += 1
161110
else:
162-
failed_test_cases += 1
111+
counter['failed'] += 1
163112
logger.error(f"{case.name}")
164-
165-
result_message = f" {passed_test_cases} passed, {failed_test_cases} failed, {skipped_test_cases} skipped"
166-
if failed_test_cases: # TODO: add `or skipped_test_cases`?
167-
logger.error(result_message)
168-
self.return_code = 3
169-
else:
170-
logger.info(result_message)
171-
self.return_code = 0
113+
return counter
172114

173115
def run(self):
174116
"""
175117
This method is to be called to run the plugin
176118
"""
119+
logger.info(f"running sonobuoy for testcase {self.check_name}")
177120
self.return_code = 11
178121
self._preflight_check()
179122
self._sonobuoy_run()
180-
self._sonobuoy_status_result()
123+
self._eval_result(self._sonobuoy_status_result())
181124

182125
# ERROR: currently disabled do to: "error retrieving results: unexpected EOF"
183126
# might be related to following bug: https://github.com/vmware-tanzu/sonobuoy/issues/1633

0 commit comments

Comments
 (0)