from . import model
from .client import client
+from .errors import JujuError
from .placement import parse as parse_placement
log = logging.getLogger(__name__)
"""
raise NotImplementedError()
- def upgrade_charm(
+ async def upgrade_charm(
self, channel=None, force_series=False, force_units=False,
- path=None, resources=None, revision=-1, switch=None):
+ path=None, resources=None, revision=None, switch=None):
"""Upgrade the charm for this application.
:param str channel: Channel to use when getting the charm from the
:param str switch: Crossgrade charm url
"""
- raise NotImplementedError()
+ # TODO: Support local upgrades
+ if path is not None:
+ raise NotImplementedError("path option is not implemented")
+ if resources is not None:
+ raise NotImplementedError("resources option is not implemented")
+
+ if switch is not None and revision is not None:
+ raise ValueError("switch and revision are mutually exclusive")
+
+ client_facade = client.ClientFacade.from_connection(self.connection)
+ app_facade = client.ApplicationFacade.from_connection(self.connection)
+
+ if switch is not None:
+ charm_url = switch
+ if not charm_url.startswith('cs:'):
+ charm_url = 'cs:' + charm_url
+ else:
+ charm_url = self.data['charm-url']
+ charm_url = charm_url.rpartition('-')[0]
+ if revision is not None:
+ charm_url = "%s-%d" % (charm_url, revision)
+ else:
+ charmstore = self.model.charmstore
+ entity = await charmstore.entity(charm_url, channel=channel)
+ charm_url = entity['Id']
+
+ if charm_url == self.data['charm-url']:
+ raise JujuError('already running charm "%s"' % charm_url)
+
+ await client_facade.AddCharm(
+ url=charm_url,
+ channel=channel
+ )
+
+ await app_facade.SetCharm(
+ application=self.entity_id,
+ channel=channel,
+ charm_url=charm_url,
+ config_settings=None,
+ config_settings_yaml=None,
+ force_series=force_series,
+ force_units=force_units,
+ resource_ids=None,
+ storage_constraints=None
+ )
+
+ await self.model.block_until(
+ lambda: self.data['charm-url'] == charm_url
+ )
async def get_metrics(self):
"""Get metrics for this application's units.
assert len(units) == 2
for unit in units:
assert isinstance(unit, Unit)
+
+
+@base.bootstrapped
+@pytest.mark.asyncio
+async def test_upgrade_charm(event_loop):
+ async with base.CleanModel() as model:
+ app = await model.deploy('ubuntu-0')
+ assert app.data['charm-url'] == 'cs:ubuntu-0'
+ await app.upgrade_charm()
+ assert app.data['charm-url'].startswith('cs:ubuntu-')
+ assert app.data['charm-url'] != 'cs:ubuntu-0'
+
+
+@base.bootstrapped
+@pytest.mark.asyncio
+async def test_upgrade_charm_channel(event_loop):
+ async with base.CleanModel() as model:
+ app = await model.deploy('ubuntu-0')
+ assert app.data['charm-url'] == 'cs:ubuntu-0'
+ await app.upgrade_charm(channel='stable')
+ assert app.data['charm-url'].startswith('cs:ubuntu-')
+ assert app.data['charm-url'] != 'cs:ubuntu-0'
+
+
+@base.bootstrapped
+@pytest.mark.asyncio
+async def test_upgrade_charm_revision(event_loop):
+ async with base.CleanModel() as model:
+ app = await model.deploy('ubuntu-0')
+ assert app.data['charm-url'] == 'cs:ubuntu-0'
+ await app.upgrade_charm(revision=8)
+ assert app.data['charm-url'] == 'cs:ubuntu-8'
+
+
+@base.bootstrapped
+@pytest.mark.asyncio
+async def test_upgrade_charm_switch(event_loop):
+ async with base.CleanModel() as model:
+ app = await model.deploy('ubuntu-0')
+ assert app.data['charm-url'] == 'cs:ubuntu-0'
+ await app.upgrade_charm(switch='ubuntu-8')
+ assert app.data['charm-url'] == 'cs:ubuntu-8'