Merge lp:~mvo/snappy/15.04-watchdog-config into lp:~snappy-dev/snappy/15.04-deprecated
- 15.04-watchdog-config
- Merge into 15.04-deprecated
Proposed by
Michael Vogt
Status: | Superseded |
---|---|
Proposed branch: | lp:~mvo/snappy/15.04-watchdog-config |
Merge into: | lp:~snappy-dev/snappy/15.04-deprecated |
Diff against target: |
613 lines (+429/-3) 2 files modified
coreconfig/config.go (+186/-3) coreconfig/config_test.go (+243/-0) |
To merge this branch: | bzr merge lp:~mvo/snappy/15.04-watchdog-config |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Snappy Developers | Pending | ||
Review via email: mp+270556@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-09-10.
Commit message
Description of the change
Enable watchdog configuration via ubuntu-core-config
To post a comment you must log in.
- 473. By Michael Vogt
-
merged parent
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'coreconfig/config.go' |
2 | --- coreconfig/config.go 2015-04-14 16:46:57 +0000 |
3 | +++ coreconfig/config.go 2015-09-09 15:59:02 +0000 |
4 | @@ -22,6 +22,7 @@ |
5 | "io/ioutil" |
6 | "os" |
7 | "os/exec" |
8 | + "path/filepath" |
9 | "reflect" |
10 | "strings" |
11 | "syscall" |
12 | @@ -40,14 +41,36 @@ |
13 | autopilotTimerDisabled string = "disabled" |
14 | ) |
15 | |
16 | +var ( |
17 | + modprobePath string = "/etc/modprobe.d/ubuntu-core.conf" |
18 | + networkRoot string = "/etc/network/interfaces.d/" |
19 | + pppRoot string = "/etc/ppp/" |
20 | + watchdogConfigPath string = "/etc/watchdog.conf" |
21 | + watchdogStartupPath string = "/etc/default/watchdog" |
22 | +) |
23 | + |
24 | // ErrInvalidUnitStatus signals that a unit is not returning a status |
25 | // of "enabled" or "disabled". |
26 | var ErrInvalidUnitStatus = errors.New("invalid unit status") |
27 | |
28 | type systemConfig struct { |
29 | - Autopilot *bool `yaml:"autopilot,omitempty"` |
30 | - Timezone *string `yaml:"timezone,omitempty"` |
31 | - Hostname *string `yaml:"hostname,omitempty"` |
32 | + Autopilot *bool `yaml:"autopilot,omitempty"` |
33 | + Timezone *string `yaml:"timezone,omitempty"` |
34 | + Hostname *string `yaml:"hostname,omitempty"` |
35 | + Modprobe *string `yaml:"modprobe,omitempty"` |
36 | + Network []passthroughConfig `yaml:"network,omitempty"` |
37 | + PPP []passthroughConfig `yaml:"ppp,omitempty"` |
38 | + Watchdog *watchdogConfig `yaml:"watchdog,omitempty"` |
39 | +} |
40 | + |
41 | +type passthroughConfig struct { |
42 | + Name string `yaml:"name,omitempty"` |
43 | + Content string `yaml:"content,omitempty"` |
44 | +} |
45 | + |
46 | +type watchdogConfig struct { |
47 | + Startup string `yaml:"startup,omitempty"` |
48 | + Config string `yaml:"config,omitempty"` |
49 | } |
50 | |
51 | type coreConfig struct { |
52 | @@ -73,11 +96,31 @@ |
53 | if err != nil { |
54 | return nil, err |
55 | } |
56 | + modprobe, err := getModprobe() |
57 | + if err != nil { |
58 | + return nil, err |
59 | + } |
60 | + network, err := getNetwork() |
61 | + if err != nil { |
62 | + return nil, err |
63 | + } |
64 | + ppp, err := getPPP() |
65 | + if err != nil { |
66 | + return nil, err |
67 | + } |
68 | + watchdog, err := getWatchdog() |
69 | + if err != nil { |
70 | + return nil, err |
71 | + } |
72 | |
73 | config := &systemConfig{ |
74 | Autopilot: &autopilot, |
75 | Timezone: &tz, |
76 | Hostname: &hostname, |
77 | + Modprobe: &modprobe, |
78 | + Network: network, |
79 | + PPP: ppp, |
80 | + Watchdog: watchdog, |
81 | } |
82 | |
83 | return config, nil |
84 | @@ -103,6 +146,18 @@ |
85 | return string(out), nil |
86 | } |
87 | |
88 | +func passthroughEqual(a, b []passthroughConfig) bool { |
89 | + if len(a) != len(b) { |
90 | + return false |
91 | + } |
92 | + for i, v := range a { |
93 | + if v != b[i] { |
94 | + return false |
95 | + } |
96 | + } |
97 | + return true |
98 | +} |
99 | + |
100 | // Set is used to configure settings for the system, this is meant to |
101 | // be used as an interface for snappy config to satisfy the ubuntu-core |
102 | // hook. |
103 | @@ -151,6 +206,38 @@ |
104 | if err := setHostname(*newConfig.Hostname); err != nil { |
105 | return "", err |
106 | } |
107 | + case "Modprobe": |
108 | + if *oldConfig.Modprobe == *newConfig.Modprobe { |
109 | + continue |
110 | + } |
111 | + |
112 | + if err := setModprobe(*newConfig.Modprobe); err != nil { |
113 | + return "", err |
114 | + } |
115 | + case "Network": |
116 | + if passthroughEqual(oldConfig.Network, newConfig.Network) { |
117 | + continue |
118 | + } |
119 | + |
120 | + if err := setNetwork(newConfig.Network); err != nil { |
121 | + return "", err |
122 | + } |
123 | + case "PPP": |
124 | + if passthroughEqual(oldConfig.PPP, newConfig.PPP) { |
125 | + continue |
126 | + } |
127 | + |
128 | + if err := setPPP(newConfig.PPP); err != nil { |
129 | + return "", err |
130 | + } |
131 | + case "Watchdog": |
132 | + if oldConfig.Watchdog != nil && *oldConfig.Watchdog == *newConfig.Watchdog { |
133 | + continue |
134 | + } |
135 | + |
136 | + if err := setWatchdog(newConfig.Watchdog); err != nil { |
137 | + return "", err |
138 | + } |
139 | } |
140 | } |
141 | |
142 | @@ -184,6 +271,102 @@ |
143 | return ioutil.WriteFile(tzFile(), []byte(timezone), 0644) |
144 | } |
145 | |
146 | +func getPassthrough(rootDir string) (pc []passthroughConfig, err error) { |
147 | + filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { |
148 | + if info.IsDir() { |
149 | + return nil |
150 | + } |
151 | + content, err := ioutil.ReadFile(path) |
152 | + if err != nil { |
153 | + return err |
154 | + } |
155 | + pc = append(pc, passthroughConfig{ |
156 | + Name: path[len(rootDir)+1:], |
157 | + Content: string(content), |
158 | + }) |
159 | + return nil |
160 | + }) |
161 | + |
162 | + return pc, nil |
163 | + |
164 | +} |
165 | +func setPassthrough(rootDir string, pc []passthroughConfig) error { |
166 | + for _, c := range pc { |
167 | + path := filepath.Join(rootDir, c.Name) |
168 | + if c.Content == "" { |
169 | + os.Remove(path) |
170 | + continue |
171 | + } |
172 | + |
173 | + if err := ioutil.WriteFile(path, []byte(c.Content), 0644); err != nil { |
174 | + return err |
175 | + } |
176 | + } |
177 | + |
178 | + return nil |
179 | +} |
180 | + |
181 | +var getNetwork = func() (pc []passthroughConfig, err error) { |
182 | + return getPassthrough(networkRoot) |
183 | +} |
184 | + |
185 | +var setNetwork = func(pc []passthroughConfig) error { |
186 | + return setPassthrough(networkRoot, pc) |
187 | +} |
188 | + |
189 | +var getPPP = func() (pc []passthroughConfig, err error) { |
190 | + return getPassthrough(pppRoot) |
191 | +} |
192 | + |
193 | +var setPPP = func(pc []passthroughConfig) error { |
194 | + return setPassthrough(pppRoot, pc) |
195 | +} |
196 | + |
197 | +// getModprobe returns the current modprobe config |
198 | +var getModprobe = func() (string, error) { |
199 | + modprobe, err := ioutil.ReadFile(modprobePath) |
200 | + if err != nil && !os.IsNotExist(err) { |
201 | + return "", err |
202 | + } |
203 | + |
204 | + return string(modprobe), nil |
205 | +} |
206 | + |
207 | +// setModprobe sets the specified modprobe config |
208 | +var setModprobe = func(modprobe string) error { |
209 | + return ioutil.WriteFile(modprobePath, []byte(modprobe), 0644) |
210 | +} |
211 | + |
212 | +// getWatchdog returns the current watchdog config |
213 | +var getWatchdog = func() (*watchdogConfig, error) { |
214 | + startup, err := ioutil.ReadFile(watchdogStartupPath) |
215 | + if err != nil && !os.IsNotExist(err) { |
216 | + return nil, err |
217 | + } |
218 | + config, err := ioutil.ReadFile(watchdogConfigPath) |
219 | + if err != nil && !os.IsNotExist(err) { |
220 | + return nil, err |
221 | + } |
222 | + |
223 | + // nil to make the yaml empty |
224 | + if len(startup) == 0 && len(config) == 0 { |
225 | + return nil, nil |
226 | + } |
227 | + |
228 | + return &watchdogConfig{ |
229 | + Startup: string(startup), |
230 | + Config: string(config)}, nil |
231 | +} |
232 | + |
233 | +// setWatchdog sets the specified watchdog config |
234 | +var setWatchdog = func(wf *watchdogConfig) error { |
235 | + if err := ioutil.WriteFile(watchdogStartupPath, []byte(wf.Startup), 0644); err != nil { |
236 | + return err |
237 | + } |
238 | + |
239 | + return ioutil.WriteFile(watchdogConfigPath, []byte(wf.Config), 0644) |
240 | +} |
241 | + |
242 | // for testing purposes |
243 | var ( |
244 | cmdAutopilotEnabled = []string{"is-enabled", autopilotTimer} |
245 | |
246 | === modified file 'coreconfig/config_test.go' |
247 | --- coreconfig/config_test.go 2015-08-02 12:21:07 +0000 |
248 | +++ coreconfig/config_test.go 2015-09-09 15:59:02 +0000 |
249 | @@ -25,6 +25,7 @@ |
250 | "testing" |
251 | |
252 | . "gopkg.in/check.v1" |
253 | + "launchpad.net/snappy/helpers" |
254 | ) |
255 | |
256 | // Hook up check.v1 into the "go test" runner. |
257 | @@ -46,6 +47,11 @@ |
258 | originalCmdAutopilotEnabled = cmdAutopilotEnabled |
259 | originalCmdSystemctl = cmdSystemctl |
260 | originalHostnamePath = hostnamePath |
261 | + originalModprobePath = modprobePath |
262 | + originalNetworkRoot = networkRoot |
263 | + originalPppRoot = pppRoot |
264 | + originalWatchdogStartupPath = watchdogStartupPath |
265 | + originalWatchdogConfigPath = watchdogConfigPath |
266 | ) |
267 | |
268 | type ConfigTestSuite struct { |
269 | @@ -72,6 +78,11 @@ |
270 | hostname = host |
271 | return nil |
272 | } |
273 | + |
274 | + networkRoot = c.MkDir() |
275 | + pppRoot = c.MkDir() |
276 | + watchdogConfigPath = filepath.Join(c.MkDir(), "watchdog-config") |
277 | + watchdogStartupPath = filepath.Join(c.MkDir(), "watchdog-startup") |
278 | } |
279 | |
280 | func (cts *ConfigTestSuite) TearDownTest(c *C) { |
281 | @@ -90,6 +101,11 @@ |
282 | cmdStopAutopilot = originalCmdStopAutopilot |
283 | cmdAutopilotEnabled = originalCmdAutopilotEnabled |
284 | cmdSystemctl = originalCmdSystemctl |
285 | + modprobePath = originalModprobePath |
286 | + networkRoot = originalNetworkRoot |
287 | + pppRoot = originalPppRoot |
288 | + watchdogStartupPath = originalWatchdogStartupPath |
289 | + watchdogConfigPath = originalWatchdogConfigPath |
290 | } |
291 | |
292 | // TestGet is a broad test, close enough to be an integration test for |
293 | @@ -101,6 +117,7 @@ |
294 | autopilot: false |
295 | timezone: America/Argentina/Cordoba |
296 | hostname: testhost |
297 | + modprobe: "" |
298 | ` |
299 | |
300 | rawConfig, err := Get() |
301 | @@ -116,6 +133,7 @@ |
302 | autopilot: true |
303 | timezone: America/Argentina/Mendoza |
304 | hostname: testhost |
305 | + modprobe: "" |
306 | ` |
307 | |
308 | cmdAutopilotEnabled = []string{"-c", "echo enabled"} |
309 | @@ -132,6 +150,7 @@ |
310 | autopilot: false |
311 | timezone: America/Argentina/Mendoza |
312 | hostname: testhost |
313 | + modprobe: "" |
314 | ` |
315 | |
316 | rawConfig, err := Set(expected) |
317 | @@ -147,6 +166,7 @@ |
318 | autopilot: true |
319 | timezone: America/Argentina/Cordoba |
320 | hostname: testhost |
321 | + modprobe: "" |
322 | ` |
323 | |
324 | enabled := false |
325 | @@ -165,6 +185,7 @@ |
326 | autopilot: false |
327 | timezone: America/Argentina/Cordoba |
328 | hostname: NEWtesthost |
329 | + modprobe: "" |
330 | ` |
331 | |
332 | rawConfig, err := Set(expected) |
333 | @@ -178,6 +199,7 @@ |
334 | autopilot: false |
335 | timezone America/Argentina/Mendoza |
336 | hostname: testhost |
337 | + modprobe: "" |
338 | ` |
339 | |
340 | rawConfig, err := Set(input) |
341 | @@ -191,6 +213,7 @@ |
342 | autopilot: false |
343 | timezone: America/Argentina/Cordoba |
344 | hostname: testhost |
345 | + modprobe: "" |
346 | ` |
347 | |
348 | rawConfig, err := Set(input) |
349 | @@ -204,12 +227,14 @@ |
350 | autopilot: false |
351 | timezone: America/Argentina/Cordoba |
352 | hostname: testhost |
353 | + modprobe: "" |
354 | ` |
355 | |
356 | input := `config: |
357 | ubuntu-core: |
358 | autopilot: false |
359 | timezone: America/Argentina/Cordoba |
360 | + modprobe: "" |
361 | ` |
362 | |
363 | rawConfig, err := Set(input) |
364 | @@ -247,6 +272,7 @@ |
365 | autopilot: false |
366 | timezone: America/Argentina/Mendoza |
367 | hostname: testhost |
368 | + modprobe: "" |
369 | ` |
370 | |
371 | rawConfig, err := Set(input) |
372 | @@ -268,6 +294,7 @@ |
373 | autopilot: true |
374 | timezone: America/Argentina/Mendoza |
375 | hostname: testhost |
376 | + modprobe: "" |
377 | ` |
378 | |
379 | enabled := false |
380 | @@ -285,6 +312,7 @@ |
381 | autopilot: false |
382 | timezone: America/Argentina/Cordoba |
383 | hostname: NEWtesthost |
384 | + modprobe: "" |
385 | ` |
386 | |
387 | setHostname = func(string) error { return errors.New("this is bad") } |
388 | @@ -300,6 +328,7 @@ |
389 | autopilot: false |
390 | timezone: America/Argentina/Cordoba |
391 | hostname: NEWtesthost |
392 | + modprobe: "" |
393 | ` |
394 | |
395 | getHostname = func() (string, error) { return "", errors.New("this is bad") } |
396 | @@ -396,3 +425,217 @@ |
397 | err := setHostname("newhostname") |
398 | c.Assert(err, DeepEquals, expectedErr) |
399 | } |
400 | + |
401 | +func (cts *ConfigTestSuite) TestModprobe(c *C) { |
402 | + modprobePath = filepath.Join(c.MkDir(), "test.conf") |
403 | + |
404 | + err := setModprobe("blacklist floppy") |
405 | + c.Assert(err, IsNil) |
406 | + |
407 | + modprobe, err := getModprobe() |
408 | + c.Assert(err, IsNil) |
409 | + c.Assert(modprobe, Equals, "blacklist floppy") |
410 | +} |
411 | + |
412 | +func (cts *ConfigTestSuite) TestModprobeYaml(c *C) { |
413 | + modprobePath = filepath.Join(c.MkDir(), "test.conf") |
414 | + |
415 | + input := `config: |
416 | + ubuntu-core: |
417 | + modprobe: | |
418 | + blacklist floppy |
419 | + softdep mlx4_core post: mlx4_en |
420 | +` |
421 | + _, err := Set(input) |
422 | + c.Assert(err, IsNil) |
423 | + |
424 | + // ensure its really there |
425 | + content, err := ioutil.ReadFile(modprobePath) |
426 | + c.Assert(err, IsNil) |
427 | + c.Assert(string(content), Equals, "blacklist floppy\nsoftdep mlx4_core post: mlx4_en\n") |
428 | +} |
429 | + |
430 | +func (cts *ConfigTestSuite) TestNetworkGet(c *C) { |
431 | + path := filepath.Join(networkRoot, "eth0") |
432 | + content := "auto eth0" |
433 | + err := ioutil.WriteFile(path, []byte(content), 0644) |
434 | + c.Assert(err, IsNil) |
435 | + |
436 | + nc, err := getNetwork() |
437 | + c.Assert(err, IsNil) |
438 | + c.Assert(nc, DeepEquals, []passthroughConfig{ |
439 | + {Name: "eth0", Content: "auto eth0"}, |
440 | + }) |
441 | +} |
442 | + |
443 | +func (cts *ConfigTestSuite) TestNetworkSet(c *C) { |
444 | + nc := []passthroughConfig{ |
445 | + {Name: "eth0", Content: "auto eth0"}, |
446 | + } |
447 | + path := filepath.Join(networkRoot, nc[0].Name) |
448 | + err := setNetwork(nc) |
449 | + c.Assert(err, IsNil) |
450 | + content, err := ioutil.ReadFile(path) |
451 | + c.Assert(err, IsNil) |
452 | + c.Assert(string(content), Equals, nc[0].Content) |
453 | +} |
454 | + |
455 | +func (cts *ConfigTestSuite) TestNetworkSetEmptyRemoves(c *C) { |
456 | + path := filepath.Join(networkRoot, "eth0") |
457 | + content := "auto eth0" |
458 | + err := ioutil.WriteFile(path, []byte(content), 0644) |
459 | + c.Assert(err, IsNil) |
460 | + |
461 | + // empty content removes |
462 | + nc := []passthroughConfig{ |
463 | + {Name: "eth0", Content: ""}, |
464 | + } |
465 | + err = setNetwork(nc) |
466 | + c.Assert(err, IsNil) |
467 | + _, err = ioutil.ReadFile(path) |
468 | + c.Assert(helpers.FileExists(path), Equals, false) |
469 | +} |
470 | + |
471 | +func (cts *ConfigTestSuite) TestPppGet(c *C) { |
472 | + path := filepath.Join(pppRoot, "chap-secrets") |
473 | + content := "password" |
474 | + err := ioutil.WriteFile(path, []byte(content), 0644) |
475 | + c.Assert(err, IsNil) |
476 | + |
477 | + nc, err := getPPP() |
478 | + c.Assert(err, IsNil) |
479 | + c.Assert(nc, DeepEquals, []passthroughConfig{ |
480 | + {Name: "chap-secrets", Content: "password"}, |
481 | + }) |
482 | +} |
483 | + |
484 | +func (cts *ConfigTestSuite) TestPppSet(c *C) { |
485 | + nc := []passthroughConfig{ |
486 | + {Name: "chap-secrets", Content: "another secret"}, |
487 | + } |
488 | + path := filepath.Join(pppRoot, nc[0].Name) |
489 | + err := setPPP(nc) |
490 | + c.Assert(err, IsNil) |
491 | + content, err := ioutil.ReadFile(path) |
492 | + c.Assert(err, IsNil) |
493 | + c.Assert(string(content), Equals, nc[0].Content) |
494 | +} |
495 | + |
496 | +func (cts *ConfigTestSuite) TestNetworkSetViaYaml(c *C) { |
497 | + modprobePath = filepath.Join(c.MkDir(), "test.conf") |
498 | + |
499 | + input := ` |
500 | +config: |
501 | + ubuntu-core: |
502 | + network: |
503 | + - name: eth0 |
504 | + content: auto dhcp |
505 | +` |
506 | + _, err := Set(input) |
507 | + c.Assert(err, IsNil) |
508 | + |
509 | + // ensure its really there |
510 | + content, err := ioutil.ReadFile(filepath.Join(networkRoot, "eth0")) |
511 | + c.Assert(err, IsNil) |
512 | + c.Assert(string(content), Equals, "auto dhcp") |
513 | +} |
514 | + |
515 | +func (cts *ConfigTestSuite) TestPPPSetViaYaml(c *C) { |
516 | + modprobePath = filepath.Join(c.MkDir(), "test.conf") |
517 | + |
518 | + input := ` |
519 | +config: |
520 | + ubuntu-core: |
521 | + ppp: |
522 | + - name: chap-secret |
523 | + content: password |
524 | +` |
525 | + _, err := Set(input) |
526 | + c.Assert(err, IsNil) |
527 | + |
528 | + // ensure its really there |
529 | + content, err := ioutil.ReadFile(filepath.Join(pppRoot, "chap-secret")) |
530 | + c.Assert(err, IsNil) |
531 | + c.Assert(string(content), Equals, "password") |
532 | +} |
533 | + |
534 | +func (cts *ConfigTestSuite) TestPassthroughConfigEqual(c *C) { |
535 | + a := []passthroughConfig{ |
536 | + {Name: "key", Content: "value"}, |
537 | + } |
538 | + b := []passthroughConfig{ |
539 | + {Name: "key", Content: "value"}, |
540 | + } |
541 | + c.Assert(passthroughEqual(a, b), Equals, true) |
542 | +} |
543 | + |
544 | +func (cts *ConfigTestSuite) TestPassthroughConfigNotEqualDifferentSize(c *C) { |
545 | + a := []passthroughConfig{} |
546 | + b := []passthroughConfig{ |
547 | + {Name: "key", Content: "value"}, |
548 | + } |
549 | + c.Assert(passthroughEqual(a, b), Equals, false) |
550 | +} |
551 | + |
552 | +func (cts *ConfigTestSuite) TestPassthroughConfigNotEqualDifferentKeys(c *C) { |
553 | + a := []passthroughConfig{ |
554 | + {Name: "key", Content: "value"}, |
555 | + } |
556 | + b := []passthroughConfig{ |
557 | + {Name: "other-key", Content: "value"}, |
558 | + } |
559 | + c.Assert(passthroughEqual(a, b), Equals, false) |
560 | +} |
561 | + |
562 | +func (cts *ConfigTestSuite) TestWatchdogGet(c *C) { |
563 | + startup := "# some startup watchdog config" |
564 | + err := ioutil.WriteFile(watchdogStartupPath, []byte(startup), 0644) |
565 | + c.Assert(err, IsNil) |
566 | + |
567 | + config := "# some watchdog config" |
568 | + err = ioutil.WriteFile(watchdogConfigPath, []byte(config), 0644) |
569 | + c.Assert(err, IsNil) |
570 | + |
571 | + wc, err := getWatchdog() |
572 | + c.Assert(err, IsNil) |
573 | + c.Assert(wc, DeepEquals, &watchdogConfig{ |
574 | + Startup: startup, Config: config, |
575 | + }) |
576 | +} |
577 | + |
578 | +func (cts *ConfigTestSuite) TestWatchdogSet(c *C) { |
579 | + wc := &watchdogConfig{ |
580 | + Startup: "startup", Config: "secret", |
581 | + } |
582 | + err := setWatchdog(wc) |
583 | + c.Assert(err, IsNil) |
584 | + |
585 | + content, err := ioutil.ReadFile(watchdogStartupPath) |
586 | + c.Assert(err, IsNil) |
587 | + c.Assert(string(content), Equals, wc.Startup) |
588 | + |
589 | + content, err = ioutil.ReadFile(watchdogConfigPath) |
590 | + c.Assert(err, IsNil) |
591 | + c.Assert(string(content), Equals, wc.Config) |
592 | +} |
593 | + |
594 | +func (cts *ConfigTestSuite) TestWatchdogSetViaYaml(c *C) { |
595 | + input := ` |
596 | +config: |
597 | + ubuntu-core: |
598 | + watchdog: |
599 | + startup: some startup |
600 | + config: some config |
601 | +` |
602 | + _, err := Set(input) |
603 | + c.Assert(err, IsNil) |
604 | + |
605 | + // ensure its really there |
606 | + content, err := ioutil.ReadFile(watchdogStartupPath) |
607 | + c.Assert(err, IsNil) |
608 | + c.Assert(string(content), Equals, "some startup") |
609 | + |
610 | + content, err = ioutil.ReadFile(watchdogConfigPath) |
611 | + c.Assert(err, IsNil) |
612 | + c.Assert(string(content), Equals, "some config") |
613 | +} |