Squashed 'acm-hub-bootstrap/' content from commit 4b79b1a0
git-subtree-dir: acm-hub-bootstrap git-subtree-split: 4b79b1a0be6da2a9efc9ace8871b4762342da70b
This commit is contained in:
25
tests/interop/README.md
Normal file
25
tests/interop/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Running tests
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Openshift clusters with multicloud-gitops pattern installed
|
||||
* factory cluster is managed via rhacm
|
||||
* kubeconfig files for Openshift clusters
|
||||
* oc client installed at ~/oc_client/oc
|
||||
|
||||
## Steps
|
||||
|
||||
* create python3 venv, clone multicloud-gitops repository
|
||||
* export KUBECONFIG=\<path to hub kubeconfig file>
|
||||
* export KUBECONFIG_EDGE=\<path to edge kubeconfig file>
|
||||
* export INFRA_PROVIDER=\<infra platform description>
|
||||
* (optional) export WORKSPACE=\<dir to save test results to> (defaults to /tmp)
|
||||
* cd multicloud-gitops/tests/interop
|
||||
* pip install -r requirements.txt
|
||||
* ./run_tests.sh
|
||||
|
||||
## Results
|
||||
|
||||
* results .xml files will be placed at $WORKSPACE
|
||||
* test logs will be placed at $WORKSPACE/.results/test_execution_logs/
|
||||
* CI badge file will be placed at $WORKSPACE
|
||||
2
tests/interop/__init__.py
Normal file
2
tests/interop/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
__version__ = "0.1.0"
|
||||
__loggername__ = "css_logger"
|
||||
2
tests/interop/conftest.py
Normal file
2
tests/interop/conftest.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from validatedpatterns_tests.interop.conftest_logger import * # noqa: F401, F403
|
||||
from validatedpatterns_tests.interop.conftest_openshift import * # noqa: F401, F403
|
||||
84
tests/interop/create_ci_badge.py
Normal file
84
tests/interop/create_ci_badge.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
from junitparser import JUnitXml
|
||||
|
||||
oc = os.environ["HOME"] + "/oc_client/oc"
|
||||
|
||||
ci_badge = {
|
||||
"schemaVersion": 1,
|
||||
"label": "Community test",
|
||||
"message": "",
|
||||
"color": "red",
|
||||
"openshiftVersion": "",
|
||||
"infraProvider": os.environ.get("INFRA_PROVIDER"),
|
||||
"patternName": os.environ.get("PATTERN_NAME"),
|
||||
"patternRepo": "",
|
||||
"patternBranch": "",
|
||||
"date": datetime.today().strftime("%Y-%m-%d"),
|
||||
"testSource": "Community",
|
||||
"debugInfo": None,
|
||||
}
|
||||
|
||||
|
||||
def get_openshift_version():
|
||||
try:
|
||||
version_ret = subprocess.run([oc, "version", "-o", "json"], capture_output=True)
|
||||
version_out = version_ret.stdout.decode("utf-8")
|
||||
openshift_version = json.loads(version_out)["openshiftVersion"]
|
||||
major_minor = ".".join(openshift_version.split(".")[:-1])
|
||||
return openshift_version, major_minor
|
||||
except KeyError as e:
|
||||
print("KeyError:" + str(e))
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
versions = get_openshift_version()
|
||||
ci_badge["openshiftVersion"] = versions[0]
|
||||
|
||||
pattern_repo = subprocess.run(
|
||||
["git", "config", "--get", "remote.origin.url"], capture_output=True, text=True
|
||||
)
|
||||
pattern_branch = subprocess.run(
|
||||
["git", "branch", "--show-current"], capture_output=True, text=True
|
||||
)
|
||||
|
||||
ci_badge["patternRepo"] = pattern_repo.stdout.strip()
|
||||
ci_badge["patternBranch"] = pattern_branch.stdout.strip()
|
||||
|
||||
# Check each xml file for failures
|
||||
results_dir = os.environ.get("WORKSPACE")
|
||||
failures = 0
|
||||
|
||||
for file in os.listdir(results_dir):
|
||||
if file.startswith("test_") and file.endswith(".xml"):
|
||||
with open(os.path.join(results_dir, file), "r") as result_file: # type: ignore
|
||||
xml = JUnitXml.fromfile(result_file) # type: ignore
|
||||
for suite in xml:
|
||||
for case in suite:
|
||||
if case.result:
|
||||
failures += 1
|
||||
|
||||
# Determine badge color from results
|
||||
if failures == 0:
|
||||
ci_badge["color"] = "green"
|
||||
|
||||
# For now we assume `message` is the same as patternBranch
|
||||
ci_badge["message"] = ci_badge["patternBranch"]
|
||||
|
||||
ci_badge_json_basename = (
|
||||
os.environ.get("PATTERN_SHORTNAME") # type: ignore
|
||||
+ "-"
|
||||
+ os.environ.get("INFRA_PROVIDER")
|
||||
+ "-"
|
||||
+ versions[1]
|
||||
+ "-stable-badge.json"
|
||||
)
|
||||
ci_badge_json_filename = os.path.join(results_dir, ci_badge_json_basename) # type: ignore
|
||||
print(f"Creating CI badge file at: {ci_badge_json_filename}")
|
||||
|
||||
with open(ci_badge_json_filename, "w") as ci_badge_file:
|
||||
json.dump(ci_badge, ci_badge_file)
|
||||
6
tests/interop/requirements.txt
Normal file
6
tests/interop/requirements.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
pytest
|
||||
kubernetes
|
||||
openshift
|
||||
openshift-python-wrapper
|
||||
junitparser
|
||||
git+https://github.com/validatedpatterns/vp-qe-test-common.git@development#egg=vp-qe-test-common
|
||||
36
tests/interop/run_tests.sh
Executable file
36
tests/interop/run_tests.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
export EXTERNAL_TEST="true"
|
||||
export PATTERN_NAME="MultiCloudGitops"
|
||||
export PATTERN_SHORTNAME="mcgitops"
|
||||
|
||||
if [ -z "${KUBECONFIG}" ]; then
|
||||
echo "No kubeconfig file set for hub cluster"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${KUBECONFIG_EDGE}" ]; then
|
||||
echo "No kubeconfig file set for edge cluster"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${INFRA_PROVIDER}" ]; then
|
||||
echo "INFRA_PROVIDER is not defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${WORKSPACE}" ]; then
|
||||
export WORKSPACE=/tmp
|
||||
fi
|
||||
|
||||
pytest -lv --disable-warnings test_subscription_status_hub.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_subscription_status_hub.xml
|
||||
|
||||
pytest -lv --disable-warnings test_subscription_status_edge.py --kubeconfig $KUBECONFIG_EDGE --junit-xml $WORKSPACE/test_subscription_status_edge.xml
|
||||
|
||||
pytest -lv --disable-warnings test_validate_hub_site_components.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_validate_hub_site_components.xml
|
||||
|
||||
pytest -lv --disable-warnings test_validate_edge_site_components.py --kubeconfig $KUBECONFIG_EDGE --junit-xml $WORKSPACE/test_validate_edge_site_components.xml
|
||||
|
||||
pytest -lv --disable-warnings test_modify_web_content.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_modify_web_content.xml
|
||||
|
||||
python3 create_ci_badge.py
|
||||
89
tests/interop/test_modify_web_content.py
Normal file
89
tests/interop/test_modify_web_content.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from ocp_resources.route import Route
|
||||
from openshift.dynamic.exceptions import NotFoundError
|
||||
from validatedpatterns_tests.interop.edge_util import modify_file_content
|
||||
|
||||
from . import __loggername__
|
||||
|
||||
logger = logging.getLogger(__loggername__)
|
||||
|
||||
|
||||
@pytest.mark.modify_web_content
|
||||
def test_modify_web_content(openshift_dyn_client):
|
||||
logger.info("Find the url for the hello-world route")
|
||||
try:
|
||||
for route in Route.get(
|
||||
dyn_client=openshift_dyn_client,
|
||||
namespace="hello-world",
|
||||
name="hello-world",
|
||||
):
|
||||
logger.info(route.instance.spec.host)
|
||||
except NotFoundError:
|
||||
err_msg = "hello-world url/route is missing in hello-world namespace"
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
|
||||
url = "http://" + route.instance.spec.host
|
||||
response = requests.get(url)
|
||||
logger.info(f"Current page content: {response.content}")
|
||||
|
||||
if os.getenv("EXTERNAL_TEST") != "true":
|
||||
chart = (
|
||||
f"{os.environ['HOME']}"
|
||||
+ "/validated_patterns/multicloud-gitops/charts/"
|
||||
+ "all/hello-world/templates/hello-world-cm.yaml"
|
||||
)
|
||||
else:
|
||||
chart = "../../charts/all/hello-world/templates/hello-world-cm.yaml"
|
||||
|
||||
logger.info("Modify the file content")
|
||||
orig_heading = "<h1>Hello World!</h1>"
|
||||
new_heading = "<h1>Validated Patterns QE was here!</h1>"
|
||||
modify_file_content(
|
||||
file_name=chart, orig_content=orig_heading, new_content=new_heading
|
||||
)
|
||||
|
||||
logger.info("Merge the change")
|
||||
patterns_repo = f"{os.environ['HOME']}/validated_patterns/multicloud-gitops"
|
||||
if os.getenv("EXTERNAL_TEST") != "true":
|
||||
subprocess.run(["git", "add", chart], cwd=f"{patterns_repo}")
|
||||
subprocess.run(
|
||||
["git", "commit", "-m", "Updating 'hello-world'"], cwd=f"{patterns_repo}"
|
||||
)
|
||||
push = subprocess.run(
|
||||
["git", "push"], cwd=f"{patterns_repo}", capture_output=True, text=True
|
||||
)
|
||||
else:
|
||||
subprocess.run(["git", "add", chart])
|
||||
subprocess.run(["git", "commit", "-m", "Updating 'hello-world'"])
|
||||
push = subprocess.run(["git", "push"], capture_output=True, text=True)
|
||||
logger.info(push.stdout)
|
||||
logger.info(push.stderr)
|
||||
|
||||
logger.info("Checking for updated page content")
|
||||
timeout = time.time() + 60 * 10
|
||||
while time.time() < timeout:
|
||||
time.sleep(30)
|
||||
response = requests.get(url)
|
||||
logger.info(response.content)
|
||||
|
||||
new_content = re.search(new_heading, str(response.content))
|
||||
|
||||
logger.info(new_content)
|
||||
if (new_content is None) or (new_content.group() != new_heading):
|
||||
continue
|
||||
break
|
||||
|
||||
if (new_content is None) or (new_content.group() != new_heading):
|
||||
err_msg = "Did not find updated page content"
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Found updated page content")
|
||||
25
tests/interop/test_subscription_status_edge.py
Normal file
25
tests/interop/test_subscription_status_edge.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from validatedpatterns_tests.interop import subscription
|
||||
|
||||
from . import __loggername__
|
||||
|
||||
logger = logging.getLogger(__loggername__)
|
||||
|
||||
|
||||
@pytest.mark.subscription_status_edge
|
||||
def test_subscription_status_edge(openshift_dyn_client):
|
||||
# These are the operator subscriptions and their associated namespaces
|
||||
expected_subs = {
|
||||
"openshift-gitops-operator": ["openshift-operators"],
|
||||
}
|
||||
|
||||
err_msg = subscription.subscription_status(
|
||||
openshift_dyn_client, expected_subs, diff=False
|
||||
)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Subscription status check passed")
|
||||
27
tests/interop/test_subscription_status_hub.py
Normal file
27
tests/interop/test_subscription_status_hub.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from validatedpatterns_tests.interop import subscription
|
||||
|
||||
from . import __loggername__
|
||||
|
||||
logger = logging.getLogger(__loggername__)
|
||||
|
||||
|
||||
@pytest.mark.subscription_status_hub
|
||||
def test_subscription_status_hub(openshift_dyn_client):
|
||||
# These are the operator subscriptions and their associated namespaces
|
||||
expected_subs = {
|
||||
"openshift-gitops-operator": ["openshift-operators"],
|
||||
"advanced-cluster-management": ["open-cluster-management"],
|
||||
"multicluster-engine": ["multicluster-engine"],
|
||||
}
|
||||
|
||||
err_msg = subscription.subscription_status(
|
||||
openshift_dyn_client, expected_subs, diff=True
|
||||
)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Subscription status check passed")
|
||||
72
tests/interop/test_validate_edge_site_components.py
Normal file
72
tests/interop/test_validate_edge_site_components.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from validatedpatterns_tests.interop import application, components
|
||||
|
||||
from . import __loggername__
|
||||
|
||||
logger = logging.getLogger(__loggername__)
|
||||
|
||||
oc = os.environ["HOME"] + "/oc_client/oc"
|
||||
|
||||
|
||||
@pytest.mark.test_validate_edge_site_components
|
||||
def test_validate_edge_site_components():
|
||||
logger.info("Checking Openshift version on edge site")
|
||||
version_out = components.dump_openshift_version()
|
||||
logger.info(f"Openshift version:\n{version_out}")
|
||||
|
||||
|
||||
@pytest.mark.validate_edge_site_reachable
|
||||
def test_validate_edge_site_reachable(kube_config, openshift_dyn_client):
|
||||
logger.info("Check if edge site API end point is reachable")
|
||||
err_msg = components.validate_site_reachable(kube_config, openshift_dyn_client)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Edge site is reachable")
|
||||
|
||||
|
||||
@pytest.mark.validate_argocd_reachable_edge_site
|
||||
def test_validate_argocd_reachable_edge_site(openshift_dyn_client):
|
||||
logger.info("Check if argocd route/url on edge site is reachable")
|
||||
err_msg = components.validate_argocd_reachable(openshift_dyn_client)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Argocd is reachable")
|
||||
|
||||
|
||||
@pytest.mark.check_pod_status_edge
|
||||
def test_check_pod_status(openshift_dyn_client):
|
||||
logger.info("Checking pod status")
|
||||
projects = [
|
||||
"openshift-operators",
|
||||
"open-cluster-management-agent",
|
||||
"open-cluster-management-agent-addon",
|
||||
"openshift-gitops",
|
||||
]
|
||||
err_msg = components.check_pod_status(openshift_dyn_client, projects)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Pod status check succeeded.")
|
||||
|
||||
|
||||
@pytest.mark.validate_argocd_applications_health_edge_site
|
||||
def test_validate_argocd_applications_health_edge_site(openshift_dyn_client):
|
||||
logger.info("Get all applications deployed by argocd on edge site")
|
||||
projects = ["openshift-gitops"]
|
||||
unhealthy_apps = application.get_argocd_application_status(
|
||||
openshift_dyn_client, projects
|
||||
)
|
||||
if unhealthy_apps:
|
||||
err_msg = "Some or all applications deployed on edge site are unhealthy"
|
||||
logger.error(f"FAIL: {err_msg}:\n{unhealthy_apps}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: All applications deployed on edge site are healthy.")
|
||||
95
tests/interop/test_validate_hub_site_components.py
Normal file
95
tests/interop/test_validate_hub_site_components.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
from ocp_resources.storage_class import StorageClass
|
||||
from validatedpatterns_tests.interop import application, components
|
||||
|
||||
from . import __loggername__
|
||||
|
||||
logger = logging.getLogger(__loggername__)
|
||||
|
||||
oc = os.environ["HOME"] + "/oc_client/oc"
|
||||
|
||||
|
||||
@pytest.mark.test_validate_hub_site_components
|
||||
def test_validate_hub_site_components(openshift_dyn_client):
|
||||
logger.info("Checking Openshift version on hub site")
|
||||
version_out = components.dump_openshift_version()
|
||||
logger.info(f"Openshift version:\n{version_out}")
|
||||
|
||||
logger.info("Dump PVC and storageclass info")
|
||||
pvcs_out = components.dump_pvc()
|
||||
logger.info(f"PVCs:\n{pvcs_out}")
|
||||
|
||||
for sc in StorageClass.get(dyn_client=openshift_dyn_client):
|
||||
logger.info(sc.instance)
|
||||
|
||||
|
||||
@pytest.mark.validate_hub_site_reachable
|
||||
def test_validate_hub_site_reachable(kube_config, openshift_dyn_client):
|
||||
logger.info("Check if hub site API end point is reachable")
|
||||
err_msg = components.validate_site_reachable(kube_config, openshift_dyn_client)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Hub site is reachable")
|
||||
|
||||
|
||||
@pytest.mark.check_pod_status_hub
|
||||
def test_check_pod_status(openshift_dyn_client):
|
||||
logger.info("Checking pod status")
|
||||
projects = [
|
||||
"openshift-operators",
|
||||
"open-cluster-management",
|
||||
"open-cluster-management-hub",
|
||||
"openshift-gitops",
|
||||
"vault",
|
||||
]
|
||||
err_msg = components.check_pod_status(openshift_dyn_client, projects)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Pod status check succeeded.")
|
||||
|
||||
|
||||
@pytest.mark.validate_acm_self_registration_managed_clusters
|
||||
def test_validate_acm_self_registration_managed_clusters(openshift_dyn_client):
|
||||
logger.info("Check ACM self registration for edge site")
|
||||
kubefiles = [os.getenv("KUBECONFIG_EDGE")]
|
||||
err_msg = components.validate_acm_self_registration_managed_clusters(
|
||||
openshift_dyn_client, kubefiles
|
||||
)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Edge site is self registered")
|
||||
|
||||
|
||||
@pytest.mark.validate_argocd_reachable_hub_site
|
||||
def test_validate_argocd_reachable_hub_site(openshift_dyn_client):
|
||||
logger.info("Check if argocd route/url on hub site is reachable")
|
||||
err_msg = components.validate_argocd_reachable(openshift_dyn_client)
|
||||
if err_msg:
|
||||
logger.error(f"FAIL: {err_msg}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: Argocd is reachable")
|
||||
|
||||
|
||||
@pytest.mark.validate_argocd_applications_health_hub_site
|
||||
def test_validate_argocd_applications_health_hub_site(openshift_dyn_client):
|
||||
logger.info("Get all applications deployed by argocd on hub site")
|
||||
projects = ["openshift-gitops", "multicloud-gitops-hub"]
|
||||
unhealthy_apps = application.get_argocd_application_status(
|
||||
openshift_dyn_client, projects
|
||||
)
|
||||
if unhealthy_apps:
|
||||
err_msg = "Some or all applications deployed on hub site are unhealthy"
|
||||
logger.error(f"FAIL: {err_msg}:\n{unhealthy_apps}")
|
||||
assert False, err_msg
|
||||
else:
|
||||
logger.info("PASS: All applications deployed on hub site are healthy.")
|
||||
Reference in New Issue
Block a user