gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/overlord/patch/patch6_1.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package patch 21 22 import ( 23 "github.com/snapcore/snapd/interfaces" 24 "github.com/snapcore/snapd/overlord/state" 25 "github.com/snapcore/snapd/snap" 26 ) 27 28 type connStatePatch6_1 struct { 29 Auto bool `json:"auto,omitempty"` 30 ByGadget bool `json:"by-gadget,omitempty"` 31 Interface string `json:"interface,omitempty"` 32 Undesired bool `json:"undesired,omitempty"` 33 StaticPlugAttrs map[string]interface{} `json:"plug-static,omitempty"` 34 DynamicPlugAttrs map[string]interface{} `json:"plug-dynamic,omitempty"` 35 StaticSlotAttrs map[string]interface{} `json:"slot-static,omitempty"` 36 DynamicSlotAttrs map[string]interface{} `json:"slot-dynamic,omitempty"` 37 } 38 39 // processConns updates conns map and augments it with plug-static and slot-static attributes from current snap info. 40 // NOTE: missing snap or missing plugs/slots are ignored and not reported as errors as we might have stale connections 41 // and ifacemgr deals with them (i.e. discards) on startup; we want to process all good slots and plugs here. 42 func processConns(conns map[string]connStatePatch6_1, infos map[string]*snap.Info) (bool, error) { 43 var updated bool 44 for id, conn := range conns { 45 // static attributes already present 46 if len(conn.StaticPlugAttrs) > 0 || len(conn.StaticSlotAttrs) > 0 { 47 continue 48 } 49 50 // undesired connections have all their attributes dropped, so don't set them 51 if conn.Undesired { 52 continue 53 } 54 55 connRef, err := interfaces.ParseConnRef(id) 56 if err != nil { 57 return false, err 58 } 59 60 var ok bool 61 var plugSnapInfo, slotSnapInfo *snap.Info 62 63 // read current snap info from disk and keep it around in infos map 64 if plugSnapInfo, ok = infos[connRef.PlugRef.Snap]; !ok { 65 plugSnapInfo, err = snap.ReadCurrentInfo(connRef.PlugRef.Snap) 66 if err == nil { 67 infos[connRef.PlugRef.Snap] = plugSnapInfo 68 } 69 } 70 if slotSnapInfo, ok = infos[connRef.SlotRef.Snap]; !ok { 71 slotSnapInfo, err = snap.ReadCurrentInfo(connRef.SlotRef.Snap) 72 if err == nil { 73 infos[connRef.SlotRef.Snap] = slotSnapInfo 74 } 75 } 76 77 if slotSnapInfo != nil { 78 if slot, ok := slotSnapInfo.Slots[connRef.SlotRef.Name]; ok && slot.Attrs != nil { 79 conn.StaticSlotAttrs = slot.Attrs 80 updated = true 81 } 82 } 83 84 if plugSnapInfo != nil { 85 if plug, ok := plugSnapInfo.Plugs[connRef.PlugRef.Name]; ok && plug.Attrs != nil { 86 conn.StaticPlugAttrs = plug.Attrs 87 updated = true 88 } 89 } 90 91 conns[id] = conn 92 } 93 94 return updated, nil 95 } 96 97 // patch6_1: 98 // - add static plug and slot attributes to connections that miss them. Attributes are read from current snap info. 99 func patch6_1(st *state.State) error { 100 infos := make(map[string]*snap.Info) 101 102 // update all pending "discard-conns" tasks as they may keep connection data in "removed". 103 for _, task := range st.Tasks() { 104 if task.Change().Status().Ready() { 105 continue 106 } 107 108 var removed map[string]connStatePatch6_1 109 if task.Kind() == "discard-conns" { 110 err := task.Get("removed", &removed) 111 if err == state.ErrNoState { 112 continue 113 } 114 if err != nil { 115 return err 116 } 117 } 118 119 updated, err := processConns(removed, infos) 120 if err != nil { 121 return err 122 } 123 124 if updated { 125 task.Set("removed", removed) 126 } 127 } 128 129 // update conns 130 var conns map[string]connStatePatch6_1 131 err := st.Get("conns", &conns) 132 if err == state.ErrNoState { 133 // no connections to process 134 return nil 135 } 136 if err != nil { 137 return err 138 } 139 140 updated, err := processConns(conns, infos) 141 if err != nil { 142 return err 143 } 144 if updated { 145 st.Set("conns", conns) 146 } 147 148 return nil 149 }