Squashed 'acm-hub-bootstrap/' content from commit 4b79b1a0

git-subtree-dir: acm-hub-bootstrap
git-subtree-split: 4b79b1a0be6da2a9efc9ace8871b4762342da70b
This commit is contained in:
2025-04-14 23:43:59 -05:00
commit 939177be6b
80 changed files with 3126 additions and 0 deletions

25
tests/interop/README.md Normal file
View 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

View File

@@ -0,0 +1,2 @@
__version__ = "0.1.0"
__loggername__ = "css_logger"

View 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

View 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)

View 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
View 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

View 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")

View 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")

View 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")

View 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.")

View 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.")