diff --git a/.github/renovate.json5 b/.github/renovate.json5 index f9c69332ab..ddc64b8123 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,7 +1,7 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["github>canonical/data-platform//renovate_presets/charm.json5"], - "reviewers": ["dragomirp", "marceloneppel", "taurus-forever"], + "reviewers": ["dragomirp", "lucasgameiroborges", "marceloneppel", "taurus-forever"], "packageRules": [ // Later rules override earlier rules { @@ -10,6 +10,66 @@ }, { "matchPackageNames": ["python"], "allowedVersions": "<3.11" + }, + { + "matchDepNames": ["Juju 2"], + "matchPackageNames": ["juju/juju"], + "allowedVersions": "<3.0.0", + "extractVersion": "^v(?.*)$", + "groupName": "Juju 2" + }, + { + "matchDepNames": ["Juju 3"], + "matchPackageNames": ["juju/juju"], + "allowedVersions": "<3.2.0", + "extractVersion": "^v(?.*)$", + "groupName": "Juju 3" + }, + { + "matchDepNames": ["libjuju 2"], + "matchPackageNames": ["juju"], + "matchManagers": ["regex"], + "matchDatasources": ["pypi"], + "versioning": "loose", + "allowedVersions": "<3", + "groupName": "Juju 2" + } + ], + "regexManagers": [ + { + "customType": "regex", + "fileMatch": ["^(workflow-templates|\\.github/workflows)/[^/]+\\.ya?ml$"], + "matchStrings": [ + "(- agent: )(?.*?) +# renovate: latest juju 2" + ], + "depNameTemplate": "Juju 2", + "packageNameTemplate": "juju/juju", + "datasourceTemplate": "github-releases", + "versioningTemplate": "loose", + "extractVersionTemplate": "Juju release" + }, + { + "customType": "regex", + "fileMatch": ["^(workflow-templates|\\.github/workflows)/[^/]+\\.ya?ml$"], + "matchStrings": [ + "(- agent: )(?.*?) +# renovate: latest juju 3" + ], + "depNameTemplate": "Juju 3", + "packageNameTemplate": "juju/juju", + "datasourceTemplate": "github-releases", + "versioningTemplate": "loose", + "extractVersionTemplate": "Juju release" + }, + { + "customType": "regex", + "fileMatch": ["^(workflow-templates|\\.github/workflows)/[^/]+\\.ya?ml$"], + "matchStrings": [ + "(libjuju: )==(?.*?) +# renovate: latest libjuju 2" + ], + "depNameTemplate": "libjuju 2", + "packageNameTemplate": "juju", + "datasourceTemplate": "pypi", + "versioningTemplate": "loose" } ] } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f0f0d133f7..91d450a8b8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -51,10 +51,10 @@ jobs: fail-fast: false matrix: juju: - - agent: 2.9.46 - libjuju: ^2 + - agent: 2.9.46 # renovate: latest juju 2 + libjuju: ==2.9.46.1 # renovate: latest libjuju 2 allure: false - - agent: 3.1.7 + - agent: 3.1.7 # renovate: latest juju 3 allure: true name: Integration test charm | ${{ matrix.juju.agent }} needs: diff --git a/poetry.lock b/poetry.lock index 16f0375a6d..6cc1849c68 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "allure-pytest" @@ -2062,4 +2062,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "3a4440088ed3387224cf11894c06b34d85381d1e3feb56b5efa50f2feda93781" +content-hash = "cf8941bee4a9d4e4017ab0cffbd75d154f3e5c78eb1cc32eb945575b04a4a898" diff --git a/pyproject.toml b/pyproject.toml index 0322a1f0a9..e0df5d0095 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,8 @@ pytest-github-secrets = {git = "https://github.com/canonical/data-platform-workf pytest-operator = "^0.34.0" pytest-operator-cache = {git = "https://github.com/canonical/data-platform-workflows", tag = "v13.1.0", subdirectory = "python/pytest_plugins/pytest_operator_cache"} pytest-operator-groups = {git = "https://github.com/canonical/data-platform-workflows", tag = "v13.1.0", subdirectory = "python/pytest_plugins/pytest_operator_groups"} -juju = "^3.3.0.0" +# renovate caret doesn't work: https://github.com/renovatebot/renovate/issues/26940 +juju = "<=3.4.0.0" boto3 = "*" tenacity = "*" landscape-api-py3 = "^0.9.0" diff --git a/src/charm.py b/src/charm.py index 92407e9d83..9e4f198941 100755 --- a/src/charm.py +++ b/src/charm.py @@ -1390,7 +1390,11 @@ def push_tls_files_to_workload(self) -> bool: if cert is not None: self._patroni.render_file(f"{PATRONI_CONF_PATH}/{TLS_CERT_FILE}", cert, 0o600) - return self.update_config() + try: + return self.update_config() + except Exception: + logger.exception("TLS files failed to push. Error in config update") + return False def _reboot_on_detached_storage(self, event: EventBase) -> None: """Reboot on detached storage. diff --git a/src/constants.py b/src/constants.py index 3f0d79114c..49929ff037 100644 --- a/src/constants.py +++ b/src/constants.py @@ -35,7 +35,7 @@ SNAP_PACKAGES = [ ( POSTGRESQL_SNAP_NAME, - {"revision": {"aarch64": "105", "x86_64": "104"}, "channel": "14/stable"}, + {"revision": {"aarch64": "110", "x86_64": "111"}, "channel": "14/stable"}, ) ] diff --git a/tests/integration/test_backups.py b/tests/integration/test_backups.py index 77cd5c070a..f63b714217 100644 --- a/tests/integration/test_backups.py +++ b/tests/integration/test_backups.py @@ -92,11 +92,8 @@ async def cloud_configs(ops_test: OpsTest, github_secrets) -> None: @pytest.mark.group(1) @pytest.mark.abort_on_fail -async def test_backup(ops_test: OpsTest, cloud_configs: Tuple[Dict, Dict]) -> None: +async def test_backup(ops_test: OpsTest, cloud_configs: Tuple[Dict, Dict], charm) -> None: """Build and deploy two units of PostgreSQL and then test the backup and restore actions.""" - # Build the PostgreSQL charm. - charm = await ops_test.build_charm(".") - # Deploy S3 Integrator and TLS Certificates Operator. await ops_test.model.deploy(S3_INTEGRATOR_APP_NAME) await ops_test.model.deploy(TLS_CERTIFICATES_APP_NAME, config=TLS_CONFIG, channel=TLS_CHANNEL) @@ -126,7 +123,7 @@ async def test_backup(ops_test: OpsTest, cloud_configs: Tuple[Dict, Dict]) -> No await action.wait() async with ops_test.fast_forward(fast_interval="60s"): await ops_test.model.wait_for_idle( - apps=[database_app_name, S3_INTEGRATOR_APP_NAME], status="active", timeout=1200 + apps=[database_app_name, S3_INTEGRATOR_APP_NAME], status="active", timeout=1500 ) primary = await get_primary(ops_test, f"{database_app_name}/0") @@ -279,14 +276,14 @@ async def test_backup(ops_test: OpsTest, cloud_configs: Tuple[Dict, Dict]) -> No # Remove the database app. await ops_test.model.remove_application(database_app_name, block_until_done=True) + # Remove the TLS operator. await ops_test.model.remove_application(TLS_CERTIFICATES_APP_NAME, block_until_done=True) @pytest.mark.group(1) -async def test_restore_on_new_cluster(ops_test: OpsTest, github_secrets) -> None: +async def test_restore_on_new_cluster(ops_test: OpsTest, github_secrets, charm) -> None: """Test that is possible to restore a backup to another PostgreSQL cluster.""" - charm = await ops_test.build_charm(".") previous_database_app_name = f"{DATABASE_APP_NAME}-gcp" database_app_name = f"new-{DATABASE_APP_NAME}" await ops_test.model.deploy(charm, application_name=previous_database_app_name) @@ -355,12 +352,9 @@ async def test_restore_on_new_cluster(ops_test: OpsTest, github_secrets) -> None # Wait for the restore to complete. async with ops_test.fast_forward(): - await wait_for_idle_on_blocked( - ops_test, - database_app_name, - 0, - S3_INTEGRATOR_APP_NAME, - ANOTHER_CLUSTER_REPOSITORY_ERROR_MESSAGE, + unit = ops_test.model.units.get(f"{database_app_name}/0") + await ops_test.model.block_until( + lambda: unit.workload_status_message == ANOTHER_CLUSTER_REPOSITORY_ERROR_MESSAGE ) # Check that the backup was correctly restored by having only the first created table. @@ -402,12 +396,9 @@ async def test_invalid_config_and_recovery_after_fixing_it( ) await action.wait() logger.info("waiting for the database charm to become blocked") - await wait_for_idle_on_blocked( - ops_test, - database_app_name, - 0, - S3_INTEGRATOR_APP_NAME, - FAILED_TO_ACCESS_CREATE_BUCKET_ERROR_MESSAGE, + unit = ops_test.model.units.get(f"{database_app_name}/0") + await ops_test.model.block_until( + lambda: unit.workload_status_message == FAILED_TO_ACCESS_CREATE_BUCKET_ERROR_MESSAGE ) # Provide valid backup configurations, but from another cluster repository. @@ -421,12 +412,9 @@ async def test_invalid_config_and_recovery_after_fixing_it( ) await action.wait() logger.info("waiting for the database charm to become blocked") - await wait_for_idle_on_blocked( - ops_test, - database_app_name, - 0, - S3_INTEGRATOR_APP_NAME, - ANOTHER_CLUSTER_REPOSITORY_ERROR_MESSAGE, + unit = ops_test.model.units.get(f"{database_app_name}/0") + await ops_test.model.block_until( + lambda: unit.workload_status_message == ANOTHER_CLUSTER_REPOSITORY_ERROR_MESSAGE ) # Provide valid backup configurations, with another path in the S3 bucket.