aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Halych <illia.halych@t-mobile.pl>2021-01-28 16:11:39 +0000
committerEli Halych <illia.halych@t-mobile.pl>2021-02-22 14:08:46 +0000
commit920aa926a2a78dc7f1ba63e648d124a405962017 (patch)
tree5ccfcd42da8c0fefd506cb65c6e3da8ecf26364c
parentca74c6ae7ad7dfd03f547fcd706bdfcdde1b20b4 (diff)
Wrapper for simulators
Implemented using Avionix. Supports Helm 3 only. The local directory path was defined relative to the package. Remote charts that are described locally are used. Starting the simulator is provided as a regular HTTP or HTTPS request. Issue-ID: INT-1829 Signed-off-by: Eli Halych <illia.halych@t-mobile.pl> Change-Id: Ia17c4043bedd853bf2c068e53d51cd2808a3c0db
-rw-r--r--requirements.txt3
-rw-r--r--src/onaptests/configuration/settings.py1
-rw-r--r--src/onaptests/steps/wrapper/__init__.py0
-rw-r--r--src/onaptests/steps/wrapper/helm_charts.py93
-rw-r--r--src/onaptests/steps/wrapper/start.py64
-rwxr-xr-xsrc/onaptests/templates/helm_charts/README.md31
-rw-r--r--src/onaptests/utils/exceptions.py4
-rw-r--r--src/onaptests/utils/simulators.py13
8 files changed, 208 insertions, 1 deletions
diff --git a/requirements.txt b/requirements.txt
index fec6816..945b8ff 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,4 +3,5 @@ openstacksdk
onapsdk==7.4.0
jinja2
kubernetes
-docker \ No newline at end of file
+docker
+avionix==0.4.4 \ No newline at end of file
diff --git a/src/onaptests/configuration/settings.py b/src/onaptests/configuration/settings.py
index ba4e163..609ca66 100644
--- a/src/onaptests/configuration/settings.py
+++ b/src/onaptests/configuration/settings.py
@@ -41,6 +41,7 @@ CLEANUP_FLAG = False
REPORTING_FILE_PATH = "/tmp/reporting.html"
K8S_REGION_TYPE = "k8s"
+TILLER_HOST = "localhost"
K8S_CONFIG = None # None means it will use default config (~/.kube/config)
K8S_NAMESPACE = "onap" # Kubernetes namespace
#SOCK_HTTP = "socks5h://127.0.0.1:8091"
diff --git a/src/onaptests/steps/wrapper/__init__.py b/src/onaptests/steps/wrapper/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/onaptests/steps/wrapper/__init__.py
diff --git a/src/onaptests/steps/wrapper/helm_charts.py b/src/onaptests/steps/wrapper/helm_charts.py
new file mode 100644
index 0000000..4482683
--- /dev/null
+++ b/src/onaptests/steps/wrapper/helm_charts.py
@@ -0,0 +1,93 @@
+"""Basic container commands to Docker."""
+import yaml
+from avionix import ChartBuilder, ChartDependency, ChartInfo
+from avionix.errors import HelmError
+from onaptests.steps.base import BaseStep
+from onaptests.utils.simulators import get_local_dir
+from onaptests.utils.exceptions import (
+ EnvironmentPreparationException,
+ EnvironmentCleanupException)
+
+
+
+class HelmChartStep(BaseStep):
+ """Basic operations on a docker container."""
+
+ def __init__(self,
+ cleanup: bool = False,
+ chart_info_file: str = None) -> None:
+ """Setup Helm chart details.
+
+ Arguments:
+ cleanup (bool): cleanup after execution. Defaults to False.
+ chart_info_file (str): description file of a chart. Default to None.
+ """
+ chart_info = None
+ dependencies = []
+
+ super().__init__(cleanup=cleanup)
+
+ chart_info_path = get_local_dir() / chart_info_file
+
+ try:
+ with open(chart_info_path, 'r') as stream:
+ chart_info = yaml.safe_load(stream)
+ except IOError as err:
+ msg = f"{chart_info_file} not found."
+ raise EnvironmentPreparationException(msg) from err
+
+
+ try:
+ for dependency in chart_info["dependencies"]:
+ dep = ChartDependency(
+ name=dependency["name"],
+ version=dependency["version"],
+ repository=dependency["repository"],
+ local_repo_name=dependency["local_repo_name"],
+ values=dependency["values"])
+ dependencies.append(dep)
+
+ self.builder = ChartBuilder(
+ chart_info=ChartInfo(
+ api_version=chart_info["api_version"],
+ name=chart_info["chart_name"],
+ version=chart_info["version"], # SemVer 2 version
+ app_version=chart_info["app_version"],
+ dependencies=dependencies
+ ),
+ kubernetes_objects=[],
+ keep_chart=False
+ )
+ except KeyError as err:
+ msg = f"{chart_info_file} does not contain required keys."
+ raise EnvironmentPreparationException(msg) from err
+
+ @property
+ def description(self) -> str:
+ """Step description."""
+ return "Execute Helm charts."
+
+ @property
+ def component(self) -> str:
+ """Component name."""
+ return "Environment"
+
+ @BaseStep.store_state
+ def execute(self) -> None:
+ """Install helm release."""
+ super().execute()
+ try:
+ self.builder.install_chart({"dependency-update": None})
+ except HelmError as err:
+ msg = "Error during helm release installation."
+ raise EnvironmentPreparationException(msg) from err
+
+
+ def cleanup(self) -> None:
+ """Uninstall helm release."""
+ try:
+ self.builder.uninstall_chart()
+ except HelmError as err:
+ msg = "Error during helm release deletion."
+ raise EnvironmentCleanupException(msg) from err
+ super().cleanup()
diff --git a/src/onaptests/steps/wrapper/start.py b/src/onaptests/steps/wrapper/start.py
new file mode 100644
index 0000000..18ba5df
--- /dev/null
+++ b/src/onaptests/steps/wrapper/start.py
@@ -0,0 +1,64 @@
+"""Start simulators via simulators' API."""
+from typing import Union, Optional, Dict
+import requests
+from onaptests.steps.base import BaseStep
+from onaptests.utils.exceptions import TestConfigurationException
+
+class SimulatorStartStep(BaseStep):
+ """Basic operations on a docker container."""
+
+ def __init__(self, # pylint: disable=R0913
+ cleanup: bool = False,
+ https: bool = False,
+ host: str = None,
+ port: Union[int, str] = None,
+ endpoint: Optional[str] = "",
+ method: str = "GET",
+ data: Dict = None) -> None:
+ """Prepare request data and details.
+
+ Arguments:
+ cleanup (bool):
+ determines if cleanup action should be called.
+ Defaults to False.
+ https (bool): use https or http. Defaults to False.
+ host (str): IP or hostname. Defaults to None.
+ port (Union[int, str]): port number. Defaults to None.
+ endpoint (str):
+ additional endpoint if applicable.
+ Defautls to "".
+ method (str):
+ GET or POST strings, case insensitive.
+ Defaults tp GET.
+ data (Dict):
+ parameters, that request's post() or get() takes, besides url.
+ For example, {"json": {}, ...}. Defaults to None.
+ """
+ if not host and not port:
+ raise TestConfigurationException("Provide host and/or port.")
+
+ super().__init__(cleanup=cleanup)
+
+ default_port = "443" if https else "80"
+ protocol = "https" if https else "http"
+ endpoint = endpoint[1:] if endpoint.startswith("/") else endpoint
+
+ self.method = method
+ self.data = data if data else {}
+ self.url = f"{protocol}://{host}:{port or default_port}/{endpoint}"
+
+ @property
+ def description(self) -> str:
+ """Step description."""
+ return "Send commands to the simulator application."
+
+ @property
+ def component(self) -> str:
+ """Component name."""
+ return "Environment"
+
+ @BaseStep.store_state
+ def execute(self) -> None:
+ """Send a start command to the simulator application."""
+ super().execute()
+ requests.request(self.method.upper(), self.url, **self.data)
diff --git a/src/onaptests/templates/helm_charts/README.md b/src/onaptests/templates/helm_charts/README.md
new file mode 100755
index 0000000..bf76ee2
--- /dev/null
+++ b/src/onaptests/templates/helm_charts/README.md
@@ -0,0 +1,31 @@
+# Local helm chart directory
+
+It is adviced that a remote repository is used for simulators, to reduce local
+complexity and avoid mistakes related to the duplicate code, submodules etc.
+
+Place a .yaml file in this folder and mention it during HelmChartStep
+initialization.
+
+How a chart info .yaml file would look like:
+
+```yaml
+api_version: "v1"
+app_version: "3.11.9"
+chart_name: "mychart"
+version: "0.1.0"
+dependencies:
+- name: "cassandra"
+ version: "0.1.4"
+ repository: "https://charts.kube-ops.io"
+ local_repo_name: "kube-ops"
+ values: {}
+- name: "generate"
+ repository: https://charts.kube-ops.io
+ version: "~0.2.3"
+ local_repo_name: "kube-ops"
+ values: {}
+```
+
+All fields in the sample .yaml file above are required by the avionix library.
+For more details, refer to the
+[documentation](https://avionix.readthedocs.io/en/latest/reference/index.html).
diff --git a/src/onaptests/utils/exceptions.py b/src/onaptests/utils/exceptions.py
index e453d67..c12ee2f 100644
--- a/src/onaptests/utils/exceptions.py
+++ b/src/onaptests/utils/exceptions.py
@@ -74,3 +74,7 @@ class EnvironmentPreparationException(OnapTestException):
class SubstepExecutionException(OnapTestException):
"""Exception raised if substep execution fails."""
+
+class EnvironmentCleanupException(OnapTestException):
+ """Test environment cleanup exception."""
+ error_message="Test couldn't finish a cleanup"
diff --git a/src/onaptests/utils/simulators.py b/src/onaptests/utils/simulators.py
new file mode 100644
index 0000000..08acdbd
--- /dev/null
+++ b/src/onaptests/utils/simulators.py
@@ -0,0 +1,13 @@
+"""Standard functions for the simulator wrapper."""
+from importlib.resources import path
+
+def get_local_dir():
+ """Get the default path for helm charts.
+
+ Returns:
+ chart_directory (Path):
+ local helm chart folder relative to the package.
+ """
+ with path('onaptests', 'templates') as templates:
+ chart_directory = templates / 'helm_charts'
+ return chart_directory