github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/assertstate/validation_set_tracking.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 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 assertstate 21 22 import ( 23 "encoding/json" 24 "fmt" 25 26 "github.com/snapcore/snapd/overlord/state" 27 ) 28 29 // ValidationSetMode reflects the mode of respective validation set, which is 30 // either monitoring or enforcing. 31 type ValidationSetMode int 32 33 const ( 34 Monitor ValidationSetMode = iota 35 Enforce 36 ) 37 38 // ValidationSetTracking holds tracking parameters for associated validation set. 39 type ValidationSetTracking struct { 40 AccountID string `json:"account-id"` 41 Name string `json:"name"` 42 Mode ValidationSetMode `json:"mode"` 43 44 // PinnedAt is an optional pinned sequence point, or 0 if not pinned. 45 PinnedAt int `json:"pinned-at,omitempty"` 46 47 // Current is the current sequence point. 48 Current int `json:"current,omitempty"` 49 50 // LocalOnly indicates that the assertion was only available locally at the 51 // time it was applied for monitor mode. This tells bulk refresh logic not 52 // to error out on such assertion if it's not in the store. 53 // This flag makes sense only in monitor mode and if pinned. 54 LocalOnly bool `json:"local-only,omitempty"` 55 } 56 57 // ValidationSetKey formats the given account id and name into a validation set key. 58 func ValidationSetKey(accountID, name string) string { 59 return fmt.Sprintf("%s/%s", accountID, name) 60 } 61 62 // UpdateValidationSet updates ValidationSetTracking. 63 // The method assumes valid tr fields. 64 func UpdateValidationSet(st *state.State, tr *ValidationSetTracking) { 65 var vsmap map[string]*json.RawMessage 66 err := st.Get("validation-sets", &vsmap) 67 if err != nil && err != state.ErrNoState { 68 panic("internal error: cannot unmarshal validation set tracking state: " + err.Error()) 69 } 70 if vsmap == nil { 71 vsmap = make(map[string]*json.RawMessage) 72 } 73 data, err := json.Marshal(tr) 74 if err != nil { 75 panic("internal error: cannot marshal validation set tracking state: " + err.Error()) 76 } 77 raw := json.RawMessage(data) 78 key := ValidationSetKey(tr.AccountID, tr.Name) 79 vsmap[key] = &raw 80 st.Set("validation-sets", vsmap) 81 } 82 83 // DeleteValidationSet deletes a validation set for the given accoundID and name. 84 // It is not an error to delete a non-existing one. 85 func DeleteValidationSet(st *state.State, accountID, name string) { 86 var vsmap map[string]*json.RawMessage 87 err := st.Get("validation-sets", &vsmap) 88 if err != nil && err != state.ErrNoState { 89 panic("internal error: cannot unmarshal validation set tracking state: " + err.Error()) 90 } 91 if len(vsmap) == 0 { 92 return 93 } 94 delete(vsmap, ValidationSetKey(accountID, name)) 95 st.Set("validation-sets", vsmap) 96 } 97 98 // GetValidationSet retrieves the ValidationSetTracking for the given account and name. 99 func GetValidationSet(st *state.State, accountID, name string, tr *ValidationSetTracking) error { 100 if tr == nil { 101 return fmt.Errorf("internal error: tr is nil") 102 } 103 104 *tr = ValidationSetTracking{} 105 106 var vset map[string]*json.RawMessage 107 err := st.Get("validation-sets", &vset) 108 if err != nil { 109 return err 110 } 111 key := ValidationSetKey(accountID, name) 112 raw, ok := vset[key] 113 if !ok { 114 return state.ErrNoState 115 } 116 // XXX: &tr pointer isn't needed here but it is likely historical (a bug in 117 // old JSON marshaling probably) and carried over from snapstate.Get. 118 err = json.Unmarshal([]byte(*raw), &tr) 119 if err != nil { 120 return fmt.Errorf("cannot unmarshal validation set tracking state: %v", err) 121 } 122 return nil 123 } 124 125 // ValidationSets retrieves all ValidationSetTracking data. 126 func ValidationSets(st *state.State) (map[string]*ValidationSetTracking, error) { 127 var vsmap map[string]*ValidationSetTracking 128 if err := st.Get("validation-sets", &vsmap); err != nil && err != state.ErrNoState { 129 return nil, err 130 } 131 return vsmap, nil 132 }