tests: fix potential infinite wait in tests spinning up a container (#7153)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-10-12 13:57:29 +02:00 committed by GitHub
parent 6d1eef039e
commit abab635a01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 52 deletions

View File

@ -17,8 +17,8 @@ TestCase.maxDiff = None
class PytestTestRunner(DiscoverRunner): # pragma: no cover class PytestTestRunner(DiscoverRunner): # pragma: no cover
"""Runs pytest to discover and run tests.""" """Runs pytest to discover and run tests."""
def __init__(self, verbosity=1, failfast=False, keepdb=False, **kwargs): def __init__(self, **kwargs):
super().__init__(verbosity, failfast, keepdb, **kwargs) super().__init__(**kwargs)
self.args = [] self.args = []
if self.failfast: if self.failfast:
@ -47,6 +47,7 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
@classmethod @classmethod
def add_arguments(cls, parser: ArgumentParser): def add_arguments(cls, parser: ArgumentParser):
"""Add more pytest-specific arguments""" """Add more pytest-specific arguments"""
DiscoverRunner.add_arguments(parser)
parser.add_argument( parser.add_argument(
"--randomly-seed", "--randomly-seed",
type=int, type=int,
@ -55,9 +56,6 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
"Default behaviour: use random.Random().getrandbits(32), so the seed is" "Default behaviour: use random.Random().getrandbits(32), so the seed is"
"different on each run.", "different on each run.",
) )
parser.add_argument(
"--keepdb", action="store_true", help="Preserves the test DB between runs."
)
def run_tests(self, test_labels, extra_tests=None, **kwargs): def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""Run pytest and return the exitcode. """Run pytest and return the exitcode.

View File

@ -49,13 +49,8 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
"OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/", "OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/",
}, },
) )
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
self.logger.info("Container failed healthcheck")
sleep(1)
@retry() @retry()
@apply_blueprint( @apply_blueprint(

View File

@ -49,13 +49,8 @@ class TestProviderOAuth2OIDCImplicit(SeleniumTestCase):
"OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/", "OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/",
}, },
) )
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
self.logger.info("Container failed healthcheck")
sleep(1)
@retry() @retry()
@apply_blueprint( @apply_blueprint(

View File

@ -48,13 +48,8 @@ class TestProviderSAML(SeleniumTestCase):
"SP_METADATA_URL": metadata_url, "SP_METADATA_URL": metadata_url,
}, },
) )
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
self.logger.info("Container failed healthcheck")
sleep(1)
@retry() @retry()
@apply_blueprint( @apply_blueprint(

View File

@ -43,7 +43,24 @@ def get_docker_tag() -> str:
return f"gh-{branch_name}" return f"gh-{branch_name}"
class SeleniumTestCase(StaticLiveServerTestCase): class DockerTestCase:
"""Mixin for dealing with containers"""
def wait_for_container(self, container: Container):
"""Check that container is health"""
attempt = 0
while True:
container.reload()
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
sleep(1)
attempt += 1
if attempt >= 30:
self.failureException("Container failed to start")
class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase):
"""StaticLiveServerTestCase which automatically creates a Webdriver instance""" """StaticLiveServerTestCase which automatically creates a Webdriver instance"""
container: Optional[Container] = None container: Optional[Container] = None
@ -82,13 +99,8 @@ class SeleniumTestCase(StaticLiveServerTestCase):
state = container.attrs.get("State", {}) state = container.attrs.get("State", {})
if "Health" not in state: if "Health" not in state:
return container return container
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
self.logger.info("Container failed healthcheck")
sleep(1)
def output_container_logs(self, container: Optional[Container] = None): def output_container_logs(self, container: Optional[Container] = None):
"""Output the container logs to our STDOUT""" """Output the container logs to our STDOUT"""

View File

@ -1,7 +1,6 @@
"""outpost tests""" """outpost tests"""
from shutil import rmtree from shutil import rmtree
from tempfile import mkdtemp from tempfile import mkdtemp
from time import sleep
import yaml import yaml
from channels.testing import ChannelsLiveServerTestCase from channels.testing import ChannelsLiveServerTestCase
@ -20,10 +19,10 @@ from authentik.outposts.models import (
) )
from authentik.outposts.tasks import outpost_connection_discovery from authentik.outposts.tasks import outpost_connection_discovery
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
from tests.e2e.utils import get_docker_tag from tests.e2e.utils import DockerTestCase, get_docker_tag
class OutpostDockerTests(ChannelsLiveServerTestCase): class OutpostDockerTests(DockerTestCase, ChannelsLiveServerTestCase):
"""Test Docker Controllers""" """Test Docker Controllers"""
def _start_container(self, ssl_folder: str) -> Container: def _start_container(self, ssl_folder: str) -> Container:
@ -45,12 +44,8 @@ class OutpostDockerTests(ChannelsLiveServerTestCase):
} }
}, },
) )
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
sleep(1)
def setUp(self): def setUp(self):
super().setUp() super().setUp()

View File

@ -1,7 +1,6 @@
"""outpost tests""" """outpost tests"""
from shutil import rmtree from shutil import rmtree
from tempfile import mkdtemp from tempfile import mkdtemp
from time import sleep
import yaml import yaml
from channels.testing.live import ChannelsLiveServerTestCase from channels.testing.live import ChannelsLiveServerTestCase
@ -20,10 +19,10 @@ from authentik.outposts.models import (
from authentik.outposts.tasks import outpost_connection_discovery from authentik.outposts.tasks import outpost_connection_discovery
from authentik.providers.proxy.controllers.docker import DockerController from authentik.providers.proxy.controllers.docker import DockerController
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
from tests.e2e.utils import get_docker_tag from tests.e2e.utils import DockerTestCase, get_docker_tag
class TestProxyDocker(ChannelsLiveServerTestCase): class TestProxyDocker(DockerTestCase, ChannelsLiveServerTestCase):
"""Test Docker Controllers""" """Test Docker Controllers"""
def _start_container(self, ssl_folder: str) -> Container: def _start_container(self, ssl_folder: str) -> Container:
@ -45,12 +44,8 @@ class TestProxyDocker(ChannelsLiveServerTestCase):
} }
}, },
) )
while True: self.wait_for_container(container)
container.reload() return container
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
sleep(1)
def setUp(self): def setUp(self):
super().setUp() super().setUp()