diff --git a/juju/application.py b/juju/application.py index 3a80f23f..4502d30b 100644 --- a/juju/application.py +++ b/juju/application.py @@ -4,9 +4,11 @@ import hashlib import json import logging -import typing +from typing import Dict, List, Union from pathlib import Path +from typing_extensions import deprecated + from . import jasyncio, model, tag, utils from .annotationhelper import _get_annotations, _set_annotations from .bundle import get_charm_series, is_local_charm @@ -24,6 +26,42 @@ class Application(model.ModelEntity): + @property + def name(self) -> str: + return self.entity_id + + @property + def exposed(self) -> bool: + return self.safe_data["exposed"] + + @property + @deprecated("Application.owner_tag is deprecated and will be removed in v4") + def owner_tag(self) -> str: + return self.safe_data["owner-tag"] + + @property + def life(self) -> str: + return self.safe_data["life"] + + @property + @deprecated("Application.min_units is deprecated and will be removed in v4") + def min_units(self) -> int: + return self.safe_data["min-units"] + + @property + def constraints(self) -> Dict[str, Union[str, int, bool]]: + return self.safe_data["constraints"] + + @property + @deprecated("Application.subordinate is deprecated and will be removed in v4") + def subordinate(self) -> bool: + return self.safe_data["subordinate"] + + @property + @deprecated("Application.workload_version is deprecated and will be removed in v4, use Unit.workload_version instead.") + def workload_version(self) -> str: + return self.safe_data["workload-version"] + @property def _unit_match_pattern(self): return r'^{}.*$'.format(self.entity_id) @@ -63,7 +101,7 @@ def subordinate_units(self): return [u for u in self.units if u.is_subordinate] @property - def relations(self) -> typing.List[Relation]: + def relations(self) -> List[Relation]: return [rel for rel in self.model.relations if rel.matches(self.name)] def related_applications(self, endpoint_name=None): diff --git a/setup.py b/setup.py index 14852310..5faca595 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,7 @@ 'kubernetes>=12.0.1,<31.0.0', 'hvac', 'packaging', + 'typing-extensions>=4.5.0', ], include_package_data=True, maintainer='Juju Ecosystem Engineering', diff --git a/tests/unit/test_application.py b/tests/unit/test_application.py index e2b9a588..927be142 100644 --- a/tests/unit/test_application.py +++ b/tests/unit/test_application.py @@ -21,7 +21,6 @@ async def test_expose_with_exposed_endpoints_as_raw_dict(self, mock_conn): mock_facade().Expose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) - app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version @@ -37,7 +36,7 @@ async def test_expose_with_exposed_endpoints_as_raw_dict(self, mock_conn): }) mock_facade().Expose.assert_called_once_with( - application="panther", + application="app-id", exposed_endpoints={ "": { "expose-to-spaces": ["alpha"], @@ -53,7 +52,6 @@ async def test_expose_with_exposed_endpoints(self, mock_conn): mock_facade().Expose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) - app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version @@ -67,7 +65,7 @@ async def test_expose_with_exposed_endpoints(self, mock_conn): }) mock_facade().Expose.assert_called_once_with( - application="panther", + application="app-id", exposed_endpoints={ "": { "expose-to-spaces": ["alpha"], @@ -89,7 +87,6 @@ async def test_expose_endpoints_on_older_controller(self, mock_conn): mock_facade().Expose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) - app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version @@ -125,7 +122,7 @@ async def test_expose_endpoints_on_older_controller(self, mock_conn): # Check that we call the facade with the right arity. await app.expose() - mock_facade().Expose.assert_called_once_with(application="panther") + mock_facade().Expose.assert_called_once_with(application="app-id") class TestUnExposeApplication(unittest.IsolatedAsyncioTestCase): @@ -137,7 +134,6 @@ async def test_unexpose_endpoints_on_older_controller(self, mock_conn): mock_facade().Unexpose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) - app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version @@ -148,7 +144,7 @@ async def test_unexpose_endpoints_on_older_controller(self, mock_conn): # Check that we call the facade with the right arity. await app.unexpose() - mock_facade().Unexpose.assert_called_once_with(application="panther") + mock_facade().Unexpose.assert_called_once_with(application="app-id") @mock.patch("juju.model.Model.connection") async def test_unexpose_endpoints_on_29_controller(self, mock_conn): @@ -158,14 +154,13 @@ async def test_unexpose_endpoints_on_29_controller(self, mock_conn): mock_facade().Unexpose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) - app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version await app.unexpose(exposed_endpoints=["alpha", "beta"]) mock_facade().Unexpose.assert_called_once_with( - application="panther", + application="app-id", exposed_endpoints=["alpha", "beta"] )