Skip to content

Commit 66e5cc3

Browse files
committed
Utilize the series selector to construct the correct base for charms
The main change is in the _resolve_charm that's used in the model and bundle deploy code path. We pass in the series info whenever we can into the ResolveCharm call, then use its result to run the series selector, then construct the base using that and finally pass the origin to the AddCharm. Note that the ResolveCharm API call is made no more than once.
1 parent 75e40a4 commit 66e5cc3

2 files changed

Lines changed: 38 additions & 22 deletions

File tree

juju/bundle.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from . import utils, jasyncio
1818
from .origin import Channel, Source
1919
from .url import Schema, URL
20+
from .utils import get_base_from_origin_or_channel
2021

2122
log = logging.getLogger(__name__)
2223

@@ -350,11 +351,13 @@ async def _resolve_charms(self):
350351

351352
charm_url = URL.parse(spec['charm'])
352353
channel = None
353-
series = spec.get('series', None)
354+
base = None
354355
track, risk = '', ''
355356
if 'channel' in spec:
356357
channel = Channel.parse(spec['channel'])
357358
track, risk = channel.track, channel.risk
359+
series = spec.get('series', None)
360+
base = get_base_from_origin_or_channel(channel, series)
358361

359362
if self.charms_facade is not None:
360363
if cons is not None and cons['arch'] != '':
@@ -365,14 +368,18 @@ async def _resolve_charms(self):
365368
origin = client.CharmOrigin(source=Source.CHARM_HUB.value,
366369
architecture=architecture,
367370
risk=risk,
368-
track=track)
371+
track=track,
372+
base=base,
373+
)
369374

370375
charm_url, charm_origin = await self.model._resolve_charm(charm_url, origin)
371376
spec['charm'] = str(charm_url)
372377
else:
373378
charm_origin = client.CharmOrigin(source=Source.CHARM_HUB.value,
374379
risk=risk,
375-
track=track)
380+
track=track,
381+
base=base,
382+
)
376383

377384
if str(channel) not in self.origins:
378385
self.origins[str(charm_url)] = {}
@@ -713,10 +720,12 @@ async def run(self, context):
713720
arch = self.architecture
714721
if not arch:
715722
arch = await context.model._resolve_architecture(url)
723+
base = get_base_from_origin_or_channel(ch, self.series)
716724
origin = client.CharmOrigin(source=Source.CHARM_HUB.value,
717725
architecture=arch,
718726
risk=ch.risk,
719-
track=ch.track)
727+
track=ch.track,
728+
base=base)
720729
identifier, origin = await context.model._resolve_charm(url, origin)
721730

722731
if identifier is None:

juju/model.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,10 @@ class LocalDeployType:
441441
"""LocalDeployType deals with local only deployments.
442442
"""
443443

444-
async def resolve(self, url, architecture, app_name=None, channel=None, series=None, revision=None, entity_url=None, force=False):
444+
async def resolve(self, url, architecture,
445+
app_name=None, channel=None, series=None,
446+
revision=None, entity_url=None, force=False,
447+
model_conf=None):
445448
"""resolve attempts to resolve a local charm or bundle using the url
446449
and architecture. If information is missing, it will attempt to backfill
447450
that information, before sending the result back.
@@ -485,6 +488,7 @@ async def resolve(self, url, architecture, app_name=None, channel=None, series=N
485488
is_bundle=is_bundle,
486489
)
487490

491+
488492
class CharmhubDeployType:
489493
"""CharmhubDeployType defines a class for resolving and deploying charmhub
490494
charms and bundles.
@@ -493,7 +497,10 @@ class CharmhubDeployType:
493497
def __init__(self, charm_resolver):
494498
self.charm_resolver = charm_resolver
495499

496-
async def resolve(self, url, architecture, app_name=None, channel=None, series=None, revision=None, entity_url=None, force=False):
500+
async def resolve(self, url, architecture,
501+
app_name=None, channel=None, series=None,
502+
revision=None, entity_url=None, force=False,
503+
model_conf=None):
497504
"""resolve attempts to resolve charmhub charms or bundles. A request to
498505
the charmhub API is required to correctly determine the charm url and
499506
underlying origin.
@@ -515,16 +522,14 @@ async def resolve(self, url, architecture, app_name=None, channel=None, series=N
515522
track=ch.track,
516523
base=base,
517524
revision=revision,
518-
series=series
519525
)
520526

527+
charm_url, origin = await self.charm_resolver(url, origin, force, series, model_conf)
528+
521529
is_bundle = origin.type_ == "bundle"
522530
if is_bundle and revision and channel:
523531
raise JujuError('revision and channel are mutually exclusive when deploying a bundle. Please choose one.')
524532

525-
526-
charm_url, origin = await self.charm_resolver(url, origin, force)
527-
528533
if app_name is None:
529534
app_name = url.name
530535

@@ -1679,7 +1684,12 @@ async def deploy(
16791684
if str(url.schema) not in self.deploy_types:
16801685
raise JujuError("unknown deploy type {}, expected charmhub or local".format(url.schema))
16811686

1682-
res = await self.deploy_types[str(url.schema)].resolve(url, architecture, application_name, channel, series, revision, entity_url, force)
1687+
model_conf = await self.get_config()
1688+
res = await self.deploy_types[str(url.schema)].resolve(url, architecture,
1689+
application_name, channel,
1690+
series, revision,
1691+
entity_url, force,
1692+
model_conf)
16831693

16841694
if res.identifier is None:
16851695
raise JujuError('unknown charm or bundle {}'.format(entity_url))
@@ -1790,7 +1800,7 @@ async def _add_charm(self, charm_url, origin):
17901800
client_facade = client.ClientFacade.from_connection(self.connection())
17911801
return await client_facade.AddCharm(channel=str(origin.risk), url=charm_url, force=False)
17921802

1793-
async def _resolve_charm(self, url, origin, force=False):
1803+
async def _resolve_charm(self, url, origin, force=False, series=None, model_config=None):
17941804
"""Calls Charms.ResolveCharms to resolve all the fields of the
17951805
charm_origin and also the url and the supported_series
17961806
@@ -1817,8 +1827,7 @@ async def _resolve_charm(self, url, origin, force=False):
18171827

18181828
resolve_origin = {'source': source, 'architecture': origin.architecture,
18191829
'track': origin.track, 'risk': origin.risk,
1820-
'base': origin.base, 'series': origin.series,
1821-
'revision': origin.revision,
1830+
'base': origin.base, 'revision': origin.revision,
18221831
}
18231832

18241833
resp = await charms_facade.ResolveCharms(resolve=[{
@@ -1833,15 +1842,13 @@ async def _resolve_charm(self, url, origin, force=False):
18331842
raise JujuError(result.error.message)
18341843

18351844
supported_series = result.supported_series
1845+
resolved_origin = result.charm_origin
18361846
charm_url = URL.parse(result.url)
1837-
if origin.series:
1838-
# Check whether the charm supports this series
1839-
# or we force it
1840-
if origin.series in supported_series or force:
1841-
result.charm_origin.series = origin.series
1842-
charm_url.series = origin.series
1843-
else:
1844-
raise JujuError("Series {} not supported for {}. Only {}".format(origin.series, result.url, supported_series))
1847+
1848+
# run the series selector to get a series for the base
1849+
selected_series = utils.series_selector(series, url, model_config, supported_series, force)
1850+
result.charm_origin.base = utils.get_base_from_origin_or_channel(resolved_origin, selected_series)
1851+
charm_url.series = selected_series
18451852

18461853
return result.url, result.charm_origin
18471854

0 commit comments

Comments
 (0)