github.com/rigado/snapd@v2.42.5-go-mod+incompatible/overlord/configstate/configcore/refresh.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017-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 configcore 21 22 import ( 23 "fmt" 24 "strconv" 25 "time" 26 27 "github.com/snapcore/snapd/overlord/configstate/config" 28 "github.com/snapcore/snapd/overlord/devicestate" 29 "github.com/snapcore/snapd/strutil" 30 "github.com/snapcore/snapd/timeutil" 31 ) 32 33 func init() { 34 supportedConfigurations["core.refresh.hold"] = true 35 supportedConfigurations["core.refresh.schedule"] = true 36 supportedConfigurations["core.refresh.timer"] = true 37 supportedConfigurations["core.refresh.metered"] = true 38 supportedConfigurations["core.refresh.retain"] = true 39 supportedConfigurations["core.refresh.rate-limit"] = true 40 } 41 42 func validateRefreshSchedule(tr config.Conf) error { 43 refreshRetainStr, err := coreCfg(tr, "refresh.retain") 44 if err != nil { 45 return err 46 } 47 if refreshRetainStr != "" { 48 if n, err := strconv.ParseUint(refreshRetainStr, 10, 8); err != nil || (n < 2 || n > 20) { 49 return fmt.Errorf("retain must be a number between 2 and 20, not %q", refreshRetainStr) 50 } 51 } 52 53 refreshHoldStr, err := coreCfg(tr, "refresh.hold") 54 if err != nil { 55 return err 56 } 57 if refreshHoldStr != "" { 58 if _, err := time.Parse(time.RFC3339, refreshHoldStr); err != nil { 59 return fmt.Errorf("refresh.hold cannot be parsed: %v", err) 60 } 61 } 62 63 refreshOnMeteredStr, err := coreCfg(tr, "refresh.metered") 64 if err != nil { 65 return err 66 } 67 switch refreshOnMeteredStr { 68 case "", "hold": 69 // noop 70 default: 71 return fmt.Errorf("refresh.metered value %q is invalid", refreshOnMeteredStr) 72 } 73 74 // check (new) refresh.timer 75 refreshTimerStr, err := coreCfg(tr, "refresh.timer") 76 if err != nil { 77 return err 78 } 79 if refreshTimerStr == "managed" { 80 st := tr.State() 81 st.Lock() 82 defer st.Unlock() 83 84 if !devicestate.CanManageRefreshes(st) { 85 return fmt.Errorf("cannot set schedule to managed") 86 } 87 return nil 88 } 89 if refreshTimerStr != "" { 90 // try legacy refresh.schedule setting if new-style 91 // refresh.timer is not set 92 if _, err = timeutil.ParseSchedule(refreshTimerStr); err != nil { 93 return err 94 } 95 } 96 97 // check (legacy) refresh.schedule 98 refreshScheduleStr, err := coreCfg(tr, "refresh.schedule") 99 if err != nil { 100 return err 101 } 102 if refreshScheduleStr == "" { 103 return nil 104 } 105 106 if refreshScheduleStr == "managed" { 107 st := tr.State() 108 st.Lock() 109 defer st.Unlock() 110 111 if !devicestate.CanManageRefreshes(st) { 112 return fmt.Errorf("cannot set schedule to managed") 113 } 114 return nil 115 } 116 117 _, err = timeutil.ParseLegacySchedule(refreshScheduleStr) 118 return err 119 } 120 121 func validateRefreshRateLimit(tr config.Conf) error { 122 refreshRateLimit, err := coreCfg(tr, "refresh.rate-limit") 123 if err != nil { 124 return err 125 } 126 // reset is fine 127 if len(refreshRateLimit) == 0 { 128 return nil 129 } 130 if _, err := strutil.ParseByteSize(refreshRateLimit); err != nil { 131 return err 132 } 133 return nil 134 }