You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pcs/SOURCES/fix-tests-for-missing-webui...

445 lines
16 KiB

From 525b102bd053a6653dff663845c98683fa78bbab Mon Sep 17 00:00:00 2001
From: Ivan Devat <idevat@redhat.com>
Date: Mon, 24 Jun 2024 17:19:58 +0200
Subject: [PATCH] fix tests for missing webui
---
pcs_test/Makefile.am | 1 +
pcs_test/smoke.sh.in | 23 ++++++--
pcs_test/tier0/daemon/app/fixtures_app.py | 53 +++----------------
.../tier0/daemon/app/fixtures_app_webui.py | 28 ++++++++++
pcs_test/tier0/daemon/app/test_app_gui.py | 37 ++++++++++---
pcs_test/tier0/daemon/app/test_app_spa.py | 26 +++++++--
pcs_test/tier0/daemon/test_env.py | 6 ++-
pcs_test/tier0/daemon/test_session.py | 25 ++++++---
pcs_test/tools/misc.py | 9 ++++
9 files changed, 138 insertions(+), 70 deletions(-)
create mode 100644 pcs_test/tier0/daemon/app/fixtures_app_webui.py
diff --git a/pcs_test/Makefile.am b/pcs_test/Makefile.am
index 4e71fcda..6c5932b3 100644
--- a/pcs_test/Makefile.am
+++ b/pcs_test/Makefile.am
@@ -134,6 +134,7 @@ EXTRA_DIST = \
tier0/common/test_tools.py \
tier0/common/test_tools_xml_fromstring.py \
tier0/daemon/app/fixtures_app.py \
+ tier0/daemon/app/fixtures_app_webui.py \
tier0/daemon/app/__init__.py \
tier0/daemon/app/test_api_v0.py \
tier0/daemon/app/test_api_v1.py \
diff --git a/pcs_test/smoke.sh.in b/pcs_test/smoke.sh.in
index a4b3ac71..37eac345 100755
--- a/pcs_test/smoke.sh.in
+++ b/pcs_test/smoke.sh.in
@@ -66,10 +66,25 @@ cat <<EOF > ${pcsd_settings_conf_path}
EOF
cat ${pcsd_settings_conf_path}
pcs cluster start --all --wait
-curl --insecure --data "username=${cluster_user}&password=${cluster_user_password}" --cookie-jar ${cookie_file} https://localhost:2224/ui/login
-curl --insecure --cookie ${cookie_file} --header "X-Requested-With: XMLHttpRequest" --data "hidden[hidden_input]=&config[stonith-enabled]=false" https://localhost:2224/managec/${cluster_name}/update_cluster_settings > "${output_file}"
-cat "${output_file}"; echo ""
-[ "$(cat ${output_file})" = "Update Successful" ]
+
+webui_http_code_response=$(
+ curl --insecure --silent --output /dev/null --write-out "%{http_code}" \
+ https://localhost:2224/ui/
+)
+if [ "$webui_http_code_response" = "200" ]; then
+ # Webui backend check
+ curl --insecure --data "username=${cluster_user}&password=${cluster_user_password}" --cookie-jar ${cookie_file} https://localhost:2224/ui/login
+ curl --insecure --cookie ${cookie_file} --header "X-Requested-With: XMLHttpRequest" --data "hidden[hidden_input]=&config[stonith-enabled]=false" https://localhost:2224/managec/${cluster_name}/update_cluster_settings > "${output_file}"
+ cat "${output_file}"; echo ""
+ [ "$(cat ${output_file})" = "Update Successful" ]
+elif [ "$webui_http_code_response" = "401" ]; then
+ curl --insecure https://localhost:2224/ui/ > "${output_file}"
+ cat "${output_file}"; echo ""
+ [ "$(cat "${output_file}")" = '{"notauthorized":"true"}' ]
+else
+ echo "Unexpected response from https://localhost:2224/ui/ - http code: '${webui_http_code_response}'"
+ exit 1
+fi
# Sanity check of API V1
curl -kb "token=${token}" https://localhost:2224/api/v1/resource-agent-get-agents-list/v1 --data '{}' > "${output_file}"
diff --git a/pcs_test/tier0/daemon/app/fixtures_app.py b/pcs_test/tier0/daemon/app/fixtures_app.py
index 3c0d6a4f..56acf473 100644
--- a/pcs_test/tier0/daemon/app/fixtures_app.py
+++ b/pcs_test/tier0/daemon/app/fixtures_app.py
@@ -1,16 +1,11 @@
from pprint import pformat
from urllib.parse import urlencode
-from tornado.httputil import (
- HTTPHeaders,
- parse_cookie,
-)
+from tornado.httputil import HTTPHeaders
from tornado.testing import AsyncHTTPTestCase
from tornado.web import Application
from pcs.daemon import ruby_pcsd
-from pcs.daemon.app.webui import session
-from pcs.daemon.app.webui.auth import PCSD_SESSION
USER = "user"
GROUPS = ["group1", "group2"]
@@ -56,6 +51,13 @@ class AppTest(AsyncHTTPTestCase):
def fetch(self, path, raise_error=False, **kwargs):
if "follow_redirects" not in kwargs:
kwargs["follow_redirects"] = False
+
+ if "is_ajax" in kwargs:
+ if "headers" not in kwargs:
+ kwargs["headers"] = {}
+ kwargs["headers"]["X-Requested-With"] = "XMLHttpRequest"
+ del kwargs["is_ajax"]
+
response = super().fetch(path, raise_error=raise_error, **kwargs)
# "Strict-Transport-Security" header is expected in every response
self.assertTrue(
@@ -91,45 +93,6 @@ class AppTest(AsyncHTTPTestCase):
self.assert_headers_contains(response.headers, self.wrapper.headers)
self.assertEqual(response.body, self.wrapper.body)
-
-class AppUiTestMixin(AppTest):
- def setUp(self):
- self.session_storage = session.Storage(lifetime_seconds=10)
- super().setUp()
-
- def assert_session_in_response(self, response, sid=None):
- self.assertTrue("Set-Cookie" in response.headers)
- cookie = parse_cookie(response.headers["Set-Cookie"])
- self.assertTrue(PCSD_SESSION, cookie)
- if sid:
- self.assertEqual(cookie[PCSD_SESSION], sid)
- return cookie[PCSD_SESSION]
-
- def fetch(self, path, raise_error=False, **kwargs):
- if "sid" in kwargs:
- if "headers" not in kwargs:
- kwargs["headers"] = {}
- kwargs["headers"]["Cookie"] = f"{PCSD_SESSION}={kwargs['sid']}"
- del kwargs["sid"]
-
- if "is_ajax" in kwargs:
- if "headers" not in kwargs:
- kwargs["headers"] = {}
- kwargs["headers"]["X-Requested-With"] = "XMLHttpRequest"
- del kwargs["is_ajax"]
-
- if "follow_redirects" not in kwargs:
- kwargs["follow_redirects"] = False
-
- return super().fetch(path, raise_error=raise_error, **kwargs)
-
- def create_login_session(self):
- return self.session_storage.login(USER)
-
- def assert_success_response(self, response, expected_body):
- self.assertEqual(response.code, 200)
- self.assertEqual(response.body.decode(), expected_body)
-
def assert_unauth_ajax(self, response):
self.assertEqual(response.code, 401)
self.assertEqual(response.body, b'{"notauthorized":"true"}')
diff --git a/pcs_test/tier0/daemon/app/fixtures_app_webui.py b/pcs_test/tier0/daemon/app/fixtures_app_webui.py
new file mode 100644
index 00000000..e38ca3e7
--- /dev/null
+++ b/pcs_test/tier0/daemon/app/fixtures_app_webui.py
@@ -0,0 +1,28 @@
+try:
+ from pcs.daemon.app import webui
+except ImportError:
+ # You need to skip tests in tests that uses AppTest in the case webui
+ # is not there.
+ webui = None
+
+from pcs_test.tier0.daemon.app import fixtures_app
+
+
+class AppTest(fixtures_app.AppTest):
+ def setUp(self):
+ self.session_storage = webui.session.Storage(lifetime_seconds=10)
+ super().setUp()
+
+ def fetch(self, path, raise_error=False, **kwargs):
+ if "sid" in kwargs:
+ if "headers" not in kwargs:
+ kwargs["headers"] = {}
+ kwargs["headers"][
+ "Cookie"
+ ] = f"{webui.auth.PCSD_SESSION}={kwargs['sid']}"
+ del kwargs["sid"]
+
+ return super().fetch(path, raise_error=raise_error, **kwargs)
+
+ def create_login_session(self):
+ return self.session_storage.login(fixtures_app.USER)
diff --git a/pcs_test/tier0/daemon/app/test_app_gui.py b/pcs_test/tier0/daemon/app/test_app_gui.py
index b3446fdb..2317eea5 100644
--- a/pcs_test/tier0/daemon/app/test_app_gui.py
+++ b/pcs_test/tier0/daemon/app/test_app_gui.py
@@ -1,14 +1,24 @@
import logging
from unittest import mock
+from tornado.httputil import parse_cookie
+
from pcs.daemon import ruby_pcsd
from pcs.daemon.app import sinatra_ui
from pcs.daemon.app.auth import UnixSocketAuthProvider
-from pcs.daemon.app.webui import sinatra_ui as sinatra_ui_webui
+
+try:
+ from pcs.daemon.app import webui
+except ImportError:
+ webui = None
from pcs.lib.auth.provider import AuthProvider
from pcs.lib.auth.types import AuthUser
-from pcs_test.tier0.daemon.app import fixtures_app
+from pcs_test.tier0.daemon.app import (
+ fixtures_app,
+ fixtures_app_webui,
+)
+from pcs_test.tools.misc import skip_unless_webui_installed
# Don't write errors to test output.
logging.getLogger("tornado.access").setLevel(logging.CRITICAL)
@@ -33,21 +43,28 @@ def patch_get_unix_socket_user(user):
auth_provider = AuthProvider(logging.getLogger("test logger"))
-class AppTest(fixtures_app.AppUiTestMixin):
+@skip_unless_webui_installed()
+@patch_login_user()
+class SinatraAjaxProtectedSession(fixtures_app_webui.AppTest):
def setUp(self):
self.wrapper = fixtures_app.RubyPcsdWrapper(ruby_pcsd.SINATRA)
super().setUp()
-
-@patch_login_user()
-class SinatraAjaxProtectedSession(AppTest):
def get_routes(self):
- return sinatra_ui_webui.get_routes(
+ return webui.sinatra_ui.get_routes(
self.session_storage,
auth_provider,
self.wrapper,
)
+ def assert_session_in_response(self, response, sid=None):
+ self.assertTrue("Set-Cookie" in response.headers)
+ cookie = parse_cookie(response.headers["Set-Cookie"])
+ self.assertTrue(webui.auth.PCSD_SESSION, cookie)
+ if sid:
+ self.assertEqual(cookie[webui.auth.PCSD_SESSION], sid)
+ return cookie[webui.auth.PCSD_SESSION]
+
def test_deal_without_authentication(self):
self.assert_unauth_ajax(self.get("/some-ajax", is_ajax=True))
@@ -63,7 +80,11 @@ class SinatraAjaxProtectedSession(AppTest):
@patch_login_user()
-class SinatraAjaxProtectedUnixSocket(AppTest):
+class SinatraAjaxProtectedUnixSocket(fixtures_app.AppTest):
+ def setUp(self):
+ self.wrapper = fixtures_app.RubyPcsdWrapper(ruby_pcsd.SINATRA)
+ super().setUp()
+
def get_routes(self):
return sinatra_ui.get_routes(auth_provider, self.wrapper)
diff --git a/pcs_test/tier0/daemon/app/test_app_spa.py b/pcs_test/tier0/daemon/app/test_app_spa.py
index 89a5ab0e..6acf3c7d 100644
--- a/pcs_test/tier0/daemon/app/test_app_spa.py
+++ b/pcs_test/tier0/daemon/app/test_app_spa.py
@@ -2,12 +2,22 @@ import logging
import os
from unittest import mock
-from pcs.daemon.app import webui
+try:
+ from pcs.daemon.app import webui
+except ImportError:
+ webui = None
+
from pcs.lib.auth.provider import AuthProvider
from pcs.lib.auth.types import AuthUser
-from pcs_test.tier0.daemon.app import fixtures_app
-from pcs_test.tools.misc import get_tmp_dir
+from pcs_test.tier0.daemon.app import (
+ fixtures_app,
+ fixtures_app_webui,
+)
+from pcs_test.tools.misc import (
+ get_tmp_dir,
+ skip_unless_webui_installed,
+)
LOGIN_BODY = {"username": fixtures_app.USER, "password": fixtures_app.PASSWORD}
PREFIX = "/ui/"
@@ -16,7 +26,7 @@ PREFIX = "/ui/"
logging.getLogger("tornado.access").setLevel(logging.CRITICAL)
-class AppTest(fixtures_app.AppUiTestMixin):
+class AppTest(fixtures_app_webui.AppTest):
def setUp(self):
self.public_dir = get_tmp_dir("tier0_daemon_app_spa")
self.spa_dir_path = os.path.join(self.public_dir.name, "ui")
@@ -41,7 +51,12 @@ class AppTest(fixtures_app.AppUiTestMixin):
auth_provider=AuthProvider(logging.Logger("test logger")),
)
+ def assert_success_response(self, response, expected_body):
+ self.assertEqual(response.code, 200)
+ self.assertEqual(response.body.decode(), expected_body)
+
+@skip_unless_webui_installed()
class Static(AppTest):
def test_index(self):
self.assert_success_response(
@@ -50,6 +65,7 @@ class Static(AppTest):
)
+@skip_unless_webui_installed()
class Fallback(AppTest):
def setUp(self):
super().setUp()
@@ -65,6 +81,7 @@ class Fallback(AppTest):
)
+@skip_unless_webui_installed()
class Login(AppTest):
def setUp(self):
super().setUp()
@@ -94,6 +111,7 @@ class Login(AppTest):
)
+@skip_unless_webui_installed()
class Logout(AppTest):
def test_can_logout(self):
session1 = self.create_login_session()
diff --git a/pcs_test/tier0/daemon/test_env.py b/pcs_test/tier0/daemon/test_env.py
index 40f0c402..0eff3660 100644
--- a/pcs_test/tier0/daemon/test_env.py
+++ b/pcs_test/tier0/daemon/test_env.py
@@ -8,7 +8,10 @@ from unittest import (
from pcs import settings
from pcs.daemon import env
-from pcs_test.tools.misc import create_setup_patch_mixin
+from pcs_test.tools.misc import (
+ create_setup_patch_mixin,
+ skip_unless_webui_installed,
+)
def webui_fallback(public_dir):
@@ -177,6 +180,7 @@ class Prepare(TestCase, create_setup_patch_mixin(env)):
{env.PCSD_DEBUG: "false"}
)
+ @skip_unless_webui_installed()
def test_errors_on_missing_paths(self):
self.path_exists.return_value = False
self.assert_environ_produces_modified_pcsd_env(
diff --git a/pcs_test/tier0/daemon/test_session.py b/pcs_test/tier0/daemon/test_session.py
index a893c01d..e8eff4cd 100644
--- a/pcs_test/tier0/daemon/test_session.py
+++ b/pcs_test/tier0/daemon/test_session.py
@@ -1,23 +1,31 @@
from contextlib import contextmanager
from unittest import TestCase
-from pcs.daemon.app.webui import session
-from pcs.daemon.app.webui.session import Session
+try:
+ from pcs.daemon.app import webui
+except ImportError:
+ webui = None
-from pcs_test.tools.misc import create_setup_patch_mixin
+from pcs_test.tools.misc import (
+ create_setup_patch_mixin,
+ skip_unless_webui_installed,
+)
SID = "abc"
USER = "user"
GROUPS = ["group1", "group2"]
-PatchSessionMixin = create_setup_patch_mixin(session)
+# If webui is None, the tests in this file using these mixins are skipped,
+# passing a dummy object instead to make this executable
+PatchSessionMixin = create_setup_patch_mixin(webui) if webui else object
+@skip_unless_webui_installed()
class SessionTest(TestCase, PatchSessionMixin):
def setUp(self):
- self.now = self.setup_patch("now", return_value=0)
- self.session = Session(SID, USER)
+ self.now = self.setup_patch("session.now", return_value=0)
+ self.session = webui.session.Session(SID, USER)
def test_session_grows_older(self):
self.now.return_value = 10.1
@@ -42,10 +50,11 @@ class SessionTest(TestCase, PatchSessionMixin):
session1.sid
+@skip_unless_webui_installed()
class StorageTest(TestCase, PatchSessionMixin):
def setUp(self):
- self.now = self.setup_patch("now", return_value=0)
- self.storage = session.Storage(lifetime_seconds=10)
+ self.now = self.setup_patch("session.now", return_value=0)
+ self.storage = webui.session.Storage(lifetime_seconds=10)
def test_does_not_accept_foreign_sid(self):
self.assertIsNone(self.storage.get("unknown_sid"))
diff --git a/pcs_test/tools/misc.py b/pcs_test/tools/misc.py
index 28e03411..7a048a4d 100644
--- a/pcs_test/tools/misc.py
+++ b/pcs_test/tools/misc.py
@@ -15,6 +15,11 @@ from pcs.cli.common.parse_args import InputModifiers
from pcs.common import str_tools
from pcs.lib.external import CommandRunner
+try:
+ from pcs.daemon.app import webui
+except ImportError:
+ webui = None # type: ignore
+
from pcs_test import TEST_ROOT
from pcs_test import settings as tests_settings
from pcs_test.tools.custom_mock import MockLibraryReportProcessor
@@ -292,6 +297,10 @@ def skip_unless_booth_resource_agent_installed():
)
+def skip_unless_webui_installed():
+ return skipUnless(webui, "test requires webui which is not installed")
+
+
def create_patcher(target_prefix_or_module):
"""
Return function for patching tests with preconfigured target prefix
--
2.45.2