Skip to content

Commit 302021e

Browse files
authored
Merge pull request #820 from juanmanuel-tirado/JUJU-3348_fix_assume_parsing
#820 #### Description This fixes a problematic parsing of assumes in bundles with resources for K8s. This could Fix #766. Additionally we update the Charms facade to version 5. #### QA Steps Use the bundle mentioned in #766 ``` from juju.model import Model m = Model() await m.connect() LCM_CHARM = "osm-lcm" LCM_APP = "lcm" LCM_CHANNEL = "latest/beta" LCM_SERIES = "focal" LCM_RESOURCES = {"lcm-image": "opensourcemano/lcm:testing-daily"} await model.deploy( LCM_CHARM, resources=LCM_RESOURCES, application_name=LCM_APP, channel=LCM_CHANNEL, series=LCM_SERIES, ) ``` #### Notes & Discussion This fix has to be ported to 3.* branches.
2 parents 9598a6e + d22d48c commit 302021e

6 files changed

Lines changed: 746 additions & 13 deletions

File tree

juju/client/_client2.py

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

juju/client/_client3.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8250,6 +8250,19 @@ class MigrationMasterFacade(Type):
82508250
'agent-version',
82518251
'controller-agent-version'],
82528252
'type': 'object'},
8253+
'MigrationSourceInfo': {'additionalProperties': False,
8254+
'properties': {'addrs': {'items': {'type': 'string'},
8255+
'type': 'array'},
8256+
'ca-cert': {'type': 'string'},
8257+
'controller-alias': {'type': 'string'},
8258+
'controller-tag': {'type': 'string'},
8259+
'local-related-models': {'items': {'type': 'string'},
8260+
'type': 'array'}},
8261+
'required': ['local-related-models',
8262+
'controller-tag',
8263+
'addrs',
8264+
'ca-cert'],
8265+
'type': 'object'},
82538266
'MigrationSpec': {'additionalProperties': False,
82548267
'properties': {'model-tag': {'type': 'string'},
82558268
'target-info': {'$ref': '#/definitions/MigrationTargetInfo'}},
@@ -8449,6 +8462,14 @@ class MigrationMasterFacade(Type):
84498462
'the end user.',
84508463
'properties': {'Params': {'$ref': '#/definitions/SetMigrationStatusMessageArgs'}},
84518464
'type': 'object'},
8465+
'SourceControllerInfo': {'description': 'SourceControllerInfo '
8466+
'returns the details '
8467+
'required to connect '
8468+
'to\n'
8469+
'the source controller '
8470+
'for model migration.',
8471+
'properties': {'Result': {'$ref': '#/definitions/MigrationSourceInfo'}},
8472+
'type': 'object'},
84528473
'Watch': {'description': 'Watch starts watching for an active '
84538474
'migration for the model\n'
84548475
'associated with the API connection. '
@@ -8697,6 +8718,28 @@ async def SetStatusMessage(self, message=None):
86978718

86988719

86998720

8721+
@ReturnMapping(MigrationSourceInfo)
8722+
async def SourceControllerInfo(self):
8723+
'''
8724+
SourceControllerInfo returns the details required to connect to
8725+
the source controller for model migration.
8726+
8727+
8728+
Returns -> MigrationSourceInfo
8729+
'''
8730+
8731+
# map input types to rpc msg
8732+
_params = dict()
8733+
msg = dict(type='MigrationMaster',
8734+
request='SourceControllerInfo',
8735+
version=3,
8736+
params=_params)
8737+
8738+
reply = await self.rpc(msg)
8739+
return reply
8740+
8741+
8742+
87008743
@ReturnMapping(NotifyWatchResult)
87018744
async def Watch(self):
87028745
'''

juju/client/_definitions.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,54 @@ def __init__(self, actions=None, **unknown_fields):
400400

401401

402402

403+
class ActivateModelArgs(Type):
404+
_toSchema = {'controller_alias': 'controller-alias', 'controller_tag': 'controller-tag', 'cross_model_uuids': 'cross-model-uuids', 'model_tag': 'model-tag', 'source_api_addrs': 'source-api-addrs', 'source_ca_cert': 'source-ca-cert'}
405+
_toPy = {'controller-alias': 'controller_alias', 'controller-tag': 'controller_tag', 'cross-model-uuids': 'cross_model_uuids', 'model-tag': 'model_tag', 'source-api-addrs': 'source_api_addrs', 'source-ca-cert': 'source_ca_cert'}
406+
def __init__(self, controller_alias=None, controller_tag=None, cross_model_uuids=None, model_tag=None, source_api_addrs=None, source_ca_cert=None, **unknown_fields):
407+
'''
408+
controller_alias : str
409+
controller_tag : str
410+
cross_model_uuids : typing.Sequence[str]
411+
model_tag : str
412+
source_api_addrs : typing.Sequence[str]
413+
source_ca_cert : str
414+
'''
415+
controller_alias_ = controller_alias
416+
controller_tag_ = controller_tag
417+
cross_model_uuids_ = cross_model_uuids
418+
model_tag_ = model_tag
419+
source_api_addrs_ = source_api_addrs
420+
source_ca_cert_ = source_ca_cert
421+
422+
# Validate arguments against known Juju API types.
423+
if controller_alias_ is not None and not isinstance(controller_alias_, (bytes, str)):
424+
raise Exception("Expected controller_alias_ to be a str, received: {}".format(type(controller_alias_)))
425+
426+
if controller_tag_ is not None and not isinstance(controller_tag_, (bytes, str)):
427+
raise Exception("Expected controller_tag_ to be a str, received: {}".format(type(controller_tag_)))
428+
429+
if cross_model_uuids_ is not None and not isinstance(cross_model_uuids_, (bytes, str, list)):
430+
raise Exception("Expected cross_model_uuids_ to be a Sequence, received: {}".format(type(cross_model_uuids_)))
431+
432+
if model_tag_ is not None and not isinstance(model_tag_, (bytes, str)):
433+
raise Exception("Expected model_tag_ to be a str, received: {}".format(type(model_tag_)))
434+
435+
if source_api_addrs_ is not None and not isinstance(source_api_addrs_, (bytes, str, list)):
436+
raise Exception("Expected source_api_addrs_ to be a Sequence, received: {}".format(type(source_api_addrs_)))
437+
438+
if source_ca_cert_ is not None and not isinstance(source_ca_cert_, (bytes, str)):
439+
raise Exception("Expected source_ca_cert_ to be a str, received: {}".format(type(source_ca_cert_)))
440+
441+
self.controller_alias = controller_alias_
442+
self.controller_tag = controller_tag_
443+
self.cross_model_uuids = cross_model_uuids_
444+
self.model_tag = model_tag_
445+
self.source_api_addrs = source_api_addrs_
446+
self.source_ca_cert = source_ca_cert_
447+
self.unknown_fields = unknown_fields
448+
449+
450+
403451
class AddApplicationOffer(Type):
404452
_toSchema = {'application_description': 'application-description', 'application_name': 'application-name', 'endpoints': 'endpoints', 'model_tag': 'model-tag', 'offer_name': 'offer-name', 'owner_tag': 'owner-tag'}
405453
_toPy = {'application-description': 'application_description', 'application-name': 'application_name', 'endpoints': 'endpoints', 'model-tag': 'model_tag', 'offer-name': 'offer_name', 'owner-tag': 'owner_tag'}
@@ -15542,6 +15590,48 @@ def __init__(self, agent_version=None, controller_agent_version=None, name=None,
1554215590

1554315591

1554415592

15593+
class MigrationSourceInfo(Type):
15594+
_toSchema = {'addrs': 'addrs', 'ca_cert': 'ca-cert', 'controller_alias': 'controller-alias', 'controller_tag': 'controller-tag', 'local_related_models': 'local-related-models'}
15595+
_toPy = {'addrs': 'addrs', 'ca-cert': 'ca_cert', 'controller-alias': 'controller_alias', 'controller-tag': 'controller_tag', 'local-related-models': 'local_related_models'}
15596+
def __init__(self, addrs=None, ca_cert=None, controller_alias=None, controller_tag=None, local_related_models=None, **unknown_fields):
15597+
'''
15598+
addrs : typing.Sequence[str]
15599+
ca_cert : str
15600+
controller_alias : str
15601+
controller_tag : str
15602+
local_related_models : typing.Sequence[str]
15603+
'''
15604+
addrs_ = addrs
15605+
ca_cert_ = ca_cert
15606+
controller_alias_ = controller_alias
15607+
controller_tag_ = controller_tag
15608+
local_related_models_ = local_related_models
15609+
15610+
# Validate arguments against known Juju API types.
15611+
if addrs_ is not None and not isinstance(addrs_, (bytes, str, list)):
15612+
raise Exception("Expected addrs_ to be a Sequence, received: {}".format(type(addrs_)))
15613+
15614+
if ca_cert_ is not None and not isinstance(ca_cert_, (bytes, str)):
15615+
raise Exception("Expected ca_cert_ to be a str, received: {}".format(type(ca_cert_)))
15616+
15617+
if controller_alias_ is not None and not isinstance(controller_alias_, (bytes, str)):
15618+
raise Exception("Expected controller_alias_ to be a str, received: {}".format(type(controller_alias_)))
15619+
15620+
if controller_tag_ is not None and not isinstance(controller_tag_, (bytes, str)):
15621+
raise Exception("Expected controller_tag_ to be a str, received: {}".format(type(controller_tag_)))
15622+
15623+
if local_related_models_ is not None and not isinstance(local_related_models_, (bytes, str, list)):
15624+
raise Exception("Expected local_related_models_ to be a Sequence, received: {}".format(type(local_related_models_)))
15625+
15626+
self.addrs = addrs_
15627+
self.ca_cert = ca_cert_
15628+
self.controller_alias = controller_alias_
15629+
self.controller_tag = controller_tag_
15630+
self.local_related_models = local_related_models_
15631+
self.unknown_fields = unknown_fields
15632+
15633+
15634+
1554515635
class MigrationSpec(Type):
1554615636
_toSchema = {'model_tag': 'model-tag', 'target_info': 'target-info'}
1554715637
_toPy = {'model-tag': 'model_tag', 'target-info': 'target_info'}

juju/client/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
'CharmHub': {'versions': [1]},
3232
'CharmRevisionUpdater': {'versions': [2]},
3333
'CharmDownloader': {'versions': [1]},
34-
'Charms': {'versions': [2, 3, 4]},
34+
'Charms': {'versions': [2, 3, 4, 5]},
3535
'Cleaner': {'versions': [2]},
3636
'Client': {'versions': [1, 2]},
3737
'Cloud': {'versions': [1, 2, 3, 4, 5]},

juju/client/facade.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -675,21 +675,43 @@ def from_json(cls, data):
675675
raise
676676
if isinstance(data, list):
677677
# check: https://juju.is/docs/sdk/assumes
678-
# assumes are in the form of a list
679678
d = {}
680679
for entry in data:
681-
if '>' in entry or '>=' in entry:
682-
# something like juju >= 2.9.31
683-
i = entry.index('>')
684-
key = entry[:i].strip()
685-
value = entry[i:].strip()
686-
d[key] = value
680+
if isinstance(entry, dict):
681+
# this could be
682+
# any-of
683+
# all-of
684+
for _, v in entry.items():
685+
if isinstance(v, list):
686+
for i in v:
687+
cls.splitEntries(i, d)
688+
else:
689+
cls.splitEntries(v, d)
687690
else:
688-
# something like k8s-api
689-
d[entry] = ''
691+
# this is a simple entry
692+
cls.splitEntries(v, d)
690693
return cls(**d)
691694
return None
692695

696+
@classmethod
697+
def splitEntries(cls, entry, result_dict):
698+
'''
699+
This is an auxiliary function to be used
700+
in the from_json function to split entries
701+
like:
702+
juju >= 2.9.31
703+
k8s-api
704+
'''
705+
if '>' in entry or '>=' in entry:
706+
# something like juju >= 2.9.31
707+
i = entry.index('>')
708+
key = entry[:i].strip()
709+
value = entry[i:].strip()
710+
result_dict[key] = value
711+
else:
712+
# something like k8s-api
713+
result_dict[entry] = ''
714+
693715
def serialize(self):
694716
d = {}
695717
for attr, tgt in self._toSchema.items():

juju/client/schemas-juju-2.9.42.json

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31595,6 +31595,15 @@
3159531595
},
3159631596
"description": "SetStatusMessage sets a human readable status message containing\ninformation about the migration's progress. This will be shown in\nstatus output shown to the end user."
3159731597
},
31598+
"SourceControllerInfo": {
31599+
"type": "object",
31600+
"properties": {
31601+
"Result": {
31602+
"$ref": "#/definitions/MigrationSourceInfo"
31603+
}
31604+
},
31605+
"description": "SourceControllerInfo returns the details required to connect to\nthe source controller for model migration."
31606+
},
3159831607
"Watch": {
3159931608
"type": "object",
3160031609
"properties": {
@@ -31693,6 +31702,39 @@
3169331702
"controller-agent-version"
3169431703
]
3169531704
},
31705+
"MigrationSourceInfo": {
31706+
"type": "object",
31707+
"properties": {
31708+
"addrs": {
31709+
"type": "array",
31710+
"items": {
31711+
"type": "string"
31712+
}
31713+
},
31714+
"ca-cert": {
31715+
"type": "string"
31716+
},
31717+
"controller-alias": {
31718+
"type": "string"
31719+
},
31720+
"controller-tag": {
31721+
"type": "string"
31722+
},
31723+
"local-related-models": {
31724+
"type": "array",
31725+
"items": {
31726+
"type": "string"
31727+
}
31728+
}
31729+
},
31730+
"additionalProperties": false,
31731+
"required": [
31732+
"local-related-models",
31733+
"controller-tag",
31734+
"addrs",
31735+
"ca-cert"
31736+
]
31737+
},
3169631738
"MigrationSpec": {
3169731739
"type": "object",
3169831740
"properties": {
@@ -32193,7 +32235,7 @@
3219332235
{
3219432236
"Name": "MigrationTarget",
3219532237
"Description": "API implements the API required for the model migration\nmaster worker when communicating with the target controller.",
32196-
"Version": 1,
32238+
"Version": 2,
3219732239
"AvailableTo": [
3219832240
"controller-user"
3219932241
],
@@ -32213,10 +32255,10 @@
3221332255
"type": "object",
3221432256
"properties": {
3221532257
"Params": {
32216-
"$ref": "#/definitions/ModelArgs"
32258+
"$ref": "#/definitions/ActivateModelArgs"
3221732259
}
3221832260
},
32219-
"description": "Activate sets the migration mode of the model to \"none\", meaning it\nis ready for use. It is an error to attempt to Abort a model that\nhas a migration mode other than importing."
32261+
"description": "Activate sets the migration mode of the model to \"none\", meaning it\nis ready for use. It is an error to attempt to Abort a model that\nhas a migration mode other than importing. It also adds any required\nexternal controller records for those controllers hosting offers used\nby the model."
3222032262
},
3222132263
"AdoptResources": {
3222232264
"type": "object",
@@ -32281,6 +32323,43 @@
3228132323
}
3228232324
},
3228332325
"definitions": {
32326+
"ActivateModelArgs": {
32327+
"type": "object",
32328+
"properties": {
32329+
"controller-alias": {
32330+
"type": "string"
32331+
},
32332+
"controller-tag": {
32333+
"type": "string"
32334+
},
32335+
"cross-model-uuids": {
32336+
"type": "array",
32337+
"items": {
32338+
"type": "string"
32339+
}
32340+
},
32341+
"model-tag": {
32342+
"type": "string"
32343+
},
32344+
"source-api-addrs": {
32345+
"type": "array",
32346+
"items": {
32347+
"type": "string"
32348+
}
32349+
},
32350+
"source-ca-cert": {
32351+
"type": "string"
32352+
}
32353+
},
32354+
"additionalProperties": false,
32355+
"required": [
32356+
"model-tag",
32357+
"controller-tag",
32358+
"source-api-addrs",
32359+
"source-ca-cert",
32360+
"cross-model-uuids"
32361+
]
32362+
},
3228432363
"AdoptResourcesArgs": {
3228532364
"type": "object",
3228632365
"properties": {

0 commit comments

Comments
 (0)