Skip to content

Commit

Permalink
migrating to DPE int tests for CI (#354)
Browse files Browse the repository at this point in the history
## Issue
We are not using DP workflows for int tests, this causes two problems:
1. forked PRs fail due to inability to access secrets
2. we want to easily share secrets across the int tests

## Solution
migrate to the new DP job for int tests

---------

Co-authored-by: Carl Csaposs <carl.csaposs@canonical.com>
  • Loading branch information
MiaAltieri and carlcsaposs-canonical authored Feb 19, 2024
1 parent 3d98182 commit 3016d4d
Show file tree
Hide file tree
Showing 18 changed files with 144 additions and 294 deletions.
103 changes: 28 additions & 75 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ on:
- cron: "53 0 * * *" # Daily at 00:53 UTC
# Triggered on push to branch "main" by .github/workflows/release.yaml
workflow_call:
secrets:
CHARMHUB_TOKEN:
required: true
AWS_ACCESS_KEY:
required: true
AWS_SECRET_KEY:
required: true
GCP_ACCESS_KEY:
required: true
GCP_SECRET_KEY:
required: true

jobs:
lint:
Expand Down Expand Up @@ -66,73 +55,37 @@ jobs:
github-token: "${{ secrets.GITHUB_TOKEN }}"

build:
name: Build charms
uses: canonical/data-platform-workflows/.github/workflows/build_charms_with_cache.yaml@v8

integration-test:
strategy:
fail-fast: false
matrix:
tox-environments:
- charm-integration
- ha-integration
- relation-integration
- legacy-integration
- tls-integration
- backup-integration
- metric-integration
- sharding-integration
- sharding-relation-integration
- sharding-race-conditions-integration
- sharding-mongos-integration
name: ${{ matrix.tox-environments }}
path:
- .
- tests/integration/sharding_tests/application
- tests/integration/relation_tests/new_relations/application-charm
- tests/integration/dummy_legacy_app
name: Build charm
uses: canonical/data-platform-workflows/.github/workflows/build_charm.yaml@v11.0.1
with:
path-to-charm-directory: ${{ matrix.path }}
cache: true

integration-test:
name: Integration test charm
needs:
- lint
- unit-test
- lib-check
- build
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup operator environment
# TODO: Replace with custom image on self-hosted runner
uses: charmed-kubernetes/actions-operator@main
with:
provider: lxd
juju-channel: 3.1/stable
- name: Download packed charm(s)
uses: actions/download-artifact@v3
with:
name: ${{ needs.build.outputs.artifact-name }}
- name: Free disk space
run: |
echo "Free disk space before cleanup"
df -T
# free space in the runner
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /usr/local/share/boost
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
echo "Free disk space after cleanup"
df -T
- name: Select tests
id: select-tests
run: |
if [ "${{ github.event_name }}" == "schedule" ]
then
echo Running unstable and stable tests
echo "mark_expression=" >> $GITHUB_OUTPUT
else
echo Skipping unstable tests
echo "mark_expression=not unstable" >> $GITHUB_OUTPUT
fi
- name: Run integration tests
run: tox run -e ${{ matrix.tox-environments }} -- -m '${{ steps.select-tests.outputs.mark_expression }}'
env:
CI_PACKED_CHARMS: ${{ needs.build.outputs.charms }}
AWS_ACCESS_KEY: ${{ matrix.tox-environments != 'backup-integration' || secrets.AWS_ACCESS_KEY }}
AWS_SECRET_KEY: ${{ matrix.tox-environments != 'backup-integration' || secrets.AWS_SECRET_KEY }}
GCP_ACCESS_KEY: ${{ matrix.tox-environments != 'backup-integration' || secrets.GCP_ACCESS_KEY }}
GCP_SECRET_KEY: ${{ matrix.tox-environments != 'backup-integration' || secrets.GCP_SECRET_KEY }}
uses: canonical/data-platform-workflows/.github/workflows/integration_test_charm.yaml@v11.0.1
with:
artifact-prefix: packed-charm-cache-true
cloud: lxd
juju-agent-version: 3.1.6
permissions:
contents: write # Needed for Allure Report beta
secrets:
integration-test: |
{
"AWS_ACCESS_KEY": "${{ secrets.AWS_ACCESS_KEY }}",
"AWS_SECRET_KEY": "${{ secrets.AWS_SECRET_KEY }}",
"GCP_ACCESS_KEY": "${{ secrets.GCP_ACCESS_KEY }}",
"GCP_SECRET_KEY": "${{ secrets.GCP_SECRET_KEY }}",
}
15 changes: 4 additions & 11 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,18 @@ on:
jobs:
ci-tests:
uses: ./.github/workflows/ci.yaml
secrets:
CHARMHUB_TOKEN: "${{ secrets.CHARMHUB_TOKEN }}"
AWS_ACCESS_KEY: "${{ secrets.AWS_ACCESS_KEY }}"
AWS_SECRET_KEY: "${{ secrets.AWS_SECRET_KEY }}"
GCP_ACCESS_KEY: "${{ secrets.GCP_ACCESS_KEY }}"
GCP_SECRET_KEY: "${{ secrets.GCP_SECRET_KEY }}"
secrets: inherit

build:
name: Build charm
uses: canonical/data-platform-workflows/.github/workflows/build_charm_without_cache.yaml@v8
with:
charmcraft-snap-channel: "latest/stable"
uses: canonical/data-platform-workflows/.github/workflows/build_charm_without_cache.yaml@v11.0.1

release-charm:
name: Release charm
needs:
- ci-tests
- build
uses: canonical/data-platform-workflows/.github/workflows/release_charm.yaml@v8
uses: canonical/data-platform-workflows/.github/workflows/release_charm.yaml@v11.0.1
with:
channel: 6/edge
artifact-name: ${{ needs.build.outputs.artifact-name }}
Expand All @@ -36,7 +29,7 @@ jobs:
contents: write # Needed to create GitHub release

release-libraries:
name: Release libraries
name: Release libraries
runs-on: ubuntu-latest
needs:
- ci-tests
Expand Down
2 changes: 0 additions & 2 deletions tests/__init__.py

This file was deleted.

1 change: 0 additions & 1 deletion tests/integration/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.
7 changes: 3 additions & 4 deletions tests/integration/backup_tests/helpers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.
import os
import subprocess

import ops
Expand Down Expand Up @@ -95,11 +94,11 @@ async def count_failed_backups(db_unit: ops.model.Unit) -> int:
return failed_backups


async def set_credentials(ops_test: OpsTest, cloud: str) -> None:
async def set_credentials(ops_test: OpsTest, github_secrets, cloud: str) -> None:
"""Sets the s3 crednetials for the provided cloud, valid options are AWS or GCP."""
# set access key and secret keys
access_key = os.environ.get(f"{cloud}_ACCESS_KEY", False)
secret_key = os.environ.get(f"{cloud}_SECRET_KEY", False)
access_key = github_secrets[f"{cloud}_ACCESS_KEY"]
secret_key = github_secrets[f"{cloud}_SECRET_KEY"]
assert access_key and secret_key, f"{cloud} access key and secret key not provided."

s3_integrator_unit = ops_test.model.applications[S3_APP_NAME].units[0]
Expand Down
32 changes: 21 additions & 11 deletions tests/integration/backup_tests/test_backups.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
from pytest_operator.plugin import OpsTest
from tenacity import RetryError, Retrying, stop_after_delay, wait_fixed

from tests.integration.helpers import get_app_name

from ..ha_tests import helpers as ha_helpers
from ..helpers import get_app_name
from . import helpers

S3_APP_NAME = "s3-integrator"
Expand Down Expand Up @@ -43,6 +42,7 @@ async def add_writes_to_db(ops_test: OpsTest):
await ha_helpers.clear_db_writes(ops_test)


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_build_and_deploy(ops_test: OpsTest) -> None:
"""Build and deploy one unit of MongoDB."""
Expand All @@ -58,6 +58,7 @@ async def test_build_and_deploy(ops_test: OpsTest) -> None:
await ops_test.model.wait_for_idle()


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_blocked_incorrect_creds(ops_test: OpsTest) -> None:
"""Verifies that the charm goes into blocked status when s3 creds are incorrect."""
Expand Down Expand Up @@ -88,13 +89,14 @@ async def test_blocked_incorrect_creds(ops_test: OpsTest) -> None:
assert db_unit.workload_status_message == "s3 credentials are incorrect."


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_blocked_incorrect_conf(ops_test: OpsTest) -> None:
async def test_blocked_incorrect_conf(ops_test: OpsTest, github_secrets) -> None:
"""Verifies that the charm goes into blocked status when s3 config options are incorrect."""
db_app_name = await get_app_name(ops_test)

# set correct AWS credentials for s3 storage but incorrect configs
await helpers.set_credentials(ops_test, cloud="AWS")
await helpers.set_credentials(ops_test, github_secrets, cloud="AWS")

# wait for both applications to be idle with the correct statuses
async with ops_test.fast_forward():
Expand All @@ -107,6 +109,7 @@ async def test_blocked_incorrect_conf(ops_test: OpsTest) -> None:
assert db_unit.workload_status_message == "s3 configurations are incompatible."


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_ready_correct_conf(ops_test: OpsTest) -> None:
"""Verifies charm goes into active status when s3 config and creds options are correct."""
Expand All @@ -130,11 +133,12 @@ async def test_ready_correct_conf(ops_test: OpsTest) -> None:
)


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_create_and_list_backups(ops_test: OpsTest) -> None:
async def test_create_and_list_backups(ops_test: OpsTest, github_secrets) -> None:
db_app_name = await get_app_name(ops_test)
leader_unit = await helpers.get_leader_unit(ops_test, db_app_name=db_app_name)
await helpers.set_credentials(ops_test, cloud="AWS")
await helpers.set_credentials(ops_test, github_secrets, cloud="AWS")
# verify backup list works
logger.error("!!!!! test_create_and_list_backups >>> %s", leader_unit)
action = await leader_unit.run_action(action_name="list-backups")
Expand All @@ -161,8 +165,9 @@ async def test_create_and_list_backups(ops_test: OpsTest) -> None:
assert backups == 1, "Backup not created."


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_multi_backup(ops_test: OpsTest, continuous_writes_to_db) -> None:
async def test_multi_backup(ops_test: OpsTest, continuous_writes_to_db, github_secrets) -> None:
"""With writes in the DB test creating a backup while another one is running.
Note that before creating the second backup we change the bucket and change the s3 storage
Expand All @@ -183,7 +188,7 @@ async def test_multi_backup(ops_test: OpsTest, continuous_writes_to_db) -> None:

# while first backup is running change access key, secret keys, and bucket name
# for GCP
await helpers.set_credentials(ops_test, cloud="GCP")
await helpers.set_credentials(ops_test, github_secrets, cloud="GCP")

# change to GCP configs and wait for PBM to resync
configuration_parameters = {
Expand Down Expand Up @@ -226,7 +231,7 @@ async def test_multi_backup(ops_test: OpsTest, continuous_writes_to_db) -> None:
assert backups == 1, "Backup not created in first bucket on GCP."

# set AWS credentials, set configs for s3 storage, and wait to resync
await helpers.set_credentials(ops_test, cloud="AWS")
await helpers.set_credentials(ops_test, github_secrets, cloud="AWS")
configuration_parameters = {
"bucket": "data-charms-testing",
"region": "us-east-1",
Expand All @@ -247,6 +252,7 @@ async def test_multi_backup(ops_test: OpsTest, continuous_writes_to_db) -> None:
assert backups == 2, "Backup not created in bucket on AWS."


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_restore(ops_test: OpsTest, add_writes_to_db) -> None:
"""Simple backup tests that verifies that writes are correctly restored."""
Expand Down Expand Up @@ -301,11 +307,14 @@ async def test_restore(ops_test: OpsTest, add_writes_to_db) -> None:
assert number_writes == number_writes_restored, "writes not correctly restored"


@pytest.mark.group(1)
@pytest.mark.parametrize("cloud_provider", ["AWS", "GCP"])
async def test_restore_new_cluster(ops_test: OpsTest, add_writes_to_db, cloud_provider):
async def test_restore_new_cluster(
ops_test: OpsTest, add_writes_to_db, cloud_provider, github_secrets
):
# configure test for the cloud provider
db_app_name = await get_app_name(ops_test)
await helpers.set_credentials(ops_test, cloud=cloud_provider)
await helpers.set_credentials(ops_test, github_secrets, cloud=cloud_provider)
if cloud_provider == "AWS":
configuration_parameters = {
"bucket": "data-charms-testing",
Expand Down Expand Up @@ -388,6 +397,7 @@ async def test_restore_new_cluster(ops_test: OpsTest, add_writes_to_db, cloud_pr
await helpers.destroy_cluster(ops_test, cluster_name=NEW_CLUSTER)


@pytest.mark.group(1)
@pytest.mark.abort_on_fail
async def test_update_backup_password(ops_test: OpsTest) -> None:
"""Verifies that after changing the backup password the pbm tool is updated and functional."""
Expand Down
Loading

0 comments on commit 3016d4d

Please sign in to comment.