Skip to content

Commit e12896b

Browse files
Merge pull request #664 from oEscal/bug/bundle/channel-default-value
Fixed the bundle run when the channel is None
2 parents 3186b78 + 3947073 commit e12896b

2 files changed

Lines changed: 128 additions & 3 deletions

File tree

juju/bundle.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,26 @@ async def run(self, context):
586586
options["trust"] = "true"
587587

588588
url = URL.parse(str(charm))
589+
590+
# set the channel to the default value if not specified
591+
if not self.channel:
592+
if Schema.CHARM_STORE.matches(url.schema):
593+
self.channel = "stable"
594+
elif Schema.CHARM_HUB.matches(url.schema):
595+
self.channel = "latest/stable"
596+
else: # for local charms
597+
self.channel = ""
598+
589599
channel = None
600+
non_normalized_channel = None
590601
if self.channel is not None and self.channel != "":
591-
channel = Channel.parse(self.channel).normalize()
602+
non_normalized_channel = Channel.parse(self.channel)
603+
channel = non_normalized_channel.normalize()
592604

593-
origin = context.origins.get(str(url), {}).get(str(channel), None)
605+
origin = context.origins.get(str(url), {}).get(
606+
str(channel),
607+
context.origins.get(str(url), {}).get(str(non_normalized_channel), None),
608+
)
594609
if origin is None:
595610
raise JujuError("expected origin to be valid for application {} and charm {} with channel {}".format(self.application, str(url), str(channel)))
596611

tests/unit/test_bundle.py

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,64 @@ async def test_run_with_charmstore_charm(self, event_loop):
224224
model._add_store_resources.assert_called_once()
225225
model._deploy.assert_called_once()
226226

227+
@pytest.mark.asyncio
228+
async def test_run_with_charmstore_charm_no_channel(self, event_loop):
229+
"""Test to verify if when the given channel is None, the channel defaults to "stable", which
230+
is the default channel value for the Chart Store
231+
"""
232+
233+
change = AddApplicationChange(1, [], params={"charm": "cs:charm",
234+
"series": "series",
235+
"application": "application",
236+
"options": "options",
237+
"constraints": "constraints",
238+
"storage": "storage",
239+
"endpoint-bindings": "endpoint_bindings",
240+
"resources": "resources",
241+
"devices": "devices",
242+
"num-units": "num_units",
243+
"channel": None})
244+
245+
model = mock.Mock()
246+
model._deploy = base.AsyncMock(return_value=None)
247+
model._add_store_resources = base.AsyncMock(return_value=["resource1"])
248+
model.applications = {}
249+
250+
context = mock.Mock()
251+
context.resolve.return_value = "cs:charm1"
252+
context.origins = {"cs:charm1": {"stable": {}}}
253+
context.trusted = False
254+
context.model = model
255+
256+
result = await change.run(context)
257+
assert result == "application"
258+
259+
model._add_store_resources.assert_called_once()
260+
model._add_store_resources.assert_called_with("application",
261+
"cs:charm1",
262+
overrides="resources")
263+
264+
model._deploy.assert_called_once()
265+
model._deploy.assert_called_with(charm_url="cs:charm1",
266+
application="application",
267+
series="series",
268+
config="options",
269+
constraints="constraints",
270+
endpoint_bindings="endpoint_bindings",
271+
resources=["resource1"],
272+
storage="storage",
273+
devices="devices",
274+
channel="stable",
275+
charm_origin=ANY,
276+
num_units="num_units")
277+
278+
# confirm that it's idempotent
279+
model.applications = {"application": None}
280+
result = await change.run(context)
281+
assert result == "application"
282+
model._add_store_resources.assert_called_once()
283+
model._deploy.assert_called_once()
284+
227285
@pytest.mark.asyncio
228286
async def test_run_with_charmhub_charm(self, event_loop):
229287
change = AddApplicationChange(1, [], params={"charm": "charm",
@@ -272,6 +330,58 @@ async def test_run_with_charmhub_charm(self, event_loop):
272330
charm_origin=ANY,
273331
num_units="num_units")
274332

333+
@pytest.mark.asyncio
334+
async def test_run_with_charmhub_charm_no_channel(self, event_loop):
335+
"""Test to verify if when the given channel is None, the channel defaults to "local/stable", which
336+
is the default channel value for the Charm Hub
337+
"""
338+
change = AddApplicationChange(1, [], params={"charm": "charm",
339+
"series": "series",
340+
"application": "application",
341+
"options": "options",
342+
"constraints": "constraints",
343+
"storage": "storage",
344+
"endpoint-bindings": "endpoint_bindings",
345+
"resources": "resources",
346+
"devices": "devices",
347+
"num-units": "num_units",
348+
"channel": None
349+
})
350+
351+
model = Mock()
352+
model._deploy = base.AsyncMock(return_value=None)
353+
model._add_charmhub_resources = base.AsyncMock(return_value=["resource1"])
354+
model.applications = {}
355+
356+
context = Mock()
357+
context.resolve.return_value = "ch:charm1"
358+
context.origins = {"ch:charm1": {"stable": Mock()}}
359+
context.trusted = False
360+
context.model = model
361+
362+
info = Mock()
363+
info.result.id_ = "12345"
364+
info.errors.error_list.code = ''
365+
info_func = base.AsyncMock(return_value=info)
366+
367+
with patch.object(charmhub.CharmHub, 'info', info_func):
368+
result = await change.run(context)
369+
assert result == "application"
370+
371+
model._deploy.assert_called_once()
372+
model._deploy.assert_called_with(charm_url="ch:charm1",
373+
application="application",
374+
series="series",
375+
config="options",
376+
constraints="constraints",
377+
endpoint_bindings="endpoint_bindings",
378+
resources=["resource1"],
379+
storage="storage",
380+
devices="devices",
381+
channel="latest/stable",
382+
charm_origin=ANY,
383+
num_units="num_units")
384+
275385
@pytest.mark.asyncio
276386
async def test_run_local(self, event_loop):
277387
change = AddApplicationChange(1, [], params={"charm": "local:charm",
@@ -308,7 +418,7 @@ async def test_run_local(self, event_loop):
308418
storage="storage",
309419
devices="devices",
310420
num_units="num_units",
311-
channel=None,
421+
channel="",
312422
charm_origin=ANY)
313423

314424
@pytest.mark.asyncio

0 commit comments

Comments
 (0)