Skip to content

Commit 5e348d5

Browse files
Some fixes for integration tests (#441)
1 parent 7f693e2 commit 5e348d5

File tree

8 files changed

+36
-21
lines changed

8 files changed

+36
-21
lines changed

github-runner-manager/src/github_runner_manager/templates/openstack-userdata.sh.j2

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ hostnamectl set-hostname github-runner
77
# Write .env contents
88
su - ubuntu -c 'cd ~/actions-runner && echo "{{ env_contents }}" > .env'
99

10+
snap refresh --hold=24h
11+
snap watch --last=auto-refresh?
12+
1013
{% if aproxy_address %}
1114
snap install aproxy --edge
1215
snap set aproxy proxy={{ aproxy_address }} listen=:54969

src/charm.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class ReconcileRunnersEvent(EventBase):
110110

111111

112112
def catch_charm_errors(
113-
func: Callable[["GithubRunnerCharm", EventT], None]
113+
func: Callable[["GithubRunnerCharm", EventT], None],
114114
) -> Callable[["GithubRunnerCharm", EventT], None]:
115115
"""Catch common errors in charm.
116116
@@ -145,7 +145,7 @@ def func_with_catch_errors(self: "GithubRunnerCharm", event: EventT) -> None:
145145

146146

147147
def catch_action_errors(
148-
func: Callable[["GithubRunnerCharm", ActionEvent], None]
148+
func: Callable[["GithubRunnerCharm", ActionEvent], None],
149149
) -> Callable[["GithubRunnerCharm", ActionEvent], None]:
150150
"""Catch common errors in actions.
151151
@@ -339,22 +339,26 @@ def _on_config_changed(self, _: ConfigChangedEvent) -> None:
339339
state = self._setup_state()
340340
self._set_reconcile_timer()
341341

342+
flush_and_reconcile = False
342343
if state.charm_config.token != self._stored.token:
343-
self._stored.token = None
344+
self._stored.token = self.config[TOKEN_CONFIG_NAME]
345+
flush_and_reconcile = True
344346
if self.config[PATH_CONFIG_NAME] != self._stored.path:
345347
self._stored.path = self.config[PATH_CONFIG_NAME]
348+
flush_and_reconcile = True
346349
if self.config[LABELS_CONFIG_NAME] != self._stored.labels:
347350
self._stored.labels = self.config[LABELS_CONFIG_NAME]
351+
flush_and_reconcile = True
348352

349353
state = self._setup_state()
350354

351355
if not self._get_set_image_ready_status():
352356
return
353-
if state.charm_config.token != self._stored.token:
357+
if flush_and_reconcile:
358+
logger.info("Flush and reconcile on config-changed")
354359
runner_scaler = self._get_runner_scaler(state)
355360
runner_scaler.flush(flush_mode=FlushMode.FLUSH_IDLE)
356361
self._reconcile_openstack_runners(runner_scaler, state.runner_config.virtual_machines)
357-
# TODO: 2024-04-12: Flush on token changes.
358362

359363
@catch_charm_errors
360364
def _on_reconcile_runners(self, _: ReconcileRunnersEvent) -> None:
@@ -518,16 +522,14 @@ def _apt_install(self, packages: Sequence[str]) -> None:
518522
@catch_charm_errors
519523
def _on_debug_ssh_relation_changed(self, _: ops.RelationChangedEvent) -> None:
520524
"""Handle debug ssh relation changed event."""
525+
self.unit.status = MaintenanceStatus("Added debug-ssh relation")
521526
state = self._setup_state()
522527

523528
if not self._get_set_image_ready_status():
524529
return
525530
runner_scaler = self._get_runner_scaler(state)
526531
runner_scaler.flush()
527-
try:
528-
runner_scaler.reconcile(state.runner_config.virtual_machines)
529-
except ReconcileError:
530-
logger.exception(FAILED_TO_RECONCILE_RUNNERS_MSG)
532+
self._reconcile_openstack_runners(runner_scaler, state.runner_config.virtual_machines)
531533

532534
@catch_charm_errors
533535
def _on_image_relation_joined(self, _: ops.RelationJoinedEvent) -> None:

tests/integration/conftest.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
from tests.integration.helpers.openstack import OpenStackInstanceHelper, PrivateEndpointConfigs
4646
from tests.status_name import ACTIVE
4747

48-
IMAGE_BUILDER_DEPLOY_TIMEOUT_IN_SECONDS = 30 * 60
48+
IMAGE_BUILDER_DEPLOY_TIMEOUT_IN_SECONDS = 20 * 60
4949

5050
# The following line is required because we are using request.getfixturevalue in conjunction
5151
# with pytest-asyncio. See https://github.com/pytest-dev/pytest-asyncio/issues/112
@@ -317,7 +317,7 @@ async def app_no_runner(
317317
) -> AsyncIterator[Application]:
318318
"""Application with no runner."""
319319
await basic_app.set_config({VIRTUAL_MACHINES_CONFIG_NAME: "0"})
320-
await model.wait_for_idle(apps=[basic_app.name], status=ACTIVE, timeout=90 * 60)
320+
await model.wait_for_idle(apps=[basic_app.name], status=ACTIVE, timeout=20 * 60)
321321
yield basic_app
322322

323323

@@ -339,7 +339,10 @@ async def image_builder_fixture(
339339
config={
340340
"app-channel": "edge",
341341
"build-interval": "12",
342-
"revision-history-limit": "5",
342+
# There are several tests running simulteously, all with the same images.
343+
# Until we update the image-builder to create different names for the images,
344+
# the history limit should be big enough so that tests do not interfere.
345+
"revision-history-limit": "15",
343346
"openstack-auth-url": private_endpoint_config["auth_url"],
344347
# Bandit thinks this is a hardcoded password
345348
"openstack-password": private_endpoint_config["password"], # nosec: B105
@@ -401,7 +404,9 @@ async def app_openstack_runner_fixture(
401404
wait_idle=False,
402405
)
403406
await model.integrate(f"{image_builder.name}:image", f"{application.name}:image")
404-
await model.wait_for_idle(apps=[application.name], status=ACTIVE, timeout=90 * 60)
407+
await model.wait_for_idle(
408+
apps=[application.name, image_builder.name], status=ACTIVE, timeout=20 * 60
409+
)
405410

406411
return application
407412

@@ -415,7 +420,7 @@ async def app_scheduled_events_fixture(
415420
application = app_openstack_runner
416421
await application.set_config({"reconcile-interval": "8"})
417422
await application.set_config({VIRTUAL_MACHINES_CONFIG_NAME: "1"})
418-
await model.wait_for_idle(apps=[application.name], status=ACTIVE, timeout=90 * 60)
423+
await model.wait_for_idle(apps=[application.name], status=ACTIVE, timeout=20 * 60)
419424
await reconcile(app=application, model=model)
420425
return application
421426

tests/integration/helpers/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ async def deploy_github_runner_charm(
156156
)
157157

158158
if wait_idle:
159-
await model.wait_for_idle(status=ACTIVE, timeout=60 * 40)
159+
await model.wait_for_idle(status=ACTIVE, timeout=60 * 20)
160160

161161
return application
162162

tests/integration/test_charm_upgrade.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ async def test_charm_upgrade(
9191
)
9292
await model.integrate(f"{image_builder.name}:image", f"{application.name}:image")
9393
await model.wait_for_idle(
94-
apps=[application.name],
94+
apps=[application.name, image_builder.name],
9595
raise_on_error=False,
9696
wait_for_active=True,
97-
timeout=180 * 60,
97+
timeout=20 * 60,
9898
check_freq=30,
9999
)
100100
origin = client.CharmOrigin(
@@ -125,6 +125,6 @@ async def test_charm_upgrade(
125125
apps=[application.name],
126126
raise_on_error=False,
127127
wait_for_active=True,
128-
timeout=180 * 60,
128+
timeout=20 * 60,
129129
check_freq=30,
130130
)

tests/integration/test_debug_ssh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async def test_ssh_debug(
3434
act: when canonical/action-tmate is triggered.
3535
assert: the ssh connection info from action-log and tmate-ssh-server matches.
3636
"""
37-
await model.wait_for_idle(status=ACTIVE, timeout=60 * 120)
37+
await model.wait_for_idle(status=ACTIVE, timeout=60 * 20)
3838

3939
unit = app_no_wait_tmate.units[0]
4040
# We need the runner to connect to the current machine, instead of the tmate_ssh_server unit,

tests/integration/test_reactive.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ async def _runner_installed_in_metrics_log() -> bool:
117117
return "runner_installed" in events
118118

119119
try:
120-
await wait_for(_runner_installed_in_metrics_log, check_interval=30, timeout=600)
120+
await wait_for(_runner_installed_in_metrics_log, check_interval=30, timeout=60 * 10)
121121
except TimeoutError:
122122
assert False, "runner_installed event has not been logged"
123123

tests/integration/test_runner_manager_openstack.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
RunnerManagerConfig,
3232
)
3333
from github_runner_manager.metrics import events
34-
from github_runner_manager.openstack_cloud import health_checks
34+
from github_runner_manager.openstack_cloud import constants, health_checks
3535
from github_runner_manager.openstack_cloud.openstack_runner_manager import (
3636
OpenStackCredentials,
3737
OpenStackRunnerManager,
@@ -51,6 +51,11 @@
5151

5252
logger = logging.getLogger(__name__)
5353

54+
# A higher create server timeout is reasonable for integration tests,
55+
# as only one machine that stays for more than the default time in BUILD,
56+
# will break the tests
57+
constants.CREATE_SERVER_TIMEOUT = 900
58+
5459

5560
@pytest.fixture(scope="module", name="runner_label")
5661
def runner_label():

0 commit comments

Comments
 (0)