Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rpm support in integTest framework (2nd PR) #2000

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/test_workflow/integ_test/distribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.

from abc import ABC, abstractmethod


class Distribution(ABC):
def __enter__(self) -> 'Distribution':
return self

def __init__(self, filename: str, version: str, work_dir: str) -> None:
self.filename = filename
self.version = version
self.work_dir = work_dir

@property
@abstractmethod
def install_dir(self) -> str:
"""
Return the install directory for the distribution
"""
pass

@property
@abstractmethod
def config_dir(self, bundle_name: str) -> str:
"""
Return the config directory for the distribution
"""
pass

@abstractmethod
def install(self) -> None:
"""
The detailed method to install the distribution before start the service
"""
pass

@property
@abstractmethod
def start_cmd(self) -> str:
"""
Return the start command for the distribution
"""
pass

def uninstall(self) -> None:
"""
Allow distribution that is not 'tar' to do proper cleanup
peterzhuamazon marked this conversation as resolved.
Show resolved Hide resolved
"""
pass
50 changes: 50 additions & 0 deletions src/test_workflow/integ_test/distribution_rpm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.

import logging
import os
import subprocess

from test_workflow.integ_test.distribution import Distribution


class DistributionRpm(Distribution):
def __init__(self, filename: str, version: str, work_dir: str) -> None:
super().__init__(filename, version, work_dir)

@property
def install_dir(self) -> str:
return os.path.join(os.sep, "usr", "share", self.filename)

@property
def config_dir(self) -> str:
return os.path.join(os.sep, "etc", self.filename)

def install(self, bundle_name: str) -> None:
logging.info(f"Installing {bundle_name} in {self.install_dir}")
logging.info("rpm installation requires sudo, script will exit if current user does not have sudo access")
rpm_install_cmd = " ".join(
[
'yum',
'remove',
'-y',
self.filename,
'&&',
'yum',
'install',
'-y',
bundle_name
]
)
subprocess.check_call(rpm_install_cmd, cwd=self.work_dir, shell=True)

@property
peterzhuamazon marked this conversation as resolved.
Show resolved Hide resolved
def start_cmd(self) -> str:
return f"systemctl start {self.filename}"

def uninstall(self) -> None:
logging.info("Uninstall {self.filename} package after the test")
subprocess.check_call(f"yum remove -y {self.filename}", shell=True)
37 changes: 37 additions & 0 deletions src/test_workflow/integ_test/distribution_tar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.

import logging
import os
import tarfile

from test_workflow.integ_test.distribution import Distribution


class DistributionTar(Distribution):
def __init__(self, filename: str, version: str, work_dir: str) -> None:
super().__init__(filename, version, work_dir)

@property
def install_dir(self) -> str:
return os.path.join(self.work_dir, f"{self.filename}-{self.version}")

@property
def config_dir(self) -> str:
return os.path.join(self.install_dir, "config")

def install(self, bundle_name: str) -> None:
logging.info(f"Installing {bundle_name} in {self.install_dir}")
with tarfile.open(bundle_name, 'r:gz') as bundle_tar:
bundle_tar.extractall(self.work_dir)

@property
def start_cmd(self) -> str:
start_cmd_map = {
"opensearch": "./opensearch-tar-install.sh",
"opensearch-dashboards": "./opensearch-dashboards",
}
return start_cmd_map[self.filename]
31 changes: 31 additions & 0 deletions src/test_workflow/integ_test/distributions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.

import logging

from test_workflow.integ_test.distribution import Distribution
from test_workflow.integ_test.distribution_rpm import DistributionRpm
from test_workflow.integ_test.distribution_tar import DistributionTar


class Distributions:
DISTRIBUTIONS_MAP = {
"tar": DistributionTar,
"rpm": DistributionRpm,
}

@classmethod
def from_name(cls, name: str) -> Distribution:
klass = cls.DISTRIBUTIONS_MAP.get(name, None)
if not klass:
raise ValueError(f"Unsupported distribution: {name}")
return klass # type: ignore[return-value]

@classmethod
def get_distribution(cls, filename: str, distribution: str, version: str, work_dir: str) -> Distribution:
klass = cls.from_name(distribution)
logging.info(f"{filename} distribution: {distribution}")
return klass(filename, version, work_dir) # type: ignore[no-any-return, operator]
1 change: 1 addition & 0 deletions src/test_workflow/integ_test/local_test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(

self.service_opensearch = ServiceOpenSearch(
self.manifest.build.version,
self.manifest.build.distribution,
self.additional_cluster_config,
self.security_enabled,
self.dependency_installer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ def __init__(

self.service_opensearch = ServiceOpenSearch(
self.manifest_opensearch.build.version,
self.manifest_opensearch.build.distribution,
{},
self.security_enabled,
self.dependency_installer_opensearch,
self.work_dir)

build = self.manifest_opensearch_dashboards.build

self.service_opensearch_dashboards = ServiceOpenSearchDashboards(
build.version,
self.manifest_opensearch_dashboards.build.version,
self.manifest_opensearch_dashboards.build.distribution,
self.additional_cluster_config,
self.security_enabled,
self.dependency_installer_opensearch_dashboards,
Expand Down
12 changes: 11 additions & 1 deletion src/test_workflow/integ_test/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import abc
import logging
import os
import time

import requests
Expand All @@ -19,9 +20,10 @@ class Service(abc.ABC):
Abstract base class for all types of test clusters.
"""

def __init__(self, work_dir, version, security_enabled, additional_config, dependency_installer):
def __init__(self, work_dir, version, distribution, security_enabled, additional_config, dependency_installer):
self.work_dir = work_dir
self.version = version
self.distribution = distribution
self.security_enabled = security_enabled
self.additional_config = additional_config
self.dependency_installer = dependency_installer
Expand All @@ -43,6 +45,8 @@ def terminate(self):

self.return_code = self.process_handler.terminate()

self.uninstall()

return ServiceTerminationResult(self.return_code, self.process_handler.stdout_data, self.process_handler.stderr_data, self.log_files)

def endpoint(self):
Expand Down Expand Up @@ -80,6 +84,12 @@ def service_alive(self):
else:
return False

def download(self):
logging.info("Downloading bundle artifact")
bundle_name = self.dependency_installer.download_dist(self.work_dir)
logging.info(f"Downloaded bundle to {os.path.realpath(bundle_name)}")
return bundle_name

def wait_for_service(self):
logging.info("Waiting for service to become available")

Expand Down
28 changes: 10 additions & 18 deletions src/test_workflow/integ_test/service_opensearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,34 @@

import logging
import os
import tarfile

import requests
import yaml

from test_workflow.integ_test.distributions import Distributions
from test_workflow.integ_test.service import Service


class ServiceOpenSearch(Service):
def __init__(
self,
version,
distribution,
additional_config,
security_enabled,
dependency_installer,
work_dir
):
super().__init__(work_dir, version, security_enabled, additional_config, dependency_installer)
super().__init__(work_dir, version, distribution, security_enabled, additional_config, dependency_installer)

self.dist = Distributions.get_distribution("opensearch", distribution, version, work_dir)
self.dependency_installer = dependency_installer

self.install_dir = os.path.join(self.work_dir, f"opensearch-{self.version}")
self.install_dir = self.dist.install_dir

def start(self):
self.__download()
self.dist.install(self.download())

self.opensearch_yml_dir = os.path.join(self.install_dir, "config", "opensearch.yml")
self.opensearch_yml_dir = os.path.join(self.dist.config_dir, "opensearch.yml")
self.security_plugin_dir = os.path.join(self.install_dir, "plugins", "opensearch-security")

if not self.security_enabled and os.path.isdir(self.security_plugin_dir):
Expand All @@ -41,20 +42,11 @@ def start(self):
if self.additional_config:
self.__add_plugin_specific_config(self.additional_config)

self.process_handler.start("./opensearch-tar-install.sh", self.install_dir)
self.process_handler.start(self.dist.start_cmd, self.install_dir)
logging.info(f"Started OpenSearch with parent PID {self.process_handler.pid}")

def __download(self):
logging.info(f"Creating local test cluster in {self.work_dir}")
logging.info("Downloading bundle")
bundle_name = self.dependency_installer.download_dist(self.work_dir)
logging.info(f"Downloaded bundle to {os.path.realpath(bundle_name)}")

logging.info(f"Unpacking {bundle_name}")
with tarfile.open(bundle_name, 'r') as bundle_tar:
bundle_tar.extractall(self.work_dir)

logging.info(f"Unpacked {bundle_name}")
def uninstall(self):
self.dist.uninstall()

def url(self, path=""):
return f'{"https" if self.security_enabled else "http"}://{self.endpoint()}:{self.port()}{path}'
Expand Down
31 changes: 12 additions & 19 deletions src/test_workflow/integ_test/service_opensearch_dashboards.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,32 @@
import logging
import os
import subprocess
import tarfile

import requests
import yaml

from test_workflow.integ_test.distributions import Distributions
from test_workflow.integ_test.service import Service


class ServiceOpenSearchDashboards(Service):
def __init__(
self,
version,
distribution,
additional_config,
security_enabled,
dependency_installer,
work_dir
):
super().__init__(work_dir, version, security_enabled, additional_config, dependency_installer)
self.install_dir = os.path.join(self.work_dir, f"opensearch-dashboards-{self.version}")
super().__init__(work_dir, version, distribution, security_enabled, additional_config, dependency_installer)
self.dist = Distributions.get_distribution("opensearch-dashboards", distribution, version, work_dir)
self.install_dir = self.dist.install_dir

def start(self):
logging.info(f"Starting OpenSearch Dashboards service from {self.work_dir}")
self.__download()
self.dist.install(self.download())

self.opensearch_dashboards_yml_dir = os.path.join(self.install_dir, "config", "opensearch_dashboards.yml")
self.opensearch_dashboards_yml_dir = os.path.join(self.dist.config_dir, "opensearch_dashboards.yml")
self.executable_dir = os.path.join(self.install_dir, "bin")

if not self.security_enabled:
Expand All @@ -42,9 +43,12 @@ def start(self):
if self.additional_config:
self.__add_plugin_specific_config(self.additional_config)

self.process_handler.start("./opensearch-dashboards", self.executable_dir)
self.process_handler.start(self.dist.start_cmd, self.executable_dir)
logging.info(f"Started OpenSearch Dashboards with parent PID {self.process_handler.pid}")

def uninstall(self):
self.dist.uninstall()

def __set_logging_dest(self):
self.log_dir = os.path.join(self.install_dir, "logs")
os.makedirs(self.log_dir, exist_ok=True)
Expand All @@ -53,22 +57,11 @@ def __set_logging_dest(self):
def __remove_security(self):
self.security_plugin_dir = os.path.join(self.install_dir, "plugins", "securityDashboards")
if os.path.isdir(self.security_plugin_dir):
subprocess.check_call("./opensearch-dashboards-plugin remove securityDashboards", cwd=self.executable_dir, shell=True)
subprocess.check_call("./opensearch-dashboards-plugin remove --allow-root securityDashboards", cwd=self.executable_dir, shell=True)

with open(self.opensearch_dashboards_yml_dir, "w") as yamlfile:
yamlfile.close()

def __download(self):
logging.info("Downloading OpenSearch Dashboards bundle")
bundle_name = self.dependency_installer.download_dist(self.work_dir)
logging.info(f"Downloaded bundle to {os.path.realpath(bundle_name)}")

logging.info(f"Unpacking {bundle_name}")
with tarfile.open(bundle_name, 'r') as bundle_tar:
bundle_tar.extractall(self.work_dir)

logging.info(f"Unpacked {bundle_name}")

def url(self, path=""):
return f'http://{self.endpoint()}:{self.port()}{path}'

Expand Down
Binary file not shown.
Loading