Merge ~kwmonroe/layer-snap:feature/snapd-refresh into ~stub/layer-snap:master

Proposed by Kevin W Monroe
Status: Merged
Merged at revision: 7d8eb64030161e7451db5968bae7d4874ae87353
Proposed branch: ~kwmonroe/layer-snap:feature/snapd-refresh
Merge into: ~stub/layer-snap:master
Diff against target: 156 lines (+94/-1)
4 files modified
README.md (+40/-1)
config.yaml (+9/-0)
lib/charms/layer/snap.py (+36/-0)
reactive/snap.py (+9/-0)
Reviewer Review Type Date Requested Status
Stuart Bishop Approve
Review via email: mp+349067@code.launchpad.net

Commit message

Support a new 'snapd_refresh' config option, which sets the snapd refresh.timer option.

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote :

This all looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/README.md b/README.md
index 254649a..1ba2ebe 100644
--- a/README.md
+++ b/README.md
@@ -86,13 +86,52 @@ have been installed, so you do not need to worry about installation
86order.86order.
8787
8888
89### Snap Refresh
90
91By default, the `snapd` daemon will query the Snap Store four (4)
92times per day to process updates for installed snaps. This layer provides
93a charm configuration option for authors and operators to control this
94refresh frequency.
95
96>NOTE: this is a global configuration option and will affect the refresh
97time for all snaps installed on a system.
98
99>NOTE: requires snapd 2.31 or higher.
100
101Examples:
102
103```sh
104## refresh snaps every tuesday
105juju config telegraf snapd_refresh="tue"
106
107## refresh snaps at 11pm on the last (5th) friday of the month
108juju config telegraf snapd_refresh="fri5,23:00"
109
110## use the system default refresh timer
111juju config telegraf snapd_refresh=""
112```
113
114Currently, the `snapd` refresh timer may be delayed up to one (1) month. This
115can be configured using the `max` option:
116
117```sh
118## delay snap refreshes as long as possible
119juju config telegraf snapd_refresh="max"
120```
121
122For more information on the possible values for `snapd_refresh`, see the
123*refresh.timer* section in the [system options][] documentation.
124
125[system options]: https://forum.snapcraft.io/t/system-options/87
126
127
89## Usage128## Usage
90129
91If you have defined your snaps in layer.yaml for automatic installation130If you have defined your snaps in layer.yaml for automatic installation
92and updates, there is nothing further to do.131and updates, there is nothing further to do.
93132
94### API133### API
95 134
96If your charm need to control installation, update and removal of snaps135If your charm need to control installation, update and removal of snaps
97itself, the following methods are available via the `charms.layer.snap`136itself, the following methods are available via the `charms.layer.snap`
98package::137package::
diff --git a/config.yaml b/config.yaml
index 754d46a..939cf3d 100644
--- a/config.yaml
+++ b/config.yaml
@@ -25,3 +25,12 @@ options:
25 description: |25 description: |
26 The address of a Snappy Enterprise Proxy to use for snaps26 The address of a Snappy Enterprise Proxy to use for snaps
27 e.g. http://snap-proxy.example.com27 e.g. http://snap-proxy.example.com
28 snapd_refresh:
29 default: ""
30 type: string
31 description: |
32 How often snapd handles updates for installed snaps. The default
33 (an empty string) is 4x per day. Set to "max" to check once per month
34 based on the charm deployment date. You may also set a custom string as
35 described in the 'refresh.timer' section here:
36 https://forum.snapcraft.io/t/system-options/87
diff --git a/lib/charms/layer/snap.py b/lib/charms/layer/snap.py
index 80e94e4..be32056 100644
--- a/lib/charms/layer/snap.py
+++ b/lib/charms/layer/snap.py
@@ -22,6 +22,7 @@ from charms import layer
22from charms import reactive22from charms import reactive
23from charms.reactive.helpers import any_file_changed, data_changed23from charms.reactive.helpers import any_file_changed, data_changed
24from time import sleep24from time import sleep
25from datetime import datetime, timedelta
2526
2627
27def install(snapname, **kw):28def install(snapname, **kw):
@@ -178,6 +179,41 @@ def set(snapname, key, value):
178 ['snap', 'set', snapname, '{}={}'.format(key, value)])179 ['snap', 'set', snapname, '{}={}'.format(key, value)])
179180
180181
182def set_refresh_timer(timer=''):
183 '''Set the system refresh.timer option (snapd 2.31+)
184
185 This method sets how often snapd will refresh installed snaps. Call with
186 an empty timer string to use the system default (currently 4x per day).
187 Use 'max' to schedule refreshes as far into the future as possible
188 (currently 1 month). Also accepts custom timer strings as defined in the
189 refresh.timer section here:
190 https://forum.snapcraft.io/t/system-options/87
191
192 This method does not validate custom strings and will lead to a
193 CalledProcessError if an invalid string is given.
194
195 :param: timer: empty string (default), 'max', or custom string
196 '''
197 if timer == 'max':
198 # A month from yesterday is the farthest we should delay to safely stay
199 # under the 1 month max. Translate that to a valid refresh.timer value.
200 # Examples:
201 # - Today is Friday the 13th, set the refresh timer to
202 # 'thu2' (Thursday the 12th is the 2nd thursday of the month).
203 # - Today is Tuesday the 1st, set the refresh timer to
204 # 'mon5' (Monday the [28..31] is the 5th monday of the month).
205 yesterday = datetime.now() - timedelta(1)
206 dow = yesterday.strftime('%a').lower()
207 # increment after int division because we want occurrence 1-5, not 0-4.
208 occurrence = yesterday.day // 7 + 1
209 timer = '{}{}'.format(dow, occurrence)
210
211 # NB: 'system' became synonymous with 'core' in 2.32.5, but we use 'core'
212 # here to ensure max compatibility.
213 set(snapname='core', key='refresh.timer', value=timer)
214 subprocess.check_call(['systemctl', 'restart', 'snapd.service'])
215
216
181def get(snapname, key):217def get(snapname, key):
182 '''Gets configuration options for a snap218 '''Gets configuration options for a snap
183219
diff --git a/reactive/snap.py b/reactive/snap.py
index 884dc63..d646527 100644
--- a/reactive/snap.py
+++ b/reactive/snap.py
@@ -31,6 +31,7 @@ from charmhelpers.core.host import write_file
31from charms import layer31from charms import layer
32from charms import reactive32from charms import reactive
33from charms.layer import snap33from charms.layer import snap
34from charms.reactive import when
34from charms.reactive.helpers import data_changed35from charms.reactive.helpers import data_changed
3536
3637
@@ -263,6 +264,14 @@ def configure_snap_enterprise_proxy():
263 'Proxy ID from header did not match store assertion: ' + e.output)264 'Proxy ID from header did not match store assertion: ' + e.output)
264265
265266
267@when('config.changed.snapd_refresh')
268def change_snapd_refresh():
269 """Set the system refresh.timer option"""
270 ensure_snapd_min_version('2.31')
271 timer = hookenv.config()['snapd_refresh']
272 snap.set_refresh_timer(timer)
273
274
266# Per https://github.com/juju-solutions/charms.reactive/issues/33,275# Per https://github.com/juju-solutions/charms.reactive/issues/33,
267# this module may be imported multiple times so ensure the276# this module may be imported multiple times so ensure the
268# initialization hook is only registered once. I have to piggy back277# initialization hook is only registered once. I have to piggy back

Subscribers

People subscribed via source and target branches

to all changes: