Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS-7092: Add server upgrade test #33

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
- integration-scaling
- integration-upgrades
- integration-auth
- integration-server-upgrade
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
15 changes: 13 additions & 2 deletions documentation/how-to/upgrade-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ The Temporal K8s charms facilitate server upgrades in the following way:
This will ensure that your database schema is updated if any updates are
available.

2. The Temporal K8s charm should be updated to the next charm revision
that you currently have deployed as follows:
2. The Temporal K8s charm should be updated to the next charm revision that you
currently have deployed as follows:

```bash
juju refresh temporal-k8s --revision=<your_revision + 1>
Expand All @@ -44,3 +44,14 @@ _Warning: It is essential that upgrades are done one consecutive revision at a
time. Charmed Temporal K8s can only guarantee backward compatibility between two
consecutive revisions in line with the upgrade system adopted by the Temporal
Server._

## Appendix

The table below shows a mapping between the Temporal K8s charms and the Temporal
server versions. It can be used as a reference for upgrading your charm
revisions in line with the Temporal server version so as to avoid any breaking
changes.

| Temporal Server Charm Revision | Temporal Admin Charm Revision | Temporal Server Version |
| :----------------------------: | :---------------------------: | :---------------------: |
| 20-21 | 8-9 | v1.21.5 |
kelkawi-a marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion templates/config.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -291,5 +291,5 @@ additionalEnvs:
{%- endif %}

dynamicConfigClient:
filepath: "{{ DYNAMIC_CONFIG_FILE_PATH | default("/etc/temporal/config/dynamicconfig/development.yaml") }}"
filepath: "{{ DYNAMIC_CONFIG_FILE_PATH | default("/etc/temporal/config/dynamicconfig/docker.yaml") }}"
pollInterval: "60s"
103 changes: 103 additions & 0 deletions tests/integration/test_server_upgrade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.

"""Temporal charm upgrades integration tests."""

import asyncio
import logging
import time

import pytest
import pytest_asyncio
from helpers import (
APP_NAME,
APP_NAME_ADMIN,
APP_NAME_UI,
create_default_namespace,
perform_temporal_integrations,
run_sample_workflow,
)
from pytest_operator.plugin import OpsTest

logger = logging.getLogger(__name__)


@pytest.mark.skip_if_deployed
@pytest_asyncio.fixture(name="deploy", scope="module")
async def deploy(ops_test: OpsTest):
"""The app is up and running."""
await ops_test.model.set_config({"update-status-hook-interval": "1m"})
charm = await ops_test.build_charm(".")

# Deploy Temporal server, Temporal admin, Temporal UI and postgresql charms.
asyncio.gather(
ops_test.model.deploy(
charm,
application_name=APP_NAME,
resources={"temporal-server-image": "temporalio/server:1.20.0"},
config={"num-history-shards": "1"},
),
ops_test.model.deploy(
APP_NAME_ADMIN, channel="edge", resources={"temporal-admin-image": "temporalio/admin-tools:1.20.0"}
),
ops_test.model.deploy(APP_NAME_UI, channel="edge"),
ops_test.model.deploy("postgresql-k8s", channel="14/stable", trust=True),
)

async with ops_test.fast_forward():
await ops_test.model.wait_for_idle(
apps=[APP_NAME, APP_NAME_ADMIN, APP_NAME_UI], status="blocked", raise_on_blocked=False, timeout=600
)
await ops_test.model.wait_for_idle(
apps=["postgresql-k8s"], status="active", raise_on_blocked=False, timeout=600
)

await perform_temporal_integrations(ops_test)

await create_default_namespace(ops_test)

await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", raise_on_blocked=False, timeout=300)
assert ops_test.model.applications[APP_NAME].units[0].workload_status == "active"
assert ops_test.model.applications[APP_NAME_UI].units[0].workload_status == "active"
await run_sample_workflow(ops_test)


@pytest.mark.abort_on_fail
@pytest.mark.usefixtures("deploy")
class TestServerUpgrade:
"""Integration test for Temporal server upgrade requiring schema update.

This test ensures that upgrading from v1.20.0 to v1.21.2 (which requires a schema update) runs
successfully on the newly built charm.
"""

async def test_server_upgrade(self, ops_test: OpsTest):
"""Refresh the charm with a new resource which requires a schema update."""
# Update admin charm to v1.21.2 first
await ops_test.model.applications[APP_NAME_ADMIN].refresh(
resources={"temporal-admin-image": "temporalio/admin-tools:1.21.2"},
)
await ops_test.model.wait_for_idle(
apps=[APP_NAME_ADMIN], raise_on_error=False, status="active", raise_on_blocked=False, timeout=600
)

# Needed for a local charm refresh
charm = await ops_test.build_charm(".")

# Update server charm to v1.21.2
await ops_test.model.applications[APP_NAME].refresh(
resources={"temporal-server-image": "temporalio/server:1.21.2"},
path=str(charm),
)

# This is to accmmodate for a self-resolving error which sometimes appears when Temporal
# services attempt to connect to the cluster before the application is ready.
await ops_test.model.wait_for_idle(
apps=[APP_NAME], raise_on_error=False, status="active", raise_on_blocked=False, timeout=600
)
time.sleep(10)

assert ops_test.model.applications[APP_NAME].units[0].workload_status == "active"
assert ops_test.model.applications[APP_NAME_ADMIN].units[0].workload_status == "active"

await run_sample_workflow(ops_test)
7 changes: 2 additions & 5 deletions tests/integration/test_upgrades.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
async def deploy(ops_test: OpsTest):
"""The app is up and running."""
# Deploy temporal server, temporal admin and postgresql charms.
await ops_test.model.deploy(APP_NAME, channel="edge")
await ops_test.model.deploy(APP_NAME, channel="edge", config={"num-history-shards": 1})
await ops_test.model.deploy(APP_NAME_ADMIN, channel="edge")
await ops_test.model.deploy(APP_NAME_UI, channel="edge")
await ops_test.model.deploy("postgresql-k8s", channel="14", trust=True)
await ops_test.model.deploy("postgresql-k8s", channel="14/stable", trust=True)

async with ops_test.fast_forward():
await ops_test.model.wait_for_idle(
Expand Down Expand Up @@ -66,9 +66,6 @@ async def test_upgrade(self, ops_test: OpsTest):
# This is to accmmodate for a self-resolving error which sometimes appears when Temporal
# services attempt to connect to the cluster before the application is ready.
await ops_test.model.applications[APP_NAME].refresh(path=str(charm), resources=resources)
await ops_test.model.applications[APP_NAME].set_config(
{"num-history-shards": "1"},
)

await ops_test.model.wait_for_idle(
apps=[APP_NAME], raise_on_error=False, status="active", raise_on_blocked=False, timeout=600
Expand Down
13 changes: 13 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,16 @@ deps =
-r{toxinidir}/requirements.txt
commands =
pytest {[vars]tst_path}integration/test_auth.py -v --tb native --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs} --destructive-mode

[testenv:integration-server-upgrade]
description = Run integration server upgrade testes
deps =
ipdb==0.13.9
juju==3.3.0.0
pytest==7.1.3
pytest-operator==0.31.1
temporalio==1.1.0
pytest-asyncio==0.21
-r{toxinidir}/requirements.txt
commands =
pytest {[vars]tst_path}integration/test_server_upgrade.py -v --tb native --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs} --destructive-mode
Loading