github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/patch/patch6_3.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 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 "encoding/json" 24 "fmt" 25 26 "github.com/snapcore/snapd/logger" 27 "github.com/snapcore/snapd/overlord/state" 28 "github.com/snapcore/snapd/snap/channel" 29 ) 30 31 // normChan will take a potentially unclean channel from the state 32 // (with leading or trailing extra "/") and return a cleaned version. 33 func normChan(in string) string { 34 out, err := channel.Full(in) 35 if err != nil { 36 logger.Noticef("cannot parse channel string %q: %v", in, err) 37 return in 38 } 39 return out 40 } 41 42 // patch6_3: 43 // - ensure channel spec is valid 44 func patch6_3(st *state.State) error { 45 var snaps map[string]*json.RawMessage 46 if err := st.Get("snaps", &snaps); err != nil && err != state.ErrNoState { 47 return fmt.Errorf("internal error: cannot get snaps: %s", err) 48 } 49 50 // Migrate snapstate 51 dirty := false 52 for name, raw := range snaps { 53 var snapst map[string]interface{} 54 if err := json.Unmarshal([]byte(*raw), &snapst); err != nil { 55 return err 56 } 57 ch, _ := snapst["channel"].(string) 58 if ch != "" { 59 normed := normChan(ch) 60 if normed != ch { 61 snapst["channel"] = normed 62 data, err := json.Marshal(snapst) 63 if err != nil { 64 return err 65 } 66 newRaw := json.RawMessage(data) 67 snaps[name] = &newRaw 68 dirty = true 69 } 70 } 71 } 72 if dirty { 73 st.Set("snaps", snaps) 74 } 75 76 // migrate tasks' snap setup 77 for _, task := range st.Tasks() { 78 chg := task.Change() 79 if chg != nil && chg.Status().Ready() { 80 continue 81 } 82 83 // check task snap-setup 84 var snapsup map[string]interface{} 85 err := task.Get("snap-setup", &snapsup) 86 if err != nil && err != state.ErrNoState { 87 return fmt.Errorf("internal error: cannot get snap-setup of task %s: %s", task.ID(), err) 88 } 89 if err == nil { 90 ch, _ := snapsup["channel"].(string) 91 if ch != "" { 92 normed := normChan(ch) 93 if normed != ch { 94 snapsup["channel"] = normed 95 task.Set("snap-setup", snapsup) 96 } 97 } 98 } 99 // check tasks "old-channel" data 100 var oldCh string 101 task.Get("old-channel", &oldCh) 102 if oldCh != "" { 103 normed := normChan(oldCh) 104 if normed != oldCh { 105 task.Set("old-channel", normed) 106 } 107 } 108 } 109 110 return nil 111 }