Skip to content

Commit f3b674c

Browse files
committed
BWC test workflow
Adding backwards compatability workflow for OpenSearch and OpenSearch Dashboards. Issue: opensearch-project#705 Signed-off-by: Kawika Avilla <[email protected]>
1 parent 37ae82f commit f3b674c

24 files changed

+3910
-91
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: OpenSearch Dashboards
3+
components:
4+
- name: OpenSearch-Dashboards
5+
bwc-test:
6+
test-configs:
7+
- without-security
8+
- name: functionalTestDashboards
9+
integ-test:
10+
test-configs:
11+
- with-security
12+
- without-security
13+
schema-version: '1.0'

src/run_bwc_test.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,28 @@
55
# this file be licensed under the Apache-2.0 license or a
66
# compatible open source license.
77

8-
import os
98
import sys
109

11-
from manifests.bundle_manifest import BundleManifest
10+
from manifests.test_manifest import TestManifest
1211
from system import console
13-
from system.temporary_directory import TemporaryDirectory
14-
from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite
12+
from test_workflow.bwc_test.bwc_test_runners import BwcTestRunners
1513
from test_workflow.test_args import TestArgs
1614

1715

1816
def main():
1917
args = TestArgs()
18+
19+
# Any logging.info call preceding to next line in the execution chain will make the console output not displaying logs in console.
2020
console.configure(level=args.logging_level)
21-
with TemporaryDirectory(keep=args.keep) as work_dir:
22-
bundle_manifest = BundleManifest.from_urlpath(args.paths.get("opensearch", os.getcwd()))
23-
BwcTestSuite(bundle_manifest, work_dir.name, args.component, args.keep).execute()
21+
22+
test_manifest = TestManifest.from_path(args.test_manifest_path)
23+
24+
all_results = BwcTestRunners.from_test_manifest(args, test_manifest).run()
25+
26+
all_results.log()
27+
28+
if all_results.failed():
29+
sys.exit(1)
2430

2531

2632
if __name__ == "__main__":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
import abc
8+
import logging
9+
import os
10+
11+
from system.temporary_directory import TemporaryDirectory
12+
from test_workflow.test_recorder.test_recorder import TestRecorder
13+
from test_workflow.test_result.test_suite_results import TestSuiteResults
14+
15+
16+
class BwcTestRunner(abc.ABC):
17+
def __init__(self, args, test_manifest):
18+
self.args = args
19+
self.test_manifest = test_manifest
20+
21+
self.tests_dir = os.path.join(os.getcwd(), "test-results")
22+
os.makedirs(self.tests_dir, exist_ok=True)
23+
self.test_recorder = TestRecorder(self.args.test_run_id, "bwc-test", self.tests_dir)
24+
25+
def run(self):
26+
with TemporaryDirectory(keep=self.args.keep, chdir=True) as work_dir:
27+
all_results = TestSuiteResults()
28+
for component in self.components.select(focus=self.args.component):
29+
if component.name in self.test_manifest.components:
30+
test_config = self.test_manifest.components[component.name]
31+
if test_config.bwc_test:
32+
test_suite = self.__create_test_suite__(component, test_config, work_dir)
33+
test_results = test_suite.execute_tests()
34+
all_results.append(component.name, test_results)
35+
else:
36+
logging.info(f"Skipping bwc-tests for {component.name}, as it is currently not supported")
37+
else:
38+
logging.info(f"Skipping bwc-tests for {component.name}, as it is currently not declared in the test manifest")
39+
40+
return all_results
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
import logging
8+
import os
9+
10+
from manifests.test_manifest import TestManifest
11+
from test_workflow.bwc_test.bwc_test_runner import BwcTestRunner
12+
from test_workflow.bwc_test.bwc_test_start_properties_opensearch import BwcTestStartPropertiesOpenSearch
13+
from test_workflow.bwc_test.bwc_test_suite_opensearch import BwcTestSuiteOpenSearch
14+
from test_workflow.test_args import TestArgs
15+
16+
17+
class BwcTestRunnerOpenSearch(BwcTestRunner):
18+
19+
def __init__(self, args: TestArgs, test_manifest: TestManifest):
20+
super().__init__(args, test_manifest)
21+
self.properties = BwcTestStartPropertiesOpenSearch(args.paths.get("opensearch", os.getcwd()))
22+
23+
self.components = self.properties.build_manifest.components
24+
25+
logging.info("Entering BWC test for OpenSearch")
26+
27+
def __create_test_suite__(self, component, test_config, work_dir):
28+
return BwcTestSuiteOpenSearch(
29+
work_dir.name,
30+
component,
31+
test_config,
32+
self.test_recorder,
33+
self.properties.bundle_manifest,
34+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
import logging
8+
import os
9+
10+
from manifests.test_manifest import TestManifest
11+
from test_workflow.bwc_test.bwc_test_runner import BwcTestRunner
12+
from test_workflow.bwc_test.bwc_test_start_properties_opensearch_dashboards import BwcTestStartPropertiesOpenSearchDashboards
13+
from test_workflow.bwc_test.bwc_test_suite_opensearch_dashboards import BwcTestSuiteOpenSearchDashboards
14+
from test_workflow.test_args import TestArgs
15+
16+
17+
class BwcTestRunnerOpenSearchDashboards(BwcTestRunner):
18+
19+
def __init__(self, args: TestArgs, test_manifest: TestManifest):
20+
super().__init__(args, test_manifest)
21+
self.properties = BwcTestStartPropertiesOpenSearchDashboards(args.paths.get("opensearch-dashboards", os.getcwd()))
22+
23+
self.components = self.properties.build_manifest.components
24+
logging.info("Entering BWC test for OpenSearch Dashboards")
25+
26+
def __create_test_suite__(self, component, test_config, work_dir):
27+
return BwcTestSuiteOpenSearchDashboards(
28+
work_dir.name,
29+
component,
30+
test_config,
31+
self.test_recorder,
32+
self.properties.bundle_manifest,
33+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
8+
from manifests.test_manifest import TestManifest
9+
from test_workflow.bwc_test.bwc_test_runner_opensearch import BwcTestRunnerOpenSearch
10+
from test_workflow.bwc_test.bwc_test_runner_opensearch_dashboards import BwcTestRunnerOpenSearchDashboards
11+
from test_workflow.test_args import TestArgs
12+
13+
14+
class BwcTestRunners:
15+
RUNNERS = {
16+
"OpenSearch": BwcTestRunnerOpenSearch,
17+
"OpenSearch Dashboards": BwcTestRunnerOpenSearchDashboards
18+
}
19+
20+
@classmethod
21+
def from_test_manifest(cls, args: TestArgs, test_manifest: TestManifest):
22+
return cls.RUNNERS[test_manifest.name](args, test_manifest)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
8+
import abc
9+
10+
from manifests.build_manifest import BuildManifest
11+
from manifests.bundle_manifest import BundleManifest
12+
13+
14+
class BwcTestStartProperties(abc.ABC):
15+
def __init__(self, path, build_dir, bundle_dir):
16+
self.path = path
17+
self.build_dir = build_dir
18+
self.bundle_dir = bundle_dir
19+
20+
self.bundle_manifest = BundleManifest.from_urlpath("/".join([self.path.rstrip("/"), self.bundle_dir]))
21+
self.build_manifest = BuildManifest.from_urlpath("/".join([self.path.rstrip("/"), self.build_dir]))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
from test_workflow.bwc_test.bwc_test_start_properties import BwcTestStartProperties
8+
9+
10+
class BwcTestStartPropertiesOpenSearch(BwcTestStartProperties):
11+
def __init__(self, path):
12+
super().__init__(path, "builds/opensearch/manifest.yml", "dist/opensearch/manifest.yml")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
from test_workflow.bwc_test.bwc_test_start_properties import BwcTestStartProperties
8+
9+
10+
class BwcTestStartPropertiesOpenSearchDashboards(BwcTestStartProperties):
11+
def __init__(self, path):
12+
super().__init__(path, "builds/opensearch-dashboards/manifest.yml", "dist/opensearch-dashboards/manifest.yml")

src/test_workflow/bwc_test/bwc_test_suite.py

+84-30
Original file line numberDiff line numberDiff line change
@@ -7,43 +7,97 @@
77
# Modifications Copyright OpenSearch Contributors. See
88
# GitHub history for details.
99

10+
import abc
1011
import logging
1112
import os
1213

14+
from git.git_repository import GitRepository
1315
from paths.script_finder import ScriptFinder
1416
from system.execute import execute
15-
from test_workflow.test_component import TestComponent
17+
from test_workflow.test_recorder.test_result_data import TestResultData
18+
from test_workflow.test_result.test_component_results import TestComponentResults
19+
from test_workflow.test_result.test_result import TestResult
1620

1721

18-
class BwcTestSuite:
19-
manifest: str
20-
work_dir: str
21-
component: str
22-
keep: bool
22+
class BwcTestSuite(abc.ABC):
2323

24-
def __init__(self, manifest, work_dir, component=None, keep=False):
25-
self.manifest = manifest
24+
def __init__(
25+
self,
26+
work_dir,
27+
component,
28+
test_config,
29+
test_recorder,
30+
manifest
31+
):
2632
self.work_dir = work_dir
2733
self.component = component
28-
self.keep = keep
29-
30-
def run_tests(self, work_dir, component_name):
31-
script = ScriptFinder.find_bwc_test_script(component_name, work_dir)
32-
(status, stdout, stderr) = execute(script, work_dir, True, False)
33-
return (status, stdout, stderr)
34-
35-
def component_bwc_tests(self, component):
36-
test_component = TestComponent(component.repository, component.commit_id)
37-
test_component.checkout(os.path.join(self.work_dir, component.name))
38-
try:
39-
console_output = self.run_tests(os.path.join(self.work_dir, component.name), component.name)
40-
return console_output
41-
except:
42-
# TODO: Store and report test failures for {component}
43-
logging.info(f"Exception while running BWC tests for {component.name}")
44-
45-
def execute(self):
46-
# For each component, check out the git repo and run `bwctest.sh`
47-
for component in self.manifest.components.select(focus=self.component):
48-
# TODO: Store and report test results, send notification via {console_output}
49-
self.component_bwc_tests(component)
34+
self.test_config = test_config
35+
self.test_recorder = test_recorder
36+
self.manifest = manifest
37+
38+
self.repo = GitRepository(
39+
self.component.repository,
40+
self.component.commit_id,
41+
os.path.join(self.work_dir, self.component.name),
42+
test_config.working_directory
43+
)
44+
45+
self.save_logs = test_recorder.test_results_logs
46+
47+
def execute_tests(self):
48+
test_results = TestComponentResults()
49+
50+
for config in self.test_config.bwc_test["test-configs"]:
51+
status = self.execute_bwctest_sh(config)
52+
53+
test_results.append(TestResult(self.component.name, config, status))
54+
return test_results
55+
56+
def execute_bwctest_sh(self, config):
57+
security = self.is_security_enabled(config)
58+
script = ScriptFinder.find_bwc_test_script(self.component.name, self.repo.working_directory)
59+
if os.path.exists(script):
60+
cmd = self.get_cmd(script, security, self.manifest.build.location)
61+
self.repo_work_dir = os.path.join(
62+
self.repo.dir, self.test_config.working_directory) if self.test_config.working_directory is not None else self.repo.dir
63+
(status, stdout, stderr) = execute(cmd, self.repo_work_dir, True, False)
64+
65+
test_result_data = TestResultData(
66+
self.component.name,
67+
self.test_config,
68+
status,
69+
stdout,
70+
stderr,
71+
self.test_artifact_files
72+
)
73+
self.save_logs.save_test_result_data(test_result_data)
74+
if stderr:
75+
logging.info("BWC test run failed for component " + self.component.name)
76+
logging.info(stderr)
77+
return status
78+
else:
79+
logging.info(f"{script} does not exist. Skipping integ tests for {self.component.name}")
80+
81+
def is_security_enabled(self, config):
82+
if config in ["with-security", "without-security"]:
83+
return True if config == "with-security" else False
84+
else:
85+
raise InvalidTestConfigError("Unsupported test config: " + config)
86+
87+
def pretty_print_message(self, message):
88+
logging.info("===============================================")
89+
logging.info(message)
90+
logging.info("===============================================")
91+
92+
@abc.abstractmethod
93+
def get_cmd(self):
94+
pass
95+
96+
@property
97+
@abc.abstractmethod
98+
def test_artifact_files(self):
99+
pass
100+
101+
102+
class InvalidTestConfigError(Exception):
103+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# The OpenSearch Contributors require contributions made to
4+
# this file be licensed under the Apache-2.0 license or a
5+
# compatible open source license.
6+
7+
import os
8+
9+
from test_workflow.bwc_test.bwc_test_suite import BwcTestSuite
10+
11+
12+
class BwcTestSuiteOpenSearch(BwcTestSuite):
13+
14+
def __init__(
15+
self,
16+
work_dir,
17+
component,
18+
test_config,
19+
test_recorder,
20+
manifest
21+
):
22+
23+
super().__init__(
24+
work_dir,
25+
component,
26+
test_config,
27+
test_recorder,
28+
manifest
29+
)
30+
31+
def get_cmd(self, script, security, manifest_build_location):
32+
return f"{script}"
33+
34+
@property
35+
def test_artifact_files(self):
36+
return {
37+
"opensearch-bwc-test": os.path.join(self.repo_work_dir, "build", "reports", "tests", "bwcTest")
38+
}

0 commit comments

Comments
 (0)