github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/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 51 // ValidationSetKey formats the given account id and name into a validation set key. 52 func ValidationSetKey(accountID, name string) string { 53 return fmt.Sprintf("%s/%s", accountID, name) 54 } 55 56 // UpdateValidationSet updates ValidationSetTracking. 57 // The method assumes valid tr fields. 58 func UpdateValidationSet(st *state.State, tr *ValidationSetTracking) { 59 var vsmap map[string]*json.RawMessage 60 err := st.Get("validation-sets", &vsmap) 61 if err != nil && err != state.ErrNoState { 62 panic("internal error: cannot unmarshal validation set tracking state: " + err.Error()) 63 } 64 if vsmap == nil { 65 vsmap = make(map[string]*json.RawMessage) 66 } 67 data, err := json.Marshal(tr) 68 if err != nil { 69 panic("internal error: cannot marshal validation set tracking state: " + err.Error()) 70 } 71 raw := json.RawMessage(data) 72 key := ValidationSetKey(tr.AccountID, tr.Name) 73 vsmap[key] = &raw 74 st.Set("validation-sets", vsmap) 75 } 76 77 // DeleteValidationSet deletes a validation set for the given accoundID and name. 78 // It is not an error to delete a non-existing one. 79 func DeleteValidationSet(st *state.State, accountID, name string) { 80 var vsmap map[string]*json.RawMessage 81 err := st.Get("validation-sets", &vsmap) 82 if err != nil && err != state.ErrNoState { 83 panic("internal error: cannot unmarshal validation set tracking state: " + err.Error()) 84 } 85 if len(vsmap) == 0 { 86 return 87 } 88 delete(vsmap, ValidationSetKey(accountID, name)) 89 st.Set("validation-sets", vsmap) 90 return 91 } 92 93 // GetValidationSet retrieves the ValidationSetTracking for the given account and name. 94 func GetValidationSet(st *state.State, accountID, name string, tr *ValidationSetTracking) error { 95 if tr == nil { 96 return fmt.Errorf("internal error: tr is nil") 97 } 98 99 *tr = ValidationSetTracking{} 100 101 var vset map[string]*json.RawMessage 102 err := st.Get("validation-sets", &vset) 103 if err != nil { 104 return err 105 } 106 key := ValidationSetKey(accountID, name) 107 raw, ok := vset[key] 108 if !ok { 109 return state.ErrNoState 110 } 111 // XXX: &tr pointer isn't needed here but it is likely historical (a bug in 112 // old JSON marshaling probably) and carried over from snapstate.Get. 113 err = json.Unmarshal([]byte(*raw), &tr) 114 if err != nil { 115 return fmt.Errorf("cannot unmarshal validation set tracking state: %v", err) 116 } 117 return nil 118 } 119 120 // ValidationSets retrieves all ValidationSetTracking data. 121 func ValidationSets(st *state.State) (map[string]*ValidationSetTracking, error) { 122 var vsmap map[string]*ValidationSetTracking 123 if err := st.Get("validation-sets", &vsmap); err != nil && err != state.ErrNoState { 124 return nil, err 125 } 126 return vsmap, nil 127 }