Skip to content

Commit 5de27a9

Browse files
committed
feat: deprecation warnings on select application attributes
1 parent 29ee682 commit 5de27a9

3 files changed

Lines changed: 56 additions & 12 deletions

File tree

juju/application.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
import hashlib
55
import json
66
import logging
7-
import typing
7+
from typing import Dict, List, Union
88
from pathlib import Path
99

10+
from typing_extensions import deprecated
11+
1012
from . import jasyncio, model, tag, utils
1113
from .annotationhelper import _get_annotations, _set_annotations
1214
from .bundle import get_charm_series, is_local_charm
@@ -24,6 +26,52 @@
2426

2527

2628
class Application(model.ModelEntity):
29+
"""Represents the current state of a deployed application.
30+
31+
In the current library version, as well entire 2.x and 3.x series,
32+
the data is supplied by Juju AllWatcher notifications, also known as deltas
33+
for the specific application. The fields are declared here:
34+
https://github.com/juju/juju/blob/be8a779/core/multiwatcher/types.go#L191-L209
35+
36+
The fields marked deprecated below will be removed in version 4.0 because
37+
a different API must be used against Juju 4.
38+
"""
39+
@property
40+
def name(self) -> str:
41+
return self.entity_id
42+
43+
@property
44+
def exposed(self) -> bool:
45+
return self.safe_data["exposed"]
46+
47+
@property
48+
@deprecated("Application.owner_tag is deprecated and will be removed in v4")
49+
def owner_tag(self) -> str:
50+
return self.safe_data["owner-tag"]
51+
52+
@property
53+
def life(self) -> str:
54+
return self.safe_data["life"]
55+
56+
@property
57+
@deprecated("Application.min_units is deprecated and will be removed in v4")
58+
def min_units(self) -> int:
59+
return self.safe_data["min-units"]
60+
61+
@property
62+
def constraints(self) -> Dict[str, Union[str, int, bool]]:
63+
return self.safe_data["constraints"]
64+
65+
@property
66+
@deprecated("Application.subordinate is deprecated and will be removed in v4")
67+
def subordinate(self) -> bool:
68+
return self.safe_data["subordinate"]
69+
70+
@property
71+
@deprecated("Application.workload_version is deprecated and will be removed in v4, use Unit.workload_version instead.")
72+
def workload_version(self) -> str:
73+
return self.safe_data["workload-version"]
74+
2775
@property
2876
def _unit_match_pattern(self):
2977
return r'^{}.*$'.format(self.entity_id)
@@ -63,7 +111,7 @@ def subordinate_units(self):
63111
return [u for u in self.units if u.is_subordinate]
64112

65113
@property
66-
def relations(self) -> typing.List[Relation]:
114+
def relations(self) -> List[Relation]:
67115
return [rel for rel in self.model.relations if rel.matches(self.name)]
68116

69117
def related_applications(self, endpoint_name=None):

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
'kubernetes>=12.0.1,<31.0.0',
3535
'hvac',
3636
'packaging',
37+
'typing-extensions>=4.5.0',
3738
],
3839
include_package_data=True,
3940
maintainer='Juju Ecosystem Engineering',

tests/unit/test_application.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ async def test_expose_with_exposed_endpoints_as_raw_dict(self, mock_conn):
2121
mock_facade().Expose.return_value.set_result([])
2222

2323
app = Application(entity_id="app-id", model=Model())
24-
app.name = "panther"
2524
app._facade = mock_facade
2625
app._facade_version = mock_facade_version
2726

@@ -37,7 +36,7 @@ async def test_expose_with_exposed_endpoints_as_raw_dict(self, mock_conn):
3736
})
3837

3938
mock_facade().Expose.assert_called_once_with(
40-
application="panther",
39+
application="app-id",
4140
exposed_endpoints={
4241
"": {
4342
"expose-to-spaces": ["alpha"],
@@ -53,7 +52,6 @@ async def test_expose_with_exposed_endpoints(self, mock_conn):
5352
mock_facade().Expose.return_value.set_result([])
5453

5554
app = Application(entity_id="app-id", model=Model())
56-
app.name = "panther"
5755
app._facade = mock_facade
5856
app._facade_version = mock_facade_version
5957

@@ -67,7 +65,7 @@ async def test_expose_with_exposed_endpoints(self, mock_conn):
6765
})
6866

6967
mock_facade().Expose.assert_called_once_with(
70-
application="panther",
68+
application="app-id",
7169
exposed_endpoints={
7270
"": {
7371
"expose-to-spaces": ["alpha"],
@@ -89,7 +87,6 @@ async def test_expose_endpoints_on_older_controller(self, mock_conn):
8987
mock_facade().Expose.return_value.set_result([])
9088

9189
app = Application(entity_id="app-id", model=Model())
92-
app.name = "panther"
9390
app._facade = mock_facade
9491
app._facade_version = mock_facade_version
9592

@@ -125,7 +122,7 @@ async def test_expose_endpoints_on_older_controller(self, mock_conn):
125122

126123
# Check that we call the facade with the right arity.
127124
await app.expose()
128-
mock_facade().Expose.assert_called_once_with(application="panther")
125+
mock_facade().Expose.assert_called_once_with(application="app-id")
129126

130127

131128
class TestUnExposeApplication(unittest.IsolatedAsyncioTestCase):
@@ -137,7 +134,6 @@ async def test_unexpose_endpoints_on_older_controller(self, mock_conn):
137134
mock_facade().Unexpose.return_value.set_result([])
138135

139136
app = Application(entity_id="app-id", model=Model())
140-
app.name = "panther"
141137
app._facade = mock_facade
142138
app._facade_version = mock_facade_version
143139

@@ -148,7 +144,7 @@ async def test_unexpose_endpoints_on_older_controller(self, mock_conn):
148144

149145
# Check that we call the facade with the right arity.
150146
await app.unexpose()
151-
mock_facade().Unexpose.assert_called_once_with(application="panther")
147+
mock_facade().Unexpose.assert_called_once_with(application="app-id")
152148

153149
@mock.patch("juju.model.Model.connection")
154150
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):
158154
mock_facade().Unexpose.return_value.set_result([])
159155

160156
app = Application(entity_id="app-id", model=Model())
161-
app.name = "panther"
162157
app._facade = mock_facade
163158
app._facade_version = mock_facade_version
164159

165160
await app.unexpose(exposed_endpoints=["alpha", "beta"])
166161

167162
mock_facade().Unexpose.assert_called_once_with(
168-
application="panther",
163+
application="app-id",
169164
exposed_endpoints=["alpha", "beta"]
170165
)
171166

0 commit comments

Comments
 (0)