github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/patch/patch6_2.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 "encoding/json" 24 "fmt" 25 "time" 26 27 "github.com/snapcore/snapd/overlord/state" 28 "github.com/snapcore/snapd/snap" 29 ) 30 31 type patch62SideInfo struct { 32 RealName string `yaml:"name,omitempty" json:"name,omitempty"` 33 SnapID string `yaml:"snap-id" json:"snap-id"` 34 Revision snap.Revision `yaml:"revision" json:"revision"` 35 Channel string `yaml:"channel,omitempty" json:"channel,omitempty"` 36 Contact string `yaml:"contact,omitempty" json:"contact,omitempty"` 37 EditedTitle string `yaml:"title,omitempty" json:"title,omitempty"` 38 EditedSummary string `yaml:"summary,omitempty" json:"summary,omitempty"` 39 EditedDescription string `yaml:"description,omitempty" json:"description,omitempty"` 40 Private bool `yaml:"private,omitempty" json:"private,omitempty"` 41 Paid bool `yaml:"paid,omitempty" json:"paid,omitempty"` 42 } 43 44 type patch62Flags struct { 45 DevMode bool `json:"devmode,omitempty"` 46 JailMode bool `json:"jailmode,omitempty"` 47 Classic bool `json:"classic,omitempty"` 48 TryMode bool `json:"trymode,omitempty"` 49 Revert bool `json:"revert,omitempty"` 50 RemoveSnapPath bool `json:"remove-snap-path,omitempty"` 51 IgnoreValidation bool `json:"ignore-validation,omitempty"` 52 Required bool `json:"required,omitempty"` 53 SkipConfigure bool `json:"skip-configure,omitempty"` 54 Unaliased bool `json:"unaliased,omitempty"` 55 Amend bool `json:"amend,omitempty"` 56 IsAutoRefresh bool `json:"is-auto-refresh,omitempty"` 57 NoReRefresh bool `json:"no-rerefresh,omitempty"` 58 RequireTypeBase bool `json:"require-base-type,omitempty"` 59 } 60 61 type patch62SnapState struct { 62 SnapType string `json:"type"` 63 Sequence []*patch62SideInfo `json:"sequence"` 64 Active bool `json:"active,omitempty"` 65 Current snap.Revision `json:"current"` 66 Channel string `json:"channel,omitempty"` 67 patch62Flags 68 Aliases interface{} `json:"aliases,omitempty"` 69 AutoAliasesDisabled bool `json:"auto-aliases-disabled,omitempty"` 70 AliasesPending bool `json:"aliases-pending,omitempty"` 71 UserID int `json:"user-id,omitempty"` 72 InstanceKey string `json:"instance-key,omitempty"` 73 CohortKey string `json:"cohort-key,omitempty"` 74 RefreshInhibitedTime *time.Time `json:"refresh-inhibited-time,omitempty"` 75 } 76 77 type patch62SnapSetup struct { 78 Channel string `json:"channel,omitempty"` 79 UserID int `json:"user-id,omitempty"` 80 Base string `json:"base,omitempty"` 81 Type snap.Type `json:"type,omitempty"` 82 PlugsOnly bool `json:"plugs-only,omitempty"` 83 CohortKey string `json:"cohort-key,omitempty"` 84 Prereq []string `json:"prereq,omitempty"` 85 patch62Flags 86 SnapPath string `json:"snap-path,omitempty"` 87 DownloadInfo interface{} `json:"download-info,omitempty"` 88 SideInfo *patch62SideInfo `json:"side-info,omitempty"` 89 patch62auxStoreInfo 90 InstanceKey string `json:"instance-key,omitempty"` 91 } 92 93 type patch62auxStoreInfo struct { 94 Media interface{} `json:"media,omitempty"` 95 } 96 97 func hasSnapdSnapID(snapst patch62SnapState) bool { 98 for _, seq := range snapst.Sequence { 99 if snap.IsSnapd(seq.SnapID) { 100 return true 101 } 102 } 103 return false 104 } 105 106 // patch6_2: 107 // - ensure snapd snaps in the snapstate have TypeSnapd for backward compatibility with old snapd snap releases. 108 // - ensure snapd snaps have TypeSnapd in pending install tasks. 109 func patch6_2(st *state.State) error { 110 var snaps map[string]*json.RawMessage 111 if err := st.Get("snaps", &snaps); err != nil && err != state.ErrNoState { 112 return fmt.Errorf("internal error: cannot get snaps: %s", err) 113 } 114 115 // Migrate snapstate 116 for name, raw := range snaps { 117 var snapst patch62SnapState 118 if err := json.Unmarshal([]byte(*raw), &snapst); err != nil { 119 return err 120 } 121 if hasSnapdSnapID(snapst) && snapst.SnapType != string(snap.TypeSnapd) { 122 snapst.SnapType = string(snap.TypeSnapd) 123 data, err := json.Marshal(snapst) 124 if err != nil { 125 return err 126 } 127 newRaw := json.RawMessage(data) 128 snaps[name] = &newRaw 129 st.Set("snaps", snaps) 130 // We can have at most one snapd snap 131 break 132 } 133 } 134 135 // migrate tasks' snap setup 136 for _, task := range st.Tasks() { 137 chg := task.Change() 138 if chg != nil && chg.Status().Ready() { 139 continue 140 } 141 142 var snapsup patch62SnapSetup 143 err := task.Get("snap-setup", &snapsup) 144 if err != nil && err != state.ErrNoState { 145 return fmt.Errorf("internal error: cannot get snap-setup of task %s: %s", task.ID(), err) 146 } 147 148 if err == nil && snapsup.SideInfo != nil { 149 if snapsup.Type != snap.TypeSnapd && snap.IsSnapd(snapsup.SideInfo.SnapID) { 150 snapsup.Type = snap.TypeSnapd 151 task.Set("snap-setup", snapsup) 152 } 153 } 154 } 155 return nil 156 }