Skip to content

Commit d6e9ca5

Browse files
authored
Merge pull request #706 from cderici/fix-facade-issues-1
#706 #### Description This change attempts to fix the `Unit.run_actions` issue where the resulting object is different based on the used Facade (which is based on whether the `2.9` or `3.0` juju client is being used). With this change both ways will return the same type of object as a result of running the action on the unit. It's also a continuation/possible-regression-fix of #698. Also adding the `EnvironUpgrader` facade that's introduced in `Juju 3.0`, so we shouldn't get the "unexpected facade" warning anymore. Also updating the clients with the latest schema from juju 3.0. In particuılar the Application facade version is bumped up `13` -> `14`. With this #705 should be fixed too. #### QA Steps QA steps for this is sort of a simulation of one of the real world libjuju uses in a function on [mongodb-operator](https://github.com/canonical/mongodb-operator/blob/8796be02e10b84f990da0426ad1cff5922dc506a/tests/integration/helpers.py#L39). Get a controller on a k8s cloud (I did it on `microk8s`). The following then should work fine. Full QA should be done with 2 separate controllers (at least that's what I did): one bootstrapped with `juju 2.9` and another with `juju 3.0`. ```python async def _get_password(): model = Model() await model.connect() await model.deploy('zinc-k8s') await model.wait_for_idle(status="active") unit = model.applications['zinc-k8s'].units[0] action = await unit.run_action("get-admin-password") action = await action.wait() print(action.results["admin-password"]) await model.disconnect() ``` #### Notes & Discussion This is also related (and most likely a fix) to: * openstack-charmers/zaza#545 * openstack-charmers/zaza#546 * https://github.com/canonical/mongodb-operator/runs/7761747331?check_suite_focus=true
2 parents 1dd9cbf + 5a88c66 commit d6e9ca5

20 files changed

Lines changed: 66725 additions & 76467 deletions

juju/action.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22

33

44
class Action(model.ModelEntity):
5+
6+
def __init__(self, entity_id, model, history_index=-1, connected=True):
7+
super().__init__(entity_id, model, history_index, connected)
8+
self.results = {}
9+
510
@property
611
def status(self):
712
return self.data['status']
813

914
async def wait(self):
10-
return await self.model.get_action_output(self.id)
15+
self.results = await self.model.get_action_output(self.id)
16+
return self

juju/client/_client.py

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,21 @@
44
from juju.client._definitions import *
55

66

7-
from juju.client import _client2, _client1, _client3, _client4, _client5, _client8, _client7, _client9, _client10, _client6, _client12, _client11, _client13, _client15, _client16, _client17, _client18, _client14
7+
from juju.client import _client7, _client1, _client3, _client2, _client14, _client4, _client6, _client5, _client11, _client9, _client18
88

99

1010
CLIENTS = {
11-
"2": _client2,
11+
"7": _client7,
1212
"1": _client1,
1313
"3": _client3,
14+
"2": _client2,
15+
"14": _client14,
1416
"4": _client4,
15-
"5": _client5,
16-
"8": _client8,
17-
"7": _client7,
18-
"9": _client9,
19-
"10": _client10,
2017
"6": _client6,
21-
"12": _client12,
18+
"5": _client5,
2219
"11": _client11,
23-
"13": _client13,
24-
"15": _client15,
25-
"16": _client16,
26-
"17": _client17,
27-
"18": _client18,
28-
"14": _client14
20+
"9": _client9,
21+
"18": _client18
2922
}
3023

3124

@@ -127,10 +120,6 @@ class ApplicationOffersFacade(TypeFactory):
127120
pass
128121

129122

130-
class ApplicationRelationsWatcherFacade(TypeFactory):
131-
pass
132-
133-
134123
class ApplicationScalerFacade(TypeFactory):
135124
pass
136125

@@ -247,10 +236,6 @@ class DeployerFacade(TypeFactory):
247236
pass
248237

249238

250-
class DiscoverSpacesFacade(TypeFactory):
251-
pass
252-
253-
254239
class DiskManagerFacade(TypeFactory):
255240
pass
256241

@@ -455,10 +440,6 @@ class RelationUnitsWatcherFacade(TypeFactory):
455440
pass
456441

457442

458-
class RemoteApplicationWatcherFacade(TypeFactory):
459-
pass
460-
461-
462443
class RemoteRelationWatcherFacade(TypeFactory):
463444
pass
464445

@@ -467,10 +448,6 @@ class RemoteRelationsFacade(TypeFactory):
467448
pass
468449

469450

470-
class RemoteRelationsWatcherFacade(TypeFactory):
471-
pass
472-
473-
474451
class ResourcesFacade(TypeFactory):
475452
pass
476453

juju/client/_client1.py

Lines changed: 7031 additions & 14300 deletions
Large diffs are not rendered by default.

juju/client/_client11.py

Lines changed: 0 additions & 1548 deletions
Large diffs are not rendered by default.

juju/client/_client14.py

Lines changed: 4 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,6 @@ class ApplicationFacade(Type):
216216
'remote',
217217
'life'],
218218
'type': 'object'},
219-
'ApplicationSet': {'additionalProperties': False,
220-
'properties': {'application': {'type': 'string'},
221-
'branch': {'type': 'string'},
222-
'options': {'patternProperties': {'.*': {'type': 'string'}},
223-
'type': 'object'}},
224-
'required': ['application',
225-
'branch',
226-
'options'],
227-
'type': 'object'},
228219
'ApplicationSetCharm': {'additionalProperties': False,
229220
'properties': {'application': {'type': 'string'},
230221
'channel': {'type': 'string'},
@@ -799,12 +790,6 @@ class ApplicationFacade(Type):
799790
'properties': {'Params': {'$ref': '#/definitions/ApplicationGet'},
800791
'Result': {'$ref': '#/definitions/ApplicationGetResults'}},
801792
'type': 'object'},
802-
'GetCharmURL': {'description': 'GetCharmURL returns the charm '
803-
'URL the given application is\n'
804-
'running at present.',
805-
'properties': {'Params': {'$ref': '#/definitions/ApplicationGet'},
806-
'Result': {'$ref': '#/definitions/StringResult'}},
807-
'type': 'object'},
808793
'GetCharmURLOrigin': {'description': 'GetCharmURLOrigin '
809794
'returns the charm URL '
810795
'and charm origin the '
@@ -853,20 +838,13 @@ class ApplicationFacade(Type):
853838
'properties': {'Params': {'$ref': '#/definitions/ScaleApplicationsParams'},
854839
'Result': {'$ref': '#/definitions/ScaleApplicationResults'}},
855840
'type': 'object'},
856-
'Set': {'description': 'Set implements the server side of '
857-
'Application.Set.\n'
858-
'It does not unset values that are set '
859-
'to an empty string.\n'
860-
'Unset should be used for that.',
861-
'properties': {'Params': {'$ref': '#/definitions/ApplicationSet'}},
862-
'type': 'object'},
863841
'SetCharm': {'description': 'SetCharm sets the charm for a '
864842
'given for the application.',
865843
'properties': {'Params': {'$ref': '#/definitions/ApplicationSetCharm'}},
866844
'type': 'object'},
867-
'SetConfigs': {'description': 'SetConfig implements the server '
868-
'side of Application.SetConfig. '
869-
'Both\n'
845+
'SetConfigs': {'description': 'SetConfigs implements the '
846+
'server side of '
847+
'Application.SetConfig. Both\n'
870848
'application and charm config '
871849
'are set. It does not unset '
872850
'values in\n'
@@ -908,10 +886,6 @@ class ApplicationFacade(Type):
908886
'properties': {'Params': {'$ref': '#/definitions/Entities'},
909887
'Result': {'$ref': '#/definitions/UnitInfoResults'}},
910888
'type': 'object'},
911-
'Unset': {'description': 'Unset implements the server side of '
912-
'Client.Unset.',
913-
'properties': {'Params': {'$ref': '#/definitions/ApplicationUnset'}},
914-
'type': 'object'},
915889
'UnsetApplicationsConfig': {'description': 'UnsetApplicationsConfig '
916890
'implements the '
917891
'server side of '
@@ -1350,35 +1324,6 @@ async def Get(self, application=None, branch=None):
13501324

13511325

13521326

1353-
@ReturnMapping(StringResult)
1354-
async def GetCharmURL(self, application=None, branch=None):
1355-
'''
1356-
GetCharmURL returns the charm URL the given application is
1357-
running at present.
1358-
1359-
application : str
1360-
branch : str
1361-
Returns -> StringResult
1362-
'''
1363-
if application is not None and not isinstance(application, (bytes, str)):
1364-
raise Exception("Expected application to be a str, received: {}".format(type(application)))
1365-
1366-
if branch is not None and not isinstance(branch, (bytes, str)):
1367-
raise Exception("Expected branch to be a str, received: {}".format(type(branch)))
1368-
1369-
# map input types to rpc msg
1370-
_params = dict()
1371-
msg = dict(type='Application',
1372-
request='GetCharmURL',
1373-
version=14,
1374-
params=_params)
1375-
_params['application'] = application
1376-
_params['branch'] = branch
1377-
reply = await self.rpc(msg)
1378-
return reply
1379-
1380-
1381-
13821327
@ReturnMapping(CharmURLOriginResult)
13831328
async def GetCharmURLOrigin(self, application=None, branch=None):
13841329
'''
@@ -1557,41 +1502,6 @@ async def ScaleApplications(self, applications=None):
15571502

15581503

15591504

1560-
@ReturnMapping(None)
1561-
async def Set(self, application=None, branch=None, options=None):
1562-
'''
1563-
Set implements the server side of Application.Set.
1564-
It does not unset values that are set to an empty string.
1565-
Unset should be used for that.
1566-
1567-
application : str
1568-
branch : str
1569-
options : typing.Mapping[str, str]
1570-
Returns -> None
1571-
'''
1572-
if application is not None and not isinstance(application, (bytes, str)):
1573-
raise Exception("Expected application to be a str, received: {}".format(type(application)))
1574-
1575-
if branch is not None and not isinstance(branch, (bytes, str)):
1576-
raise Exception("Expected branch to be a str, received: {}".format(type(branch)))
1577-
1578-
if options is not None and not isinstance(options, dict):
1579-
raise Exception("Expected options to be a Mapping, received: {}".format(type(options)))
1580-
1581-
# map input types to rpc msg
1582-
_params = dict()
1583-
msg = dict(type='Application',
1584-
request='Set',
1585-
version=14,
1586-
params=_params)
1587-
_params['application'] = application
1588-
_params['branch'] = branch
1589-
_params['options'] = options
1590-
reply = await self.rpc(msg)
1591-
return reply
1592-
1593-
1594-
15951505
@ReturnMapping(None)
15961506
async def SetCharm(self, application=None, channel=None, charm_origin=None, charm_url=None, config_settings=None, config_settings_yaml=None, endpoint_bindings=None, force=None, force_series=None, force_units=None, generation=None, resource_ids=None, storage_constraints=None):
15971507
'''
@@ -1678,7 +1588,7 @@ async def SetCharm(self, application=None, channel=None, charm_origin=None, char
16781588
@ReturnMapping(ErrorResults)
16791589
async def SetConfigs(self, args=None):
16801590
'''
1681-
SetConfig implements the server side of Application.SetConfig. Both
1591+
SetConfigs implements the server side of Application.SetConfig. Both
16821592
application and charm config are set. It does not unset values in
16831593
Config map that are set to an empty string. Unset should be used for that.
16841594
@@ -1827,39 +1737,6 @@ async def UnitsInfo(self, entities=None):
18271737

18281738

18291739

1830-
@ReturnMapping(None)
1831-
async def Unset(self, application=None, branch=None, options=None):
1832-
'''
1833-
Unset implements the server side of Client.Unset.
1834-
1835-
application : str
1836-
branch : str
1837-
options : typing.Sequence[str]
1838-
Returns -> None
1839-
'''
1840-
if application is not None and not isinstance(application, (bytes, str)):
1841-
raise Exception("Expected application to be a str, received: {}".format(type(application)))
1842-
1843-
if branch is not None and not isinstance(branch, (bytes, str)):
1844-
raise Exception("Expected branch to be a str, received: {}".format(type(branch)))
1845-
1846-
if options is not None and not isinstance(options, (bytes, str, list)):
1847-
raise Exception("Expected options to be a Sequence, received: {}".format(type(options)))
1848-
1849-
# map input types to rpc msg
1850-
_params = dict()
1851-
msg = dict(type='Application',
1852-
request='Unset',
1853-
version=14,
1854-
params=_params)
1855-
_params['application'] = application
1856-
_params['branch'] = branch
1857-
_params['options'] = options
1858-
reply = await self.rpc(msg)
1859-
return reply
1860-
1861-
1862-
18631740
@ReturnMapping(ErrorResults)
18641741
async def UnsetApplicationsConfig(self, args=None):
18651742
'''

0 commit comments

Comments
 (0)