Skip to content

Commit c44be86

Browse files
authored
Merge pull request #910 from cderici/forward-ports-from-2.9-to-3.x
#910 #### Description This brings forward from `2.9` the following PRs: #901, #905, and #896 into `3.x` (the main branch). #### QA Steps There were a couple of conflicts that needed to be fixed, so QA will be necessary, make sure the following tests are passing: ``` tox -e integration -- tests/integration/test_application.py::test_app_charm_name ``` ``` tox -e py3 -- -m wait_for_idle ``` ``` tox -e integration -- -m wait_for_idle ``` ```sh tox -e integration -- tests/integration/test_model.py::test_deploy_bundle_local_charm_series_manifest ```
2 parents fabb5d5 + 0e55ac8 commit c44be86

11 files changed

Lines changed: 181 additions & 21 deletions

File tree

juju/application.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,19 @@ async def run(self, command, timeout=None):
567567
units=[],
568568
)
569569

570+
@property
571+
def charm_name(self):
572+
"""Get the charm name of this application
573+
574+
:return str: The name of the charm
575+
"""
576+
return URL.parse(self.charm_url).name
577+
570578
@property
571579
def charm_url(self):
572-
"""Get the charm url for a given application
580+
"""Get the charm url for this application
573581
574-
:return string: The charm url for an application
582+
:return str: The charm url
575583
"""
576584
return self.safe_data['charm-url']
577585

juju/bundle.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ async def _handle_local_charms(self, bundle, bundle_dir):
129129
if not series:
130130
metadata = utils.get_local_charm_metadata(charm_dir)
131131
series = await get_charm_series(metadata, self.model)
132-
if not self.model.connection().is_using_old_client and not series:
132+
if not series:
133+
base = utils.get_local_charm_base(None, charm_path, client.Base)
134+
series = utils.base_channel_to_series(base.channel)
135+
if not series:
133136
raise JujuError(
134137
"Couldn't determine series for charm at {}. "
135138
"Add a 'series' key to the bundle.".format(charm_dir))

juju/model.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,12 +2709,24 @@ def _raise_for_status(entities, status):
27092709
if raise_on_blocked and unit.workload_status == "blocked":
27102710
blocks.setdefault("Unit", []).append(unit.name)
27112711
continue
2712-
waiting_for_a_particular_status = status and unit.workload_status != status
2713-
if not waiting_for_a_particular_status and unit.agent_status == "idle":
2714-
# We'll be here in two cases:
2715-
# 1) We're not waiting for a particular status and the agent is "idle"
2716-
# 2) We're waiting for a particular status and the workload is in that
2717-
# status
2712+
# TODO (cderici): we need two versions of wait_for_idle, one for waiting on
2713+
# individual units, another one for waiting for an application.
2714+
# The convoluted logic below is the result of trying to do both at the same
2715+
# time
2716+
need_to_wait_more_for_a_particular_status = status and (unit.workload_status != status)
2717+
app_is_in_desired_status = (not status) or (app_status == status)
2718+
if not need_to_wait_more_for_a_particular_status and \
2719+
unit.agent_status == "idle" and \
2720+
(wait_for_at_least_units or app_is_in_desired_status):
2721+
# A unit is ready if either:
2722+
# 1) Don't need to wait more for a particular status and the agent is "idle"
2723+
# 2) We're looking for a particular status and the unit's workload,
2724+
# as well as the application, is in that status. If the user wants to
2725+
# see only a particular number of units in that state -- i.e. a subset of
2726+
# the units is needed, then we don't care about the application status
2727+
# (because e.g. app can be in 'waiting' while unit.0 is 'active' and unit.1
2728+
# is 'waiting')
2729+
27182730
# Either way, the unit is ready, start measuring the time period that
27192731
# it needs to stay in that state (i.e. idle_period)
27202732
units_ready.add(unit.name)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
applications:
2+
test1:
3+
charm: "../charm-manifest"
4+
num_units: 1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
options:
2+
status:
3+
type: string
4+
default: "active"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
status="$(config-get status)"
4+
5+
if [[ "$status" == "error" ]]; then
6+
if [[ -e .errored ]]; then
7+
status="active"
8+
else
9+
touch .errored
10+
exit 1
11+
fi
12+
fi
13+
status-set "$status"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
analysis:
2+
attributes:
3+
- name: language
4+
result: python
5+
- name: framework
6+
result: operator
7+
bases:
8+
- architectures:
9+
- amd64
10+
channel: '20.04'
11+
name: ubuntu
12+
charmcraft-started-at: '2021-08-20T08:09:00.639806Z'
13+
charmcraft-version: 1.2.1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name: charm
2+
summary: "test"
3+
description: "test"
4+
maintainers: ["test"]

tests/integration/test_application.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,13 @@ async def test_app_remove_wait_flag(event_loop):
297297

298298
await model.remove_application(app.name, block_until_done=True)
299299
assert a_name not in model.applications
300+
301+
302+
@base.bootstrapped
303+
@pytest.mark.asyncio
304+
async def test_app_charm_name(event_loop):
305+
async with base.CleanModel() as model:
306+
app = await model.deploy('ubuntu')
307+
await model.wait_for_idle(status="active")
308+
assert 'ubuntu' in app.charm_url
309+
assert 'ubuntu' == app.charm_name

tests/integration/test_model.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,20 @@ async def test_deploy_bundle_local_charms(event_loop):
178178
assert model.units['test2/0'].workload_status == 'active'
179179

180180

181+
@base.bootstrapped
182+
@pytest.mark.asyncio
183+
@pytest.mark.bundle
184+
async def test_deploy_bundle_local_charm_series_manifest(event_loop):
185+
bundle_path = INTEGRATION_TEST_DIR / 'bundle' / 'local-manifest.yaml'
186+
187+
async with base.CleanModel() as model:
188+
await model.deploy(bundle_path)
189+
await wait_for_bundle(model, bundle_path)
190+
assert set(model.units.keys()) == set(['test1/0'])
191+
assert model.units['test1/0'].agent_status == 'idle'
192+
assert model.units['test1/0'].workload_status == 'active'
193+
194+
181195
@base.bootstrapped
182196
@pytest.mark.asyncio
183197
@pytest.mark.bundle
@@ -848,12 +862,12 @@ async def test_get_machines(event_loop):
848862

849863
@base.bootstrapped
850864
@pytest.mark.asyncio
865+
@pytest.mark.wait_for_idle
851866
async def test_wait_for_idle_without_units(event_loop):
852867
async with base.CleanModel() as model:
853868
await model.deploy(
854869
'ubuntu',
855870
application_name='ubuntu',
856-
series='bionic',
857871
channel='stable',
858872
num_units=0,
859873
)
@@ -863,12 +877,12 @@ async def test_wait_for_idle_without_units(event_loop):
863877

864878
@base.bootstrapped
865879
@pytest.mark.asyncio
880+
@pytest.mark.wait_for_idle
866881
async def test_wait_for_idle_with_not_enough_units(event_loop):
867882
async with base.CleanModel() as model:
868883
await model.deploy(
869884
'ubuntu',
870885
application_name='ubuntu',
871-
series='bionic',
872886
channel='stable',
873887
num_units=2,
874888
)
@@ -878,6 +892,7 @@ async def test_wait_for_idle_with_not_enough_units(event_loop):
878892

879893
@base.bootstrapped
880894
@pytest.mark.asyncio
895+
@pytest.mark.wait_for_idle
881896
async def test_wait_for_idle_more_units_than_needed(event_loop):
882897
async with base.CleanModel() as model:
883898
charm_path = TESTS_DIR / 'charm'
@@ -900,13 +915,13 @@ async def test_wait_for_idle_more_units_than_needed(event_loop):
900915

901916
@base.bootstrapped
902917
@pytest.mark.asyncio
918+
@pytest.mark.wait_for_idle
903919
async def test_wait_for_idle_with_enough_units(event_loop):
904920
pytest.skip("This is testing juju functionality")
905921
async with base.CleanModel() as model:
906922
await model.deploy(
907923
'ubuntu',
908924
application_name='ubuntu',
909-
series='jammy',
910925
channel='stable',
911926
num_units=3,
912927
)
@@ -915,13 +930,13 @@ async def test_wait_for_idle_with_enough_units(event_loop):
915930

916931
@base.bootstrapped
917932
@pytest.mark.asyncio
933+
@pytest.mark.wait_for_idle
918934
async def test_wait_for_idle_with_exact_units(event_loop):
919935
pytest.skip("This is testing juju functionality")
920936
async with base.CleanModel() as model:
921937
await model.deploy(
922938
'ubuntu',
923939
application_name='ubuntu',
924-
series='jammy',
925940
channel='stable',
926941
num_units=2,
927942
)
@@ -930,6 +945,7 @@ async def test_wait_for_idle_with_exact_units(event_loop):
930945

931946
@base.bootstrapped
932947
@pytest.mark.asyncio
948+
@pytest.mark.wait_for_idle
933949
async def test_wait_for_idle_with_exact_units_scale_down(event_loop):
934950
"""Deploys 3 units, waits for them to be idle, then removes 2 of them,
935951
then waits for exactly 1 unit to be left.

0 commit comments

Comments
 (0)