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

fix: make client_facades reflect facades in generated client code #1150

Merged
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a9601a7
test: add a (failing) test to validate client_facades
james-garner-canonical Oct 9, 2024
9a8498f
ci: add a tox environment to run the test
james-garner-canonical Oct 9, 2024
0d54e47
fix: update client_facades to pass validation test
james-garner-canonical Oct 9, 2024
93e2755
ci: add github job to validate client_schemas on push and PRs
james-garner-canonical Oct 9, 2024
fb180ef
style: fix linting issues
james-garner-canonical Oct 9, 2024
ab7d340
style: add copyright header
james-garner-canonical Oct 9, 2024
e6dc554
fix: remove a use of | in type annotations that slipped through
james-garner-canonical Oct 9, 2024
5bf9845
fix: add some print statements for debugging
james-garner-canonical Oct 10, 2024
021cdd1
fix: see what happens if we use supported_bases instead
james-garner-canonical Oct 10, 2024
c49061c
ci: remove custom error collection and use pytest
james-garner-canonical Oct 10, 2024
ae1a319
fix: revert changes made for debugging
james-garner-canonical Oct 10, 2024
1afdad6
style: simplify test and pass linting
james-garner-canonical Oct 10, 2024
ead3548
feat: add a manually updated collection of excluded facades
james-garner-canonical Oct 10, 2024
74dbff3
ci: bump action versions
james-garner-canonical Oct 10, 2024
b9a7071
test: refactor test_client_facades
james-garner-canonical Oct 10, 2024
770af9b
test: out of sheer superstition, revert last commit to rerun tests
james-garner-canonical Oct 10, 2024
32a2b36
test: revert revert as it didn't help
james-garner-canonical Oct 10, 2024
d911ef4
test: simplify test
james-garner-canonical Oct 11, 2024
e800b48
test: simplify globbing expression and add docstrings
james-garner-canonical Oct 15, 2024
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
19 changes: 19 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ jobs:
run: |
make build-test

validate:
name: Validate
runs-on: ubuntu-latest
strategy:
matrix:
python:
- "3.10"
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: pip install tox
- name: Run validation tests
run: tox -e validate

unit-tests:
needs: lint
name: Unit tests
Expand Down
112 changes: 57 additions & 55 deletions juju/client/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import weakref
from http.client import HTTPSConnection
from dateutil.parser import parse
from typing import Dict, List

import macaroonbakery.bakery as bakery
import macaroonbakery.httpbakery as httpbakery
Expand All @@ -20,86 +21,89 @@

log = logging.getLogger('juju.client.connection')

# Manual list of facades present in schemas + codegen which python-libjuju does not yet support
excluded_facades: Dict[str, List[int]] = {
'Charms': [7],
}
# Please keep in alphabetical order
# in future this will likely be generated automatically (perhaps at runtime)
client_facades = {
'Action': {'versions': [2, 6, 7]},
'Action': {'versions': [7]},
'ActionPruner': {'versions': [1]},
'Agent': {'versions': [2, 3]},
'Admin': {'versions': [3]},
'Agent': {'versions': [3]},
'AgentLifeFlag': {'versions': [1]},
'AgentTools': {'versions': [1]},
'AllModelWatcher': {'versions': [2, 3, 4]},
'AllWatcher': {'versions': [1, 2, 3, 4]},
'AllModelWatcher': {'versions': [4]},
'AllWatcher': {'versions': [3]},
'Annotations': {'versions': [2]},
'Application': {'versions': [14, 15, 16, 17, 19]},
'ApplicationOffers': {'versions': [1, 2, 4]},
'Application': {'versions': [17, 18, 19]},
'ApplicationOffers': {'versions': [4]},
'ApplicationScaler': {'versions': [1]},
'Backups': {'versions': [1, 2, 3]},
'Backups': {'versions': [3]},
'Block': {'versions': [2]},
'Bundle': {'versions': [5, 6]},
'CharmHub': {'versions': [1]},
'CharmRevisionUpdater': {'versions': [2]},
'CharmDownloader': {'versions': [1]},
'Charms': {'versions': [5, 6]},
'Cleaner': {'versions': [2]},
'Client': {'versions': [5, 6]},
'Cloud': {'versions': [1, 2, 3, 4, 5, 7]},
'Controller': {'versions': [9, 11]},
'CrossModelRelations': {'versions': [1, 2]},
'CrossModelSecrets': {'versions': [1]},
'CrossController': {'versions': [1]},
'CredentialManager': {'versions': [1]},
'CredentialValidator': {'versions': [1, 2]},
dimaqq marked this conversation as resolved.
Show resolved Hide resolved
'Bundle': {'versions': [6]},
'CAASAdmission': {'versions': [1]},
'CAASAgent': {'versions': [1, 2]},
'CAASAgent': {'versions': [2]},
'CAASApplication': {'versions': [1]},
'CAASApplicationProvisioner': {'versions': [1]},
'CAASFirewaller': {'versions': [1]},
'CAASFirewallerEmbedded': {'versions': [1]},
'CAASFirewallerSidecar': {'versions': [1]},
'CAASModelOperator': {'versions': [1]},
'CAASModelConfigManager': {'versions': [1]},
'CAASModelOperator': {'versions': [1]},
'CAASOperator': {'versions': [1]},
'CAASOperatorProvisioner': {'versions': [1]},
'CAASOperatorUpgrader': {'versions': [1]},
'CAASUnitProvisioner': {'versions': [1, 2]},
'CAASUnitProvisioner': {'versions': [2]},
'CharmDownloader': {'versions': [1]},
'CharmRevisionUpdater': {'versions': [2]},
'Charms': {'versions': [6]},
'Cleaner': {'versions': [2]},
'Client': {'versions': [6, 7]},
'Cloud': {'versions': [7]},
'Controller': {'versions': [11]},
'CredentialManager': {'versions': [1]},
'CredentialValidator': {'versions': [2]},
'CrossController': {'versions': [1]},
'CrossModelRelations': {'versions': [2]},
'CrossModelSecrets': {'versions': [1]},
'Deployer': {'versions': [1]},
'DiskManager': {'versions': [2]},
'EntityWatcher': {'versions': [2]},
'EnvironUpgrader': {'versions': [1]},
'ExternalControllerUpdater': {'versions': [1]},
'FanConfigurer': {'versions': [1]},
'FilesystemAttachmentsWatcher': {'versions': [2]},
'Firewaller': {'versions': [3, 4, 5, 7]},
'FirewallRules': {'versions': [1]},
'Firewaller': {'versions': [7]},
'HighAvailability': {'versions': [2]},
'HostKeyReporter': {'versions': [1]},
'ImageManager': {'versions': [2]},
'ImageMetadata': {'versions': [3]},
'ImageMetadataManager': {'versions': [1]},
'InstanceMutater': {'versions': [2, 3]},
'InstancePoller': {'versions': [3, 4]},
'InstanceMutater': {'versions': [3]},
'InstancePoller': {'versions': [4]},
'KeyManager': {'versions': [1]},
'KeyUpdater': {'versions': [1]},
'LeadershipService': {'versions': [2]},
'LifeFlag': {'versions': [1]},
'Logger': {'versions': [1]},
'LogForwarding': {'versions': [1]},
'Machiner': {'versions': [1, 2, 5]},
'Logger': {'versions': [1]},
'MachineActions': {'versions': [1]},
'MachineManager': {'versions': [9, 10]},
'MachineManager': {'versions': [10]},
'MachineUndertaker': {'versions': [1]},
'MeterStatus': {'versions': [1, 2]},
'Machiner': {'versions': [5]},
'MeterStatus': {'versions': [2]},
'MetricsAdder': {'versions': [2]},
'MetricsDebug': {'versions': [2]},
'MetricsManager': {'versions': [1]},
'MigrationFlag': {'versions': [1]},
'MigrationMaster': {'versions': [1, 3]},
'MigrationMaster': {'versions': [3]},
'MigrationMinion': {'versions': [1]},
'MigrationStatusWatcher': {'versions': [1]},
'MigrationTarget': {'versions': [1]},
'ModelConfig': {'versions': [1, 2, 3]},
'ModelGeneration': {'versions': [1, 2, 4]},
'ModelManager': {'versions': [2, 3, 4, 5, 9]},
'MigrationTarget': {'versions': [1, 2]},
'ModelConfig': {'versions': [3]},
'ModelGeneration': {'versions': [4]},
'ModelManager': {'versions': [9]},
'ModelSummaryWatcher': {'versions': [1]},
'ModelUpgrader': {'versions': [1]},
'NotifyWatcher': {'versions': [1]},
Expand All @@ -108,45 +112,43 @@
'PayloadsHookContext': {'versions': [1]},
'Pinger': {'versions': [1]},
'Provisioner': {'versions': [11]},
'ProxyUpdater': {'versions': [1, 2]},
'RaftLease': {'versions': [1, 2]},
'ProxyUpdater': {'versions': [2]},
'RaftLease': {'versions': [2]},
'Reboot': {'versions': [2]},
'RelationStatusWatcher': {'versions': [1]},
'RelationUnitsWatcher': {'versions': [1]},
'RemoteRelations': {'versions': [1, 2]},
'RemoteRelationWatcher': {'versions': [1]},
'Resources': {'versions': [1, 2, 3]},
'RemoteRelations': {'versions': [2]},
'Resources': {'versions': [3]},
'ResourcesHookContext': {'versions': [1]},
'Resumer': {'versions': [2]},
'RetryStrategy': {'versions': [1]},
'Secrets': {'versions': [1, 2]},
'SecretsManager': {'versions': [1, 2]},
'SSHClient': {'versions': [4]},
'SecretBackends': {'versions': [1]},
'SecretBackendsManager': {'versions': [1]},
'SecretBackendsRotateWatcher': {'versions': [1]},
'Secrets': {'versions': [1, 2]},
'SecretsDrain': {'versions': [1]},
'SecretsManager': {'versions': [1, 2]},
'SecretsRevisionWatcher': {'versions': [1]},
'SecretsRotationWatcher': {'versions': [1]},
'SecretsTriggerWatcher': {'versions': [1]},
'Singular': {'versions': [2]},
'Spaces': {'versions': [6]},
'StatusHistory': {'versions': [2]},
'Storage': {'versions': [3, 4, 6]},
'StorageProvisioner': {'versions': [3, 4]},
'Storage': {'versions': [6]},
'StorageProvisioner': {'versions': [4]},
'StringsWatcher': {'versions': [1]},
'Subnets': {'versions': [2, 4, 5]},
'SSHClient': {'versions': [1, 2, 3, 4]},
'Subnets': {'versions': [5]},
'Undertaker': {'versions': [1]},
'UnitAssigner': {'versions': [1]},
'Uniter': {'versions': [18]},
'Uniter': {'versions': [18, 19]},
'UpgradeSeries': {'versions': [3]},
'UpgradeSteps': {'versions': [2]},
'Upgrader': {'versions': [1]},
'UpgradeSeries': {'versions': [1, 3]},
'UpgradeSteps': {'versions': [1, 2]},
'UserManager': {'versions': [1, 2, 3]},
'UserManager': {'versions': [3]},
'UserSecretsDrain': {'versions': [1]},
'UserSecretsManager': {'versions': [1]},
'VolumeAttachmentsWatcher': {'versions': [2]},
'VolumeAttachmentPlansWatcher': {'versions': [1]},
'VolumeAttachmentsWatcher': {'versions': [2]},
}


Expand Down
51 changes: 51 additions & 0 deletions tests/validate/test_facades.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2023 Canonical Ltd.
# Licensed under the Apache V2, see LICENCE file for details.

import importlib
from collections import defaultdict
from pathlib import Path
from typing import Dict, List, TypedDict

import pytest

from juju.client.connection import client_facades, excluded_facades


class Versions(TypedDict, total=True):
versions: List[int]


ClientFacades = Dict[str, Versions]


@pytest.fixture
def project_root(pytestconfig: pytest.Config) -> Path:
return pytestconfig.rootpath


@pytest.fixture
def generated_code_facades(project_root: Path) -> ClientFacades:
"""Return a client_facades dictionary from generated code under project_root.
"""
facades: Dict[str, List[int]] = defaultdict(list)
for file in (project_root / 'juju' / 'client').glob('_client[0-9]*.py'):
module = importlib.import_module(f'juju.client.{file.stem}')
james-garner-canonical marked this conversation as resolved.
Show resolved Hide resolved
for cls_name in dir(module):
cls = getattr(module, cls_name)
try:
cls.name
cls.version
except AttributeError:
continue
if cls.version in excluded_facades.get(cls.name, []):
continue
facades[cls.name].append(cls.version)
return {name: {'versions': sorted(facades[name])} for name in sorted(facades)}


def test_client_facades(project_root: Path, generated_code_facades: ClientFacades) -> None:
assert {
k: v['versions'] for k, v in client_facades.items()
} == {
k: v['versions'] for k, v in generated_code_facades.items()
}
4 changes: 4 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ commands =
pip install pylxd
python -m pytest --tb native -ra -v -s {posargs:-m 'serial'}

[testenv:validate]
envdir = {toxworkdir}/validate
commands = python -m pytest --tb native -ra -vv tests/validate

[testenv:example]
envdir = {toxworkdir}/py3
commands = python {posargs}
Expand Down
Loading