|
15 | 15 | import asyncio |
16 | 16 | import json |
17 | 17 | import logging |
| 18 | +import os |
18 | 19 |
|
19 | | -from . import model, tag |
| 20 | +from . import model, tag, utils |
20 | 21 | from .status import derive_status |
21 | 22 | from .annotationhelper import _get_annotations, _set_annotations |
22 | 23 | from .client import client |
23 | 24 | from .errors import JujuError |
| 25 | +from .bundle import get_charm_series |
24 | 26 | from .placement import parse as parse_placement |
25 | 27 |
|
26 | 28 | log = logging.getLogger(__name__) |
@@ -586,9 +588,10 @@ async def refresh( |
586 | 588 | :param str switch: Crossgrade charm url |
587 | 589 |
|
588 | 590 | """ |
589 | | - # TODO: Support local upgrades |
590 | 591 | if path is not None: |
591 | | - raise NotImplementedError("path option is not implemented") |
| 592 | + await self.local_refresh(channel, force, force_series, force_units, |
| 593 | + path, resources) |
| 594 | + return |
592 | 595 | if resources is not None: |
593 | 596 | raise NotImplementedError("resources option is not implemented") |
594 | 597 |
|
@@ -692,6 +695,61 @@ async def refresh( |
692 | 695 |
|
693 | 696 | upgrade_charm = refresh |
694 | 697 |
|
| 698 | + async def local_refresh( |
| 699 | + self, channel=None, force=False, force_series=False, force_units=False, |
| 700 | + path=None, resources=None): |
| 701 | + """Refresh the charm for this application with a local charm. |
| 702 | +
|
| 703 | + :param str channel: Channel to use when getting the charm from the |
| 704 | + charm store, e.g. 'development' |
| 705 | + :param bool force_series: Refresh even if series of deployed |
| 706 | + application is not supported by the new charm |
| 707 | + :param bool force_units: Refresh all units immediately, even if in |
| 708 | + error state |
| 709 | + :param str path: Refresh to a charm located at path |
| 710 | + :param dict resources: Dictionary of resource name/filepath pairs |
| 711 | + :param int revision: Explicit refresh revision |
| 712 | + :param str switch: Crossgrade charm url |
| 713 | +
|
| 714 | + """ |
| 715 | + app_facade = self._facade() |
| 716 | + |
| 717 | + charm_dir = os.path.abspath( |
| 718 | + os.path.expanduser(path)) |
| 719 | + model_config = await self.get_config() |
| 720 | + |
| 721 | + series = get_charm_series(charm_dir) |
| 722 | + if not series: |
| 723 | + model_config = await self.get_config() |
| 724 | + default_series = model_config.get("default-series") |
| 725 | + if default_series: |
| 726 | + series = default_series.value |
| 727 | + charm_url = await self.model.add_local_charm_dir(charm_dir, series) |
| 728 | + metadata = utils.get_local_charm_metadata(path) |
| 729 | + if resources is not None: |
| 730 | + resources = await self.model.add_local_resources(self.entity_id, |
| 731 | + charm_url, |
| 732 | + metadata, |
| 733 | + resources=resources) |
| 734 | + |
| 735 | + # Update application |
| 736 | + await app_facade.SetCharm( |
| 737 | + application=self.entity_id, |
| 738 | + channel=channel, |
| 739 | + charm_url=charm_url, |
| 740 | + config_settings=None, |
| 741 | + config_settings_yaml=None, |
| 742 | + force=force, |
| 743 | + force_series=force_series, |
| 744 | + force_units=force_units, |
| 745 | + resource_ids=resources, |
| 746 | + storage_constraints=None, |
| 747 | + ) |
| 748 | + |
| 749 | + await self.model.block_until( |
| 750 | + lambda: self.data['charm-url'] == charm_url |
| 751 | + ) |
| 752 | + |
695 | 753 | async def get_metrics(self): |
696 | 754 | """Get metrics for this application's units. |
697 | 755 |
|
|
0 commit comments