diff --git a/.github/workflows/jsonschema.yaml b/.github/workflows/jsonschema.yaml index 04aade4da..264d0246a 100644 --- a/.github/workflows/jsonschema.yaml +++ b/.github/workflows/jsonschema.yaml @@ -20,7 +20,7 @@ jobs: persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} diff --git a/Makefile b/Makefile index b6b36c353..f0861ae5a 100644 --- a/Makefile +++ b/Makefile @@ -3,3 +3,8 @@ # You can add custom targets above or below the include line include Makefile-common + +CLUSTERGROUP_LABEL ?= group-one +.PHONY: import-default-spoke +import-default-spoke: ## Import the default spoke cluster for this pattern, set VP_SPOKECONFIG and VP_HUBCONFIG env vars + @$(ANSIBLE_RUN) -e clustergroup_label=$(CLUSTERGROUP_LABEL) rhvp.cluster_utils.import_spoke_cluster diff --git a/Makefile-common b/Makefile-common index 79bcf801f..36cae531c 100644 --- a/Makefile-common +++ b/Makefile-common @@ -52,3 +52,7 @@ validate-schema: ## validates values files against schema in common/clustergroup .PHONY: argo-healthcheck argo-healthcheck: ## Checks if all argo applications are synced @$(ANSIBLE_RUN) rhvp.cluster_utils.argo_healthcheck + +.PHONY: run-ci-tests +run-ci-tests: ## To run ci-tests, set any needed env vars + @$(ANSIBLE_RUN) rhvp.cluster_utils.run_ci_tests diff --git a/pattern.sh b/pattern.sh index 85c99052e..b2172fd4f 100755 --- a/pattern.sh +++ b/pattern.sh @@ -9,6 +9,19 @@ function version { echo "$1" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' } +# We need this check mostly for CI testing, we do not want to run container in container +function is_container() { + [ -n "${KUBERNETES_SERVICE_HOST:-}" ] && return 0 + [ -f /.dockerenv ] && return 0 + [ -f /run/.containerenv ] && return 0 + return 1 +} + +if is_container; then + echo "Already running in a container" + exec "$@" +fi + if [ -z "${PATTERN_UTILITY_CONTAINER:-}" ]; then PATTERN_UTILITY_CONTAINER="quay.io/validatedpatterns/utility-container" fi @@ -115,6 +128,7 @@ podman run -it --rm --pull=newer \ -e TOKEN_SECRET \ -e UUID_FILE \ -e VALUES_SECRET \ + -e 'VP_*' \ "${PKI_HOST_MOUNT_ARGS[@]}" \ -v "$(pwd -P)":"$(pwd -P)" \ -v "${HOME}":"${HOME}" \ diff --git a/tests/ci/README.md b/tests/ci/README.md new file mode 100644 index 000000000..c62c7fc07 --- /dev/null +++ b/tests/ci/README.md @@ -0,0 +1,42 @@ +# CI Tests + +The requirements.txt file is just a placeholder to show the installed packages in the utility container: +[utility-container requirements.txt](https://github.com/validatedpatterns/utility-container/blob/main/requirements.txt) + +## The ci will run pytest based on file pattern + +pytest -lv test\_\.py --junit-xml .results/test\_\.xml + +## To run upstream tests locally + +Set the env variables pointing to the clusters needed to run the tests on:\ +`VP_HUBCONFIG` (`VP_SPOKECONFIG` if applicable) pointing to the kubconfig of hub (and spoke) clusters\ +(all VP\_\* env var will be available inside the container)\ +`TARGET_CLUSTERGROUP` if its different from the default (values-global.yaml main.clusterGroupName)\ +Test logs and junit-xml will be saved in ci/.results/\ +Run from root repository: + +```bash +./pattern.sh make run-ci-tests +``` + +## Writing additional tests + +The openshift_dyn_client fixture will return a DynamicClient which can be used inside test functions.\ +It requires only an env variable param to use it as a kubeconfig. + +```python +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +``` + +If your tests requires additional python packages, you might want to either run them fully locally in a venv or similar.\ +Or if you want to use the pattern framework (make/Ansible wrappers) you need to use your own util container + +```bash +PATTERN_UTILITY_CONTAINER="your_utility container" ./pattern.sh make run-ci-tests + +``` diff --git a/tests/ci/__init__.py b/tests/ci/__init__.py new file mode 100644 index 000000000..3dc1f76bc --- /dev/null +++ b/tests/ci/__init__.py @@ -0,0 +1 @@ +__version__ = "0.1.0" diff --git a/tests/ci/conftest.py b/tests/ci/conftest.py new file mode 100644 index 000000000..12cc3c06c --- /dev/null +++ b/tests/ci/conftest.py @@ -0,0 +1 @@ +from validatedpatterns_tests.interop.conftest_openshift import * # noqa: F401,F403 diff --git a/tests/ci/requirements.txt b/tests/ci/requirements.txt new file mode 100644 index 000000000..0a68e1e28 --- /dev/null +++ b/tests/ci/requirements.txt @@ -0,0 +1,15 @@ +ansible-core==2.18.* +ansible-runner +awxkit +kubernetes +openshift +boto3>=1.21 +botocore>=1.24 +awscli>=1.22 +azure-cli>=2.34 +gcloud +humanize +pytz +pytest +junitparser +vp-qe-test-common @ git+https://github.com/validatedpatterns/vp-qe-test-common.git@v1 \ No newline at end of file diff --git a/tests/ci/test_hub.py b/tests/ci/test_hub.py new file mode 100644 index 000000000..36c80bb4a --- /dev/null +++ b/tests/ci/test_hub.py @@ -0,0 +1,106 @@ +import pytest +from validatedpatterns_tests.interop import application, components, subscription + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_subscription_status_hub(openshift_dyn_client): + expected_subs = { + "openshift-gitops-operator": ["openshift-gitops-operator"], + "advanced-cluster-management": ["open-cluster-management"], + "multicluster-engine": ["multicluster-engine"], + } + subscription.assert_subscription_status(openshift_dyn_client, expected_subs) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_SPOKECONFIG"], + indirect=True, +) +def test_subscription_status_spoke(openshift_dyn_client): + expected_subs = { + "openshift-gitops-operator": ["openshift-gitops-operator"], + } + + subscription.assert_subscription_status(openshift_dyn_client, expected_subs) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG", "VP_SPOKECONFIG"], + indirect=True, +) +def test_site_reachable(openshift_dyn_client): + + components.assert_site_reachable(openshift_dyn_client) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_pod_status_hub(openshift_dyn_client): + projects = [ + "patterns-operator", + "open-cluster-management", + "open-cluster-management-hub", + "vp-gitops", + "vault", + "hello-world", + "config-demo", + "external-secrets", + ] + + components.assert_pod_status(openshift_dyn_client, projects, skip_check=[]) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_SPOKECONFIG"], + indirect=True, +) +def test_pod_status_spoke(openshift_dyn_client): + projects = [ + "open-cluster-management-agent", + "open-cluster-management-agent-addon", + "vp-gitops", + "hello-world", + "config-demo", + "external-secrets", + ] + + components.assert_pod_status(openshift_dyn_client, projects, skip_check=[]) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_managed_clusters(openshift_dyn_client): + components.assert_managed_clusters(openshift_dyn_client, ["group-one"]) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG", "VP_SPOKECONFIG"], + indirect=True, +) +def test_argocd_reachable(openshift_dyn_client): + components.assert_argocd_reachable(openshift_dyn_client) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG", "VP_SPOKECONFIG"], + indirect=True, +) +def test_argocd_applications_health(openshift_dyn_client): + projects = ["vp-gitops", "multicloud-gitops-hub"] + + application.assert_argocd_applications(openshift_dyn_client, projects) diff --git a/tests/ci/test_standalone.py b/tests/ci/test_standalone.py new file mode 100644 index 000000000..aea8772f7 --- /dev/null +++ b/tests/ci/test_standalone.py @@ -0,0 +1,51 @@ +import pytest +from validatedpatterns_tests.interop import components, subscription + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_subscription_status_standalone(openshift_dyn_client): + expected_subs = { + "openshift-gitops-operator": ["openshift-gitops-operator"], + } + + subscription.assert_subscription_status(openshift_dyn_client, expected_subs) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_site_reachable_hub(openshift_dyn_client): + components.assert_site_reachable(openshift_dyn_client) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_argocd_reachable_standalone(openshift_dyn_client): + components.assert_argocd_reachable(openshift_dyn_client) + + +@pytest.mark.parametrize( + "openshift_dyn_client", + ["VP_HUBCONFIG"], + indirect=True, +) +def test_pod_status_standalone(openshift_dyn_client): + projects = [ + "patterns-operator", + "vp-gitops", + "vault", + "hello-world", + "config-demo", + "external-secrets", + # "non-existing" + ] + components.assert_pod_status(openshift_dyn_client, projects, skip_check=[]) diff --git a/values-global.yaml b/values-global.yaml index 41545ed9e..04b831331 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -7,7 +7,7 @@ global: syncPolicy: Automatic installPlanApproval: Automatic main: - clusterGroupName: hub + variant: hub multiSourceConfig: enabled: true clusterGroupChartVersion: "0.9.*" diff --git a/values-group-one.yaml b/variants/hub/values-group-one.yaml similarity index 100% rename from values-group-one.yaml rename to variants/hub/values-group-one.yaml diff --git a/values-hub.yaml b/variants/hub/values-hub.yaml similarity index 100% rename from values-hub.yaml rename to variants/hub/values-hub.yaml diff --git a/values-standalone.yaml b/variants/standalone/values-standalone.yaml similarity index 100% rename from values-standalone.yaml rename to variants/standalone/values-standalone.yaml