From a15858d934d131f410fab6b27045a83b2a2dfd37 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 31 Mar 2020 16:22:10 +1300 Subject: [PATCH] handle the 'snaps' section of the autoinstall file went through a few versions of this locally, this one is pleasingly small in delta. --- examples/autoinstall-interactive.yaml | 5 +++ subiquity/controllers/snaplist.py | 15 ++++++-- subiquity/models/snaplist.py | 50 +++++++++++++++++---------- subiquity/ui/views/snaplist.py | 10 +++--- 4 files changed, 55 insertions(+), 25 deletions(-) diff --git a/examples/autoinstall-interactive.yaml b/examples/autoinstall-interactive.yaml index e07035b0..410aa276 100644 --- a/examples/autoinstall-interactive.yaml +++ b/examples/autoinstall-interactive.yaml @@ -1,3 +1,8 @@ version: 1 interactive-sections: - keyboard + - snaps + - identity +snaps: + - name: etcd + channel: 3.2/stable diff --git a/subiquity/controllers/snaplist.py b/subiquity/controllers/snaplist.py index a4aa393a..95085049 100644 --- a/subiquity/controllers/snaplist.py +++ b/subiquity/controllers/snaplist.py @@ -119,13 +119,19 @@ class SnapListController(SubiquityController): super().__init__(app) self.loader = self._make_loader() - # XXX load_autoinstall_data / apply_autoinstall_config go here + def load_autoinstall_data(self, ai_data): + to_install = {} + for snap in ai_data: + to_install[snap['name']] = SnapSelection( + channel=snap.get('channel', 'stable'), + is_classic=snap.get('classic', False)) + self.model.set_installed_list(to_install) def snapd_network_changed(self): - # If the loader managed to load the list of snaps, the - # network must basically be working. if not self.interactive(): return + # If the loader managed to load the list of snaps, the + # network must basically be working. if self.loader.snap_list_fetched: return else: @@ -163,3 +169,6 @@ class SnapListController(SubiquityController): def cancel(self, sender=None): self.app.prev_screen() + + def make_autoinstall(self): + return self.model.to_install diff --git a/subiquity/models/snaplist.py b/subiquity/models/snaplist.py index 1c3580a9..6f43b384 100644 --- a/subiquity/models/snaplist.py +++ b/subiquity/models/snaplist.py @@ -25,13 +25,23 @@ log = logging.getLogger("subiquity.models.snaplist") @attr.s(cmp=False) class SnapInfo: name = attr.ib() - summary = attr.ib() - publisher = attr.ib() - verified = attr.ib() - description = attr.ib() - confinement = attr.ib() - license = attr.ib() + summary = attr.ib(default='') + publisher = attr.ib(default='') + verified = attr.ib(default=False) + description = attr.ib(default='') + confinement = attr.ib(default='') + license = attr.ib(default='') channels = attr.ib(default=attr.Factory(list)) + partial = attr.ib(default=True) + + def update(self, data): + self.summary = data['summary'] + self.publisher = data['developer'] + self.verified = data['publisher']['validation'] == "verified" + self.description = data['description'] + self.confinement = data['confinement'] + self.license = data['license'] + self.partial = False @attr.s(cmp=False) @@ -61,25 +71,27 @@ class SnapListModel: self._snaps_by_name = {} self.to_install = {} # snap_name -> SnapSelection + def _snap_for_name(self, name): + s = self._snaps_by_name.get(name) + if s is None: + s = self._snaps_by_name[name] = SnapInfo(name=name) + self._snap_info.append(s) + return s + def load_find_data(self, data): - for s in data['result']: - snap = SnapInfo( - name=s['name'], - summary=s['summary'], - publisher=s['developer'], - verified=s['publisher']['validation'] == "verified", - description=s['description'], - confinement=s['confinement'], - license=s['license'], - ) - self._snap_info.append(snap) - self._snaps_by_name[s['name']] = snap + for info in data['result']: + self._snap_for_name(info['name']).update(info) + + def add_partial_snap(self, name): + self._snaps_for_name(name) def load_info_data(self, data): info = data['result'][0] snap = self._snaps_by_name.get(info['name']) if snap is None: return + if snap.partial: + snap.update(info) channel_map = info['channels'] for track in info['tracks']: for risk in risks: @@ -104,4 +116,6 @@ class SnapListModel: return self._snap_info[:] def set_installed_list(self, to_install): + for name in to_install.keys(): + self._snap_for_name(name) self.to_install = to_install diff --git a/subiquity/ui/views/snaplist.py b/subiquity/ui/views/snaplist.py index 36d12cde..785d9427 100644 --- a/subiquity/ui/views/snaplist.py +++ b/subiquity/ui/views/snaplist.py @@ -309,10 +309,11 @@ class SnapCheckBox(CheckBox): False: SelectableIcon("[ ]"), } - def __init__(self, parent, snap): + def __init__(self, parent, snap, state): self.parent = parent self.snap = snap - super().__init__(snap.name, on_state_change=self.state_change) + super().__init__( + snap.name, state=state, on_state_change=self.state_change) def loaded(self): if len(self.snap.channels) == 0: # or other indication of failure @@ -370,7 +371,7 @@ class SnapListView(BaseView): def __init__(self, model, controller): self.model = model self.controller = controller - self.to_install = {} # {snap_name: (channel, is_classic)} + self.to_install = model.to_install.copy() self.load() def loaded(self): @@ -455,7 +456,8 @@ class SnapListView(BaseView): if snap.name in preinstalled: log.debug("not offering preseeded snap %r", snap.name) continue - box = self.snap_boxes[snap.name] = SnapCheckBox(self, snap) + box = self.snap_boxes[snap.name] = SnapCheckBox( + self, snap, snap.name in self.to_install) publisher = snap.publisher if snap.verified: publisher = [publisher, ('verified', '\N{check mark}')]