Skip to content

Commit c22f799

Browse files
authored
Merge branch 'master' into wait-for-at-least-units-param-rename
2 parents c07128a + b067dc1 commit c22f799

4 files changed

Lines changed: 119 additions & 12 deletions

File tree

juju/application.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -749,11 +749,10 @@ async def refresh(
749749
}
750750

751751
# Compute the difference btw resources needed and the existing resources
752-
resources_to_update = [
753-
resource for resource in charm_resources
754-
if resource.get('Name', resource.get('name')) not in existing_resources or
755-
existing_resources[resource.get('Name', resource.get('name'))].origin != 'upload'
756-
]
752+
resources_to_update = []
753+
for resource in charm_resources:
754+
if utils.should_upgrade_resource(resource, existing_resources):
755+
resources_to_update.append(resource)
757756

758757
# Update the resources
759758
if resources_to_update:

juju/utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,3 +523,30 @@ def series_selector(series_arg='', charm_url=None, model_config=None, supported_
523523
# Charm hasn't specified a default (likely due to being a local charm
524524
# deployed by path). Last chance, best we can do is default to LTS.
525525
return DEFAULT_SUPPORTED_LTS
526+
527+
528+
def should_upgrade_resource(available_resource, existing_resources):
529+
"""Called in the context of upgrade_charm. Given a resource R, takes a look at the resources we
530+
already have and decides if we need to refresh R.
531+
532+
:param dict[str] available_resource: The dict representing the client.Resource coming from the
533+
charmhub api. We're considering if we need to refresh this during upgrade_charm.
534+
:param dict[str] existing_resources: The dict coming from resources_facade.ListResources
535+
representing the resources of the currently deployed charm.
536+
537+
:result bool: The decision to refresh the given resource
538+
"""
539+
# should upgrade resource?
540+
res_name = available_resource.get('Name', available_resource.get('name'))
541+
# no, if it's upload
542+
if existing_resources[res_name].origin == 'upload':
543+
return False
544+
545+
# no, if we already have it (and upstream doesn't have a newer res available)
546+
if res_name in existing_resources:
547+
available_rev = available_resource.get('Revision', available_resource.get('revision', -1))
548+
u_fields = existing_resources[res_name].unknown_fields
549+
existing_rev = u_fields.get('Revision', u_fields.get('revision', -1))
550+
if existing_rev >= available_rev:
551+
return False
552+
return True

tests/integration/test_application.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,17 @@ async def test_upgrade_local_charm_resource(event_loop):
245245
assert ress['file-res']
246246

247247

248+
@base.bootstrapped
249+
@pytest.mark.asyncio
250+
async def test_upgrade_charm_resource_same_rev_no_update(event_loop):
251+
async with base.CleanModel() as model:
252+
app = await model.deploy('keystone', channel='victoria/stable')
253+
ress = await app.get_resources()
254+
await app.refresh(channel='ussuri/stable')
255+
ress2 = await app.get_resources()
256+
assert ress['policyd-override'].fingerprint == ress2['policyd-override'].fingerprint
257+
258+
248259
@base.bootstrapped
249260
@pytest.mark.asyncio
250261
async def test_trusted(event_loop):

tests/unit/test_utils.py

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
import pytest
33

44
from juju.utils import series_selector, get_base_from_origin_or_channel, \
5-
parse_base_arg, juju_config_dir, juju_ssh_key_paths, \
6-
DEFAULT_SUPPORTED_LTS, get_series_version, get_version_series, \
7-
base_channel_to_series, base_channel_from_series, \
8-
get_os_from_series
9-
from juju.client import client
5+
parse_base_arg, DEFAULT_SUPPORTED_LTS, get_series_version, \
6+
get_version_series, base_channel_to_series, \
7+
base_channel_from_series, get_os_from_series
108
from juju.errors import JujuError
119
from juju.url import URL
10+
from juju import utils
11+
from juju.client import client
1212

1313

1414
class TestDirResolve(unittest.TestCase):
1515
def test_config_dir(self):
16-
config_dir = juju_config_dir()
16+
config_dir = utils.juju_config_dir()
1717
assert 'local/share/juju' in config_dir
1818

1919
def test_juju_ssh_key_paths(self):
20-
public, private = juju_ssh_key_paths()
20+
public, private = utils.juju_ssh_key_paths()
2121
assert public.endswith('ssh/juju_id_rsa.pub')
2222
assert private.endswith('ssh/juju_id_rsa')
2323

@@ -73,3 +73,73 @@ def test_get_os_from_series(self):
7373
def test_get_base_from_series(self):
7474
orgn = client.CharmOrigin(track='latest', risk='edge')
7575
assert get_base_from_origin_or_channel(orgn, series='jammy') == client.Base('22.04/edge', 'ubuntu')
76+
77+
78+
class TestShouldUpgradeResource(unittest.TestCase):
79+
def test_should_upgrade_resource_no_same_rev(self):
80+
# fields are trimmed for readability
81+
res = {'created-at': '2019-10-24T20:45:19.201000',
82+
'description': 'The policy.d overrides file',
83+
'download': {'hash-sha-256': 'e3b0c4', 'hash-sha-384': '38b060a751ac914898b95b',
84+
'hash-sha-512': 'cf83e1357eef1a538327af927da3e',
85+
'hash-sha3-384': '0c63a75b1bbed1e058d5f004',
86+
'size': 0,
87+
'url': 'https://api.charmhub.io/api/v1/resMGU0L516cGTTwNam.policyd-override_0'},
88+
'filename': 'policyd-override.zip', 'name': 'policyd-override', 'revision': 0, 'type': 'file'}
89+
90+
existing = {
91+
'policyd-override':
92+
client.Resource(charmresource=None,
93+
application='keystone', id_='keystone/policyd-override', pending_id='',
94+
timestamp='0001-01-01T00:00:00Z', username='', name='policyd-override',
95+
origin='store', type='file', path='policyd-override.zip',
96+
description='The policy.doverrides file',
97+
revision=0, fingerprint='OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb',
98+
size=0)}
99+
assert not utils.should_upgrade_resource(res, existing)
100+
101+
def test_should_upgrade_resource_no_local_upload(self):
102+
# fields are trimmed for readability
103+
res = {'created-at': '2019-10-24T20:45:19.201000',
104+
'description': 'The policy.d overrides file',
105+
'download': {'hash-sha-256': 'e3b0c4', 'hash-sha-384': '38b060a751ac914898b95b',
106+
'hash-sha-512': 'cf83e1357eef1a538327af927da3e',
107+
'hash-sha3-384': '0c63a75b1bbed1e058d5f004',
108+
'size': 0,
109+
'url': 'https://api.charmhub.io/api/v1/resMGU0L516cGTTwNam.policyd-override_0'},
110+
'filename': 'policyd-override.zip', 'name': 'local_res', 'revision': 0,
111+
'type': 'file'}
112+
113+
existing = {
114+
'local_res':
115+
client.Resource(charmresource=None,
116+
application='keystone', id_='keystone/policyd-override', pending_id='',
117+
timestamp='0001-01-01T00:00:00Z', username='', name='policyd-override',
118+
origin='upload', type='file', path='policyd-override.zip',
119+
description='The policy.doverrides file',
120+
revision=0, fingerprint='OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb',
121+
size=0)}
122+
assert not utils.should_upgrade_resource(res, existing)
123+
124+
def test_should_upgrade_resource_yes_new_revision(self):
125+
# fields are trimmed for readability
126+
res = {'created-at': '2019-10-24T20:45:19.201000',
127+
'description': 'The policy.d overrides file',
128+
'download': {'hash-sha-256': 'e3b0c4', 'hash-sha-384': '38b060a751ac914898b95b',
129+
'hash-sha-512': 'cf83e1357eef1a538327af927da3e',
130+
'hash-sha3-384': '0c63a75b1bbed1e058d5f004',
131+
'size': 0,
132+
'url': 'https://api.charmhub.io/api/v1/resMGU0L516cGTTwNam.policyd-override_0'},
133+
'filename': 'policyd-override.zip', 'name': 'policyd-override', 'revision': 1,
134+
'type': 'file'}
135+
136+
existing = {
137+
'policyd-override':
138+
client.Resource(charmresource=None,
139+
application='keystone', id_='keystone/policyd-override', pending_id='',
140+
timestamp='0001-01-01T00:00:00Z', username='', name='policyd-override',
141+
origin='store', type='file', path='policyd-override.zip',
142+
description='The policy.doverrides file',
143+
revision=0, fingerprint='OLBgp1GsljhM2TJ+sbHjaiH9txEUvgdDTAzHv2P24donTt6/529l+9Ua0vFImLlb',
144+
size=0)}
145+
assert utils.should_upgrade_resource(res, existing)

0 commit comments

Comments
 (0)