Skip to content

Commit f1f52ad

Browse files
authored
Support new distribution-validations and add few enhancements to validation workflow (#4447)
Signed-off-by: Divya Madala <divyaasm@amazon.com>
1 parent 04c7e7f commit f1f52ad

21 files changed

+850
-239
lines changed
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright OpenSearch Contributors
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# The OpenSearch Contributors require contributions made to
5+
# this file be licensed under the Apache-2.0 license or a
6+
# compatible open source license.
7+
#
8+
# This page intentionally left blank.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright OpenSearch Contributors
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# The OpenSearch Contributors require contributions made to
5+
# this file be licensed under the Apache-2.0 license or a
6+
# compatible open source license.
7+
8+
import logging
9+
import os
10+
11+
from system.execute import execute
12+
from test_workflow.integ_test.utils import get_password
13+
from validation_workflow.api_test_cases import ApiTestCases
14+
from validation_workflow.download_utils import DownloadUtils
15+
from validation_workflow.validation import Validation
16+
from validation_workflow.validation_args import ValidationArgs
17+
18+
19+
class ValidateDeb(Validation, DownloadUtils):
20+
def __init__(self, args: ValidationArgs) -> None:
21+
super().__init__(args)
22+
23+
def installation(self) -> bool:
24+
try:
25+
for project in self.args.projects:
26+
set_password = f' env OPENSEARCH_INITIAL_ADMIN_PASSWORD={get_password(str(self.args.version))}' if project == "opensearch" else ""
27+
execute(f'sudo dpkg --purge {project}', ".")
28+
execute(f'sudo {set_password} dpkg -i {os.path.basename(self.args.file_path.get(project))}', str(self.tmp_dir.path))
29+
except:
30+
raise Exception("Failed to install OpenSearch/OpenSearch-Dashboards")
31+
return True
32+
33+
def start_cluster(self) -> bool:
34+
try:
35+
for project in self.args.projects:
36+
execute(f'sudo systemctl enable {project}', ".")
37+
execute(f'sudo systemctl start {project}', ".")
38+
execute(f'sudo systemctl status {project}', ".")
39+
except:
40+
raise Exception('Failed to Start Cluster')
41+
return True
42+
43+
def validation(self) -> bool:
44+
if self.check_cluster_readiness():
45+
test_result, counter = ApiTestCases().test_apis(self.args.version, self.args.projects,
46+
self.check_for_security_plugin(os.path.join(os.sep, "usr", "share", "opensearch")) if self.args.allow_http else True)
47+
if (test_result):
48+
logging.info(f'All tests Pass : {counter}')
49+
return True
50+
else:
51+
raise Exception(f'Not all tests Pass : {counter}')
52+
else:
53+
raise Exception("Cluster is not ready for API test")
54+
55+
def cleanup(self) -> bool:
56+
try:
57+
for project in self.args.projects:
58+
execute(f'sudo dpkg --purge {project}', ".")
59+
except Exception as e:
60+
raise Exception(f'Exception occurred either while attempting to stop cluster or removing OpenSearch/OpenSearch-Dashboards. {str(e)}')
61+
return True

src/validation_workflow/docker/inspect_docker_image.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __init__(self, image_id: str, image_name: str, prod_image_tag: str) -> None:
2727
self.image_id = image_id
2828
self.image_name = image_name
2929
self.prod_image_tag = prod_image_tag
30-
self.image_tag = ValidationArgs().stg_tag('opensearch_dashboards').replace(" ", "") if ("dashboards" in self.image_name) else ValidationArgs().stg_tag('opensearch').replace(" ", "")
30+
self.image_tag = ValidationArgs().stg_tag('opensearch-dashboards').replace(" ", "") if ("dashboards" in self.image_name) else ValidationArgs().stg_tag('opensearch').replace(" ", "")
3131
self.auth_token_url = "https://auth.docker.io/token?"
3232
self.auth_service_scope = "service=registry.docker.io&scope=repository:"
3333
self.registry_url = "https://index.docker.io/v2/"

src/validation_workflow/docker/validation_docker.py

+8-43
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,10 @@
99
import os
1010
import shutil
1111
import subprocess
12-
import time
1312
from subprocess import PIPE
1413
from typing import Any
1514

16-
import requests
17-
18-
from system.temporary_directory import TemporaryDirectory
19-
from validation_workflow.api_request import ApiTest
15+
from test_workflow.integ_test.utils import get_password
2016
from validation_workflow.api_test_cases import ApiTestCases
2117
from validation_workflow.docker.inspect_docker_image import InspectDockerImage
2218
from validation_workflow.validation import Validation
@@ -61,8 +57,7 @@ def start_cluster(self) -> bool:
6157
def validation(self) -> bool:
6258
# STEP 2 . inspect image digest between opensearchproject(downloaded/local) and opensearchstaging(dockerHub)
6359
if not self.args.using_staging_artifact_only:
64-
self.image_names_list = [self.args.OS_image, self.args.OSD_image]
65-
self.image_names_list = [x for x in self.image_names_list if (os.path.basename(x) in self.args.projects)]
60+
self.image_names_list = ['opensearchproject/' + project for project in self.args.projects]
6661
self.image_digests = list(map(lambda x: self.inspect_docker_image(x[0], x[1]), zip(self.image_ids.values(), self.image_names_list))) # type: ignore
6762
if all(self.image_digests):
6863
logging.info('Image digest is validated.\n\n')
@@ -79,7 +74,7 @@ def validation(self) -> bool:
7974
self.args.version
8075
)
8176
if return_code:
82-
logging.info('Checking if cluster is ready for API test in every 10 seconds\n\n')
77+
logging.info('Checking if cluster is ready for API test in every 5 seconds\n\n')
8378

8479
if self.check_cluster_readiness():
8580
# STEP 4 . OS, OSD API validation
@@ -94,8 +89,8 @@ def validation(self) -> bool:
9489
raise Exception(f'Not all tests Pass : {_counter}')
9590
else:
9691
raise Exception("Cluster is not ready for API test.")
97-
else:
98-
raise Exception('The container failed to start. Exiting the validation.')
92+
else:
93+
raise Exception('The container failed to start. Exiting the validation.')
9994

10095
return True
10196

@@ -129,36 +124,6 @@ def cleanup_process(self) -> bool:
129124

130125
return('returncode=0' in (str(result)))
131126

132-
def check_http_request(self) -> bool:
133-
self.test_readiness_urls = {
134-
'https://localhost:9200/': 'opensearch cluster API',
135-
'http://localhost:5601/api/status': 'opensearch-dashboards API',
136-
}
137-
138-
for url, name in self.test_readiness_urls.items():
139-
try:
140-
status_code, response_text = ApiTest(url, self.args.version).api_get()
141-
if status_code != 200:
142-
logging.error(f'Error connecting to {name} ({url}): status code {status_code}')
143-
return False
144-
except (requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout) as e:
145-
logging.error(f'Error connecting to {name} ({url}): {e}')
146-
return False
147-
return True
148-
149-
def check_cluster_readiness(self) -> bool:
150-
max_retry = 20
151-
retry_count = 0
152-
while retry_count < max_retry:
153-
logging.info(f'sleeping 10sec for retry {retry_count + 1}/{max_retry}')
154-
time.sleep(10)
155-
if self.check_http_request():
156-
logging.info('\n\ncluster is now ready for API test\n\n')
157-
return True
158-
retry_count += 1
159-
logging.error(f"Maximum number of retries ({max_retry}) reached. Cluster is not ready for API test.")
160-
return False
161-
162127
def get_artifact_image_name(self, artifact: str, using_staging_artifact_only: str) -> Any:
163128
self.image_names = {
164129
'dockerhub': {
@@ -241,7 +206,6 @@ def run_container(self, image_ids: dict, version: str) -> Any:
241206
'2': 'docker-compose-2.x.yml'
242207
}
243208

244-
self.tmp_dir = TemporaryDirectory()
245209
self.target_yml_file = os.path.join(self.tmp_dir.name, 'docker-compose.yml')
246210

247211
self.major_version_number = version[0]
@@ -252,8 +216,9 @@ def run_container(self, image_ids: dict, version: str) -> Any:
252216
self.replacements = [(f'opensearchproject/{key}:{self.major_version_number}', value) for key, value in image_ids.items()]
253217

254218
list(map(lambda r: self.inplace_change(self.target_yml_file, r[0], r[1]), self.replacements))
255-
219+
os.environ["OPENSEARCH_INITIAL_ADMIN_PASSWORD"] = get_password(str(version))
256220
# spin up containers
257-
self.docker_compose_up = f'docker-compose -f {self.target_yml_file} up -d'
221+
services = "opensearch-node1 opensearch-node2" if "opensearch-dashboards" not in self.args.projects else ""
222+
self.docker_compose_up = f'docker-compose -f {self.target_yml_file} up -d {services}'
258223
result = subprocess.run(self.docker_compose_up, shell=True, stdout=PIPE, stderr=PIPE, universal_newlines=True)
259224
return ('returncode=0' in (str(result)), self.target_yml_file)

src/validation_workflow/rpm/validation_rpm.py

+9-28
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77

88
import logging
99
import os
10-
import time
1110

1211
from system.execute import execute
13-
from system.temporary_directory import TemporaryDirectory
1412
from test_workflow.integ_test.utils import get_password
1513
from validation_workflow.api_test_cases import ApiTestCases
1614
from validation_workflow.download_utils import DownloadUtils
@@ -22,26 +20,6 @@ class ValidateRpm(Validation, DownloadUtils):
2220

2321
def __init__(self, args: ValidationArgs) -> None:
2422
super().__init__(args)
25-
self.base_url_production = "https://artifacts.opensearch.org/releases/bundle/"
26-
self.base_url_staging = "https://ci.opensearch.org/ci/dbc/distribution-build-"
27-
self.tmp_dir = TemporaryDirectory()
28-
29-
def download_artifacts(self) -> bool:
30-
isFilePathEmpty = bool(self.args.file_path)
31-
for project in self.args.projects:
32-
if (isFilePathEmpty):
33-
if ("https:" not in self.args.file_path.get(project)):
34-
self.copy_artifact(self.args.file_path.get(project), str(self.tmp_dir.path))
35-
else:
36-
self.args.version = self.get_version(self.args.file_path.get(project))
37-
self.check_url(self.args.file_path.get(project))
38-
else:
39-
if (self.args.artifact_type == "staging"):
40-
self.args.file_path[project] = f"{self.base_url_staging}{project}/{self.args.version}/{self.args.build_number[project]}/linux/{self.args.arch}/{self.args.distribution}/dist/{project}/{project}-{self.args.version}-linux-{self.args.arch}.rpm" # noqa: E501
41-
else:
42-
self.args.file_path[project] = f"{self.base_url_production}{project}/{self.args.version}/{project}-{self.args.version}-linux-{self.args.arch}.rpm"
43-
self.check_url(self.args.file_path.get(project))
44-
return True
4523

4624
def installation(self) -> bool:
4725
try:
@@ -58,7 +36,6 @@ def start_cluster(self) -> bool:
5836
try:
5937
for project in self.args.projects:
6038
execute(f'sudo systemctl start {project}', ".")
61-
time.sleep(20)
6239
(stdout, stderr, status) = execute(f'sudo systemctl status {project}', ".")
6340
if(status == 0):
6441
logging.info(stdout)
@@ -70,12 +47,16 @@ def start_cluster(self) -> bool:
7047
return True
7148

7249
def validation(self) -> bool:
73-
test_result, counter = ApiTestCases().test_apis(self.args.version, self.args.projects, self.check_for_security_plugin(os.path.join(os.sep, "usr", "share", "opensearch")) if not self.args.force_https else True) # noqa: E501
74-
if (test_result):
75-
logging.info(f'All tests Pass : {counter}')
76-
return True
50+
if self.check_cluster_readiness():
51+
test_result, counter = ApiTestCases().test_apis(self.args.version, self.args.projects,
52+
self.check_for_security_plugin(os.path.join(os.sep, "usr", "share", "opensearch")) if self.args.allow_http else True)
53+
if (test_result):
54+
logging.info(f'All tests Pass : {counter}')
55+
return True
56+
else:
57+
raise Exception(f'Not all tests Pass : {counter}')
7758
else:
78-
raise Exception(f'Not all tests Pass : {counter}')
59+
raise Exception("Cluster is not ready for API test")
7960

8061
def cleanup(self) -> bool:
8162
try:

src/validation_workflow/tar/validation_tar.py

+9-29
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77

88
import logging
99
import os
10-
import time
1110

1211
from system.execute import execute
1312
from system.process import Process
14-
from system.temporary_directory import TemporaryDirectory
1513
from test_workflow.integ_test.utils import get_password
1614
from validation_workflow.api_test_cases import ApiTestCases
1715
from validation_workflow.download_utils import DownloadUtils
@@ -23,29 +21,9 @@ class ValidateTar(Validation, DownloadUtils):
2321

2422
def __init__(self, args: ValidationArgs) -> None:
2523
super().__init__(args)
26-
self.base_url_production = "https://artifacts.opensearch.org/releases/bundle/"
27-
self.base_url_staging = "https://ci.opensearch.org/ci/dbc/distribution-build-"
28-
self.tmp_dir = TemporaryDirectory()
2924
self.os_process = Process()
3025
self.osd_process = Process()
3126

32-
def download_artifacts(self) -> bool:
33-
isFilePathEmpty = bool(self.args.file_path)
34-
for project in self.args.projects:
35-
if (isFilePathEmpty):
36-
if ("https:" not in self.args.file_path.get(project)):
37-
self.copy_artifact(self.args.file_path.get(project), str(self.tmp_dir.path))
38-
else:
39-
self.args.version = self.get_version(self.args.file_path.get(project))
40-
self.check_url(self.args.file_path.get(project))
41-
else:
42-
if (self.args.artifact_type == "staging"):
43-
self.args.file_path[project] = f"{self.base_url_staging}{project}/{self.args.version}/{self.args.build_number[project]}/linux/{self.args.arch}/{self.args.distribution}/dist/{project}/{project}-{self.args.version}-linux-{self.args.arch}.tar.gz" # noqa: E501
44-
else:
45-
self.args.file_path[project] = f"{self.base_url_production}{project}/{self.args.version}/{project}-{self.args.version}-linux-{self.args.arch}.tar.gz"
46-
self.check_url(self.args.file_path.get(project))
47-
return True
48-
4927
def installation(self) -> bool:
5028
try:
5129
for project in self.args.projects:
@@ -58,22 +36,24 @@ def installation(self) -> bool:
5836
def start_cluster(self) -> bool:
5937
try:
6038
self.os_process.start(f'export OPENSEARCH_INITIAL_ADMIN_PASSWORD={get_password(str(self.args.version))} && ./opensearch-tar-install.sh', os.path.join(self.tmp_dir.path, "opensearch"))
61-
time.sleep(85)
6239
if ("opensearch-dashboards" in self.args.projects):
6340
self.osd_process.start(os.path.join(str(self.tmp_dir.path), "opensearch-dashboards", "bin", "opensearch-dashboards"), ".")
64-
time.sleep(20)
6541
logging.info('Started cluster')
6642
except:
6743
raise Exception('Failed to Start Cluster')
6844
return True
6945

7046
def validation(self) -> bool:
71-
test_result, counter = ApiTestCases().test_apis(self.args.version, self.args.projects, self.check_for_security_plugin(os.path.join(self.tmp_dir.path, "opensearch")) if not self.args.force_https else True) # noqa: E501
72-
if (test_result):
73-
logging.info(f'All tests Pass : {counter}')
47+
if self.check_cluster_readiness():
48+
test_result, counter = ApiTestCases().test_apis(self.args.version, self.args.projects,
49+
self.check_for_security_plugin(os.path.join(self.tmp_dir.path, "opensearch")) if self.args.allow_http else True)
50+
if (test_result):
51+
logging.info(f'All tests Pass : {counter}')
52+
return True
53+
else:
54+
raise Exception(f'Not all tests Pass : {counter}')
7455
else:
75-
raise Exception(f'Not all tests Pass : {counter}')
76-
return True
56+
raise Exception("Cluster is not ready for API test")
7757

7858
def cleanup(self) -> bool:
7959
try:

0 commit comments

Comments
 (0)