~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/service/systemd/service_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2015 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package systemd_test
 
5
 
 
6
import (
 
7
        "bytes"
 
8
        "fmt"
 
9
        "os"
 
10
        "strings"
 
11
 
 
12
        "github.com/coreos/go-systemd/unit"
 
13
        "github.com/juju/errors"
 
14
        "github.com/juju/testing"
 
15
        jc "github.com/juju/testing/checkers"
 
16
        "github.com/juju/utils/exec"
 
17
        "github.com/juju/utils/shell"
 
18
        gc "gopkg.in/check.v1"
 
19
        "gopkg.in/juju/names.v2"
 
20
 
 
21
        "github.com/juju/juju/juju/paths"
 
22
        "github.com/juju/juju/service"
 
23
        "github.com/juju/juju/service/common"
 
24
        "github.com/juju/juju/service/systemd"
 
25
        systemdtesting "github.com/juju/juju/service/systemd/testing"
 
26
        coretesting "github.com/juju/juju/testing"
 
27
)
 
28
 
 
29
var renderer = &shell.BashRenderer{}
 
30
 
 
31
const confStr = `
 
32
[Unit]
 
33
Description=juju agent for %s
 
34
After=syslog.target
 
35
After=network.target
 
36
After=systemd-user-sessions.service
 
37
 
 
38
[Service]
 
39
ExecStart=%s
 
40
Restart=on-failure
 
41
 
 
42
[Install]
 
43
WantedBy=multi-user.target
 
44
 
 
45
`
 
46
 
 
47
const jujud = "/var/lib/juju/bin/jujud"
 
48
 
 
49
var listCmdArg = exec.RunParams{
 
50
        Commands: `/bin/systemctl list-unit-files --no-legend --no-page -t service | grep -o -P '^\w[\S]*(?=\.service)'`,
 
51
}
 
52
 
 
53
type initSystemSuite struct {
 
54
        coretesting.BaseSuite
 
55
 
 
56
        dataDir string
 
57
        ch      chan string
 
58
        stub    *testing.Stub
 
59
        conn    *systemd.StubDbusAPI
 
60
        fops    *systemd.StubFileOps
 
61
        exec    *systemd.StubExec
 
62
 
 
63
        name    string
 
64
        tag     names.Tag
 
65
        conf    common.Conf
 
66
        confStr string
 
67
        service *systemd.Service
 
68
}
 
69
 
 
70
var _ = gc.Suite(&initSystemSuite{})
 
71
 
 
72
func (s *initSystemSuite) SetUpTest(c *gc.C) {
 
73
        s.BaseSuite.SetUpTest(c)
 
74
 
 
75
        dataDir, err := paths.DataDir("vivid")
 
76
        c.Assert(err, jc.ErrorIsNil)
 
77
        s.dataDir = dataDir
 
78
        // Patch things out.
 
79
        s.ch = systemd.PatchNewChan(s)
 
80
 
 
81
        s.stub = &testing.Stub{}
 
82
        s.conn = systemd.PatchNewConn(s, s.stub)
 
83
        s.fops = systemd.PatchFileOps(s, s.stub)
 
84
        s.exec = systemd.PatchExec(s, s.stub)
 
85
 
 
86
        // Set up the service.
 
87
        tagStr := "machine-0"
 
88
        tag, err := names.ParseTag(tagStr)
 
89
        c.Assert(err, jc.ErrorIsNil)
 
90
        s.tag = tag
 
91
        s.name = "jujud-" + tagStr
 
92
        s.conf = common.Conf{
 
93
                Desc:      "juju agent for " + tagStr,
 
94
                ExecStart: jujud + " " + tagStr,
 
95
        }
 
96
        s.service = s.newService(c)
 
97
 
 
98
        // Reset any incidental calls.
 
99
        s.stub.ResetCalls()
 
100
}
 
101
 
 
102
func (s *initSystemSuite) newService(c *gc.C) *systemd.Service {
 
103
        service, err := systemd.NewService(s.name, s.conf, s.dataDir)
 
104
        c.Assert(err, jc.ErrorIsNil)
 
105
        return service
 
106
}
 
107
 
 
108
func (s *initSystemSuite) newConfStr(name string) string {
 
109
        return s.newConfStrCmd(name, "")
 
110
}
 
111
 
 
112
func (s *initSystemSuite) newConfStrCmd(name, cmd string) string {
 
113
        tag := name[len("jujud-"):]
 
114
        if cmd == "" {
 
115
                cmd = jujud + " " + tag
 
116
        }
 
117
        return fmt.Sprintf(confStr[1:], tag, cmd)
 
118
}
 
119
 
 
120
func (s *initSystemSuite) newConfStrEnv(name, env string) string {
 
121
        const replace = "[Service]\n"
 
122
        result := s.newConfStr(name)
 
123
        result = strings.Replace(
 
124
                result, replace,
 
125
                fmt.Sprintf("%sEnvironment=%s\n", replace, env),
 
126
                1,
 
127
        )
 
128
        return result
 
129
}
 
130
 
 
131
func (s *initSystemSuite) addService(name, status string) {
 
132
        tag := name[len("jujud-"):]
 
133
        desc := "juju agent for " + tag
 
134
        s.conn.AddService(name, desc, status)
 
135
}
 
136
 
 
137
func (s *initSystemSuite) addListResponse() {
 
138
        var lines []string
 
139
        for _, unit := range s.conn.Units {
 
140
                lines = append(lines, strings.TrimSuffix(unit.Name, ".service"))
 
141
        }
 
142
 
 
143
        s.exec.Responses = append(s.exec.Responses, exec.ExecResponse{
 
144
                Code:   0,
 
145
                Stdout: []byte(strings.Join(lines, "\n")),
 
146
                Stderr: nil,
 
147
        })
 
148
}
 
149
 
 
150
func (s *initSystemSuite) setConf(c *gc.C, conf common.Conf) {
 
151
        data, err := systemd.Serialize(s.name, conf, renderer)
 
152
        c.Assert(err, jc.ErrorIsNil)
 
153
        s.exec.Responses = append(s.exec.Responses, exec.ExecResponse{
 
154
                Code:   0,
 
155
                Stdout: data,
 
156
                Stderr: nil,
 
157
        })
 
158
}
 
159
 
 
160
func (s *initSystemSuite) checkCreateFileCall(c *gc.C, index int, filename, content string, perm os.FileMode) {
 
161
        if content == "" {
 
162
                name := filename
 
163
                filename = fmt.Sprintf("%s/init/%s/%s.service", s.dataDir, name, name)
 
164
                content = s.newConfStr(name)
 
165
        }
 
166
 
 
167
        call := s.stub.Calls()[index]
 
168
        if !c.Check(call.FuncName, gc.Equals, "CreateFile") {
 
169
                return
 
170
        }
 
171
        if !c.Check(call.Args, gc.HasLen, 3) {
 
172
                return
 
173
        }
 
174
 
 
175
        callFilename, callData, callPerm := call.Args[0], call.Args[1], call.Args[2]
 
176
        c.Check(callFilename, gc.Equals, filename)
 
177
 
 
178
        // Some tests don't generate valid ini files, instead including placeholder
 
179
        // strings (e.g. "a\nb\nc\n"). To avoid parsing errors, we only try and
 
180
        // parse actual and expected file content if they don't exactly match.
 
181
        if content != string(callData.([]byte)) {
 
182
                // Parse the ini configurations and compare those.
 
183
                expected, err := unit.Deserialize(bytes.NewReader(callData.([]byte)))
 
184
                c.Assert(err, jc.ErrorIsNil)
 
185
                cfg, err := unit.Deserialize(strings.NewReader(content))
 
186
                c.Assert(err, jc.ErrorIsNil)
 
187
                c.Check(cfg, jc.SameContents, expected)
 
188
        }
 
189
 
 
190
        c.Check(callPerm, gc.Equals, perm)
 
191
}
 
192
 
 
193
func (s *initSystemSuite) TestListServices(c *gc.C) {
 
194
        s.addService("jujud-machine-0", "active")
 
195
        s.addService("something-else", "error")
 
196
        s.addService("jujud-unit-wordpress-0", "active")
 
197
        s.addService("another", "inactive")
 
198
        s.addListResponse()
 
199
 
 
200
        names, err := systemd.ListServices()
 
201
        c.Assert(err, jc.ErrorIsNil)
 
202
 
 
203
        c.Check(names, jc.SameContents, []string{
 
204
                "jujud-machine-0",
 
205
                "something-else",
 
206
                "jujud-unit-wordpress-0",
 
207
                "another",
 
208
        })
 
209
        s.stub.CheckCallNames(c, "RunCommand")
 
210
}
 
211
 
 
212
func (s *initSystemSuite) TestListServicesEmpty(c *gc.C) {
 
213
        s.addListResponse()
 
214
 
 
215
        names, err := systemd.ListServices()
 
216
        c.Assert(err, jc.ErrorIsNil)
 
217
 
 
218
        c.Check(names, gc.HasLen, 0)
 
219
        s.stub.CheckCallNames(c, "RunCommand")
 
220
}
 
221
 
 
222
func (s *initSystemSuite) TestNewService(c *gc.C) {
 
223
        service := s.newService(c)
 
224
        c.Check(service, jc.DeepEquals, &systemd.Service{
 
225
                Service: common.Service{
 
226
                        Name: s.name,
 
227
                        Conf: s.conf,
 
228
                },
 
229
                ConfName: s.name + ".service",
 
230
                UnitName: s.name + ".service",
 
231
                Dirname:  fmt.Sprintf("%s/init/%s", s.dataDir, s.name),
 
232
        })
 
233
        s.stub.CheckCalls(c, nil)
 
234
}
 
235
 
 
236
func (s *initSystemSuite) TestNewServiceLogfile(c *gc.C) {
 
237
        s.conf.Logfile = "/var/log/juju/machine-0.log"
 
238
        service := s.newService(c)
 
239
 
 
240
        user, group := systemd.SyslogUserGroup()
 
241
        dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name)
 
242
        script := `
 
243
#!/usr/bin/env bash
 
244
 
 
245
# Set up logging.
 
246
touch '/var/log/juju/machine-0.log'
 
247
chown `[1:] + user + `:` + group + ` '/var/log/juju/machine-0.log'
 
248
chmod 0600 '/var/log/juju/machine-0.log'
 
249
exec >> '/var/log/juju/machine-0.log'
 
250
exec 2>&1
 
251
 
 
252
# Run the script.
 
253
` + jujud + " machine-0"
 
254
        c.Check(service, jc.DeepEquals, &systemd.Service{
 
255
                Service: common.Service{
 
256
                        Name: s.name,
 
257
                        Conf: common.Conf{
 
258
                                Desc:      s.conf.Desc,
 
259
                                ExecStart: dirname + "/exec-start.sh",
 
260
                                Logfile:   "/var/log/juju/machine-0.log",
 
261
                        },
 
262
                },
 
263
                UnitName: s.name + ".service",
 
264
                ConfName: s.name + ".service",
 
265
                Dirname:  dirname,
 
266
                Script:   []byte(script),
 
267
        })
 
268
        // This gives us a more readable output if they aren't equal.
 
269
        c.Check(string(service.Script), gc.Equals, script)
 
270
        c.Check(strings.Split(string(service.Script), "\n"), jc.DeepEquals, strings.Split(script, "\n"))
 
271
}
 
272
 
 
273
func (s *initSystemSuite) TestNewServiceEmptyConf(c *gc.C) {
 
274
        service, err := systemd.NewService(s.name, common.Conf{}, s.dataDir)
 
275
        c.Assert(err, jc.ErrorIsNil)
 
276
 
 
277
        c.Check(service, jc.DeepEquals, &systemd.Service{
 
278
                Service: common.Service{
 
279
                        Name: s.name,
 
280
                },
 
281
                ConfName: s.name + ".service",
 
282
                UnitName: s.name + ".service",
 
283
                Dirname:  fmt.Sprintf("%s/init/%s", s.dataDir, s.name),
 
284
        })
 
285
        s.stub.CheckCalls(c, nil)
 
286
}
 
287
 
 
288
func (s *initSystemSuite) TestNewServiceBasic(c *gc.C) {
 
289
        s.conf.ExecStart = "/path/to/some/other/command"
 
290
        svc := s.newService(c)
 
291
 
 
292
        c.Check(svc, jc.DeepEquals, &systemd.Service{
 
293
                Service: common.Service{
 
294
                        Name: s.name,
 
295
                        Conf: s.conf,
 
296
                },
 
297
                ConfName: s.name + ".service",
 
298
                UnitName: s.name + ".service",
 
299
                Dirname:  fmt.Sprintf("%s/init/%s", s.dataDir, s.name),
 
300
        })
 
301
        s.stub.CheckCalls(c, nil)
 
302
}
 
303
 
 
304
func (s *initSystemSuite) TestNewServiceExtraScript(c *gc.C) {
 
305
        s.conf.ExtraScript = "'/path/to/another/command'"
 
306
        svc := s.newService(c)
 
307
 
 
308
        dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name)
 
309
        script := `
 
310
#!/usr/bin/env bash
 
311
 
 
312
'/path/to/another/command'
 
313
`[1:] + jujud + " machine-0"
 
314
        c.Check(svc, jc.DeepEquals, &systemd.Service{
 
315
                Service: common.Service{
 
316
                        Name: s.name,
 
317
                        Conf: common.Conf{
 
318
                                Desc:      s.conf.Desc,
 
319
                                ExecStart: dirname + "/exec-start.sh",
 
320
                        },
 
321
                },
 
322
                UnitName: s.name + ".service",
 
323
                ConfName: s.name + ".service",
 
324
                Dirname:  dirname,
 
325
                Script:   []byte(script),
 
326
        })
 
327
        // This gives us a more readable output if they aren't equal.
 
328
        c.Check(string(svc.Script), gc.Equals, script)
 
329
        s.stub.CheckCalls(c, nil)
 
330
}
 
331
 
 
332
func (s *initSystemSuite) TestNewServiceMultiline(c *gc.C) {
 
333
        s.conf.ExecStart = "a\nb\nc"
 
334
        svc := s.newService(c)
 
335
 
 
336
        dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name)
 
337
        script := `
 
338
#!/usr/bin/env bash
 
339
 
 
340
a
 
341
b
 
342
c`[1:]
 
343
        c.Check(svc, jc.DeepEquals, &systemd.Service{
 
344
                Service: common.Service{
 
345
                        Name: s.name,
 
346
                        Conf: common.Conf{
 
347
                                Desc:      s.conf.Desc,
 
348
                                ExecStart: dirname + "/exec-start.sh",
 
349
                        },
 
350
                },
 
351
                UnitName: s.name + ".service",
 
352
                ConfName: s.name + ".service",
 
353
                Dirname:  dirname,
 
354
                Script:   []byte(script),
 
355
        })
 
356
        // This gives us a more readable output if they aren't equal.
 
357
        c.Check(string(svc.Script), gc.Equals, script)
 
358
        s.stub.CheckCalls(c, nil)
 
359
}
 
360
 
 
361
func (s *initSystemSuite) TestInstalledTrue(c *gc.C) {
 
362
        s.addService("jujud-machine-0", "active")
 
363
        s.addService("something-else", "error")
 
364
        s.addService("juju-mongod", "active")
 
365
        s.addListResponse()
 
366
 
 
367
        installed, err := s.service.Installed()
 
368
        c.Assert(err, jc.ErrorIsNil)
 
369
 
 
370
        c.Check(installed, jc.IsTrue)
 
371
        s.stub.CheckCallNames(c, "RunCommand")
 
372
}
 
373
 
 
374
func (s *initSystemSuite) TestInstalledFalse(c *gc.C) {
 
375
        s.addService("something-else", "error")
 
376
        s.addListResponse()
 
377
 
 
378
        installed, err := s.service.Installed()
 
379
        c.Assert(err, jc.ErrorIsNil)
 
380
 
 
381
        c.Check(installed, jc.IsFalse)
 
382
        s.stub.CheckCallNames(c, "RunCommand")
 
383
}
 
384
 
 
385
func (s *initSystemSuite) TestInstalledError(c *gc.C) {
 
386
        s.addService("jujud-machine-0", "active")
 
387
        s.addService("something-else", "error")
 
388
        s.addService("juju-mongod", "active")
 
389
        s.addListResponse()
 
390
        failure := errors.New("<failed>")
 
391
        s.stub.SetErrors(failure)
 
392
 
 
393
        installed, err := s.service.Installed()
 
394
        c.Assert(errors.Cause(err), gc.Equals, failure)
 
395
 
 
396
        c.Check(installed, jc.IsFalse)
 
397
        s.stub.CheckCallNames(c, "RunCommand")
 
398
}
 
399
 
 
400
func (s *initSystemSuite) TestExistsTrue(c *gc.C) {
 
401
        s.setConf(c, s.conf)
 
402
 
 
403
        exists, err := s.service.Exists()
 
404
        c.Assert(err, jc.ErrorIsNil)
 
405
 
 
406
        c.Check(exists, jc.IsTrue)
 
407
        s.stub.CheckCallNames(c, "RunCommand")
 
408
}
 
409
 
 
410
func (s *initSystemSuite) TestExistsFalse(c *gc.C) {
 
411
        // We force the systemd API to return a slightly different conf.
 
412
        // In this case we simply set Conf.Env, which s.conf does not set.
 
413
        // This causes Service.Exists to return false.
 
414
        s.setConf(c, common.Conf{
 
415
                Desc:      s.conf.Desc,
 
416
                ExecStart: s.conf.ExecStart,
 
417
                Env:       map[string]string{"a": "b"},
 
418
        })
 
419
 
 
420
        exists, err := s.service.Exists()
 
421
        c.Assert(err, jc.ErrorIsNil)
 
422
 
 
423
        c.Check(exists, jc.IsFalse)
 
424
        s.stub.CheckCallNames(c, "RunCommand")
 
425
}
 
426
 
 
427
func (s *initSystemSuite) TestExistsError(c *gc.C) {
 
428
        failure := errors.New("<failed>")
 
429
        s.stub.SetErrors(failure)
 
430
 
 
431
        exists, err := s.service.Exists()
 
432
        c.Assert(errors.Cause(err), gc.Equals, failure)
 
433
 
 
434
        c.Check(exists, jc.IsFalse)
 
435
        s.stub.CheckCallNames(c, "RunCommand")
 
436
}
 
437
 
 
438
func (s *initSystemSuite) TestExistsEmptyConf(c *gc.C) {
 
439
        s.service.Service.Conf = common.Conf{}
 
440
 
 
441
        _, err := s.service.Exists()
 
442
 
 
443
        c.Check(err, gc.ErrorMatches, `.*no conf expected.*`)
 
444
        s.stub.CheckCalls(c, nil)
 
445
}
 
446
 
 
447
func (s *initSystemSuite) TestRunningTrue(c *gc.C) {
 
448
        s.addService("jujud-machine-0", "active")
 
449
        s.addService("something-else", "error")
 
450
        s.addService("juju-mongod", "active")
 
451
 
 
452
        running, err := s.service.Running()
 
453
        c.Assert(err, jc.ErrorIsNil)
 
454
 
 
455
        c.Check(running, jc.IsTrue)
 
456
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
457
}
 
458
 
 
459
func (s *initSystemSuite) TestRunningFalse(c *gc.C) {
 
460
        s.addService("jujud-machine-0", "inactive")
 
461
        s.addService("something-else", "error")
 
462
        s.addService("juju-mongod", "active")
 
463
 
 
464
        running, err := s.service.Running()
 
465
        c.Assert(err, jc.ErrorIsNil)
 
466
 
 
467
        c.Check(running, jc.IsFalse)
 
468
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
469
}
 
470
 
 
471
func (s *initSystemSuite) TestRunningNotEnabled(c *gc.C) {
 
472
        s.addService("something-else", "active")
 
473
 
 
474
        running, err := s.service.Running()
 
475
        c.Assert(err, jc.ErrorIsNil)
 
476
 
 
477
        c.Check(running, jc.IsFalse)
 
478
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
479
}
 
480
 
 
481
func (s *initSystemSuite) TestRunningError(c *gc.C) {
 
482
        s.addService("jujud-machine-0", "active")
 
483
        s.addService("something-else", "error")
 
484
        s.addService("juju-mongod", "active")
 
485
        failure := errors.New("<failed>")
 
486
        s.stub.SetErrors(failure)
 
487
 
 
488
        running, err := s.service.Running()
 
489
        c.Assert(errors.Cause(err), gc.Equals, failure)
 
490
 
 
491
        c.Check(running, jc.IsFalse)
 
492
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
493
}
 
494
 
 
495
func (s *initSystemSuite) TestStart(c *gc.C) {
 
496
        s.addService("jujud-machine-0", "inactive")
 
497
        s.ch <- "done"
 
498
        s.addListResponse()
 
499
 
 
500
        err := s.service.Start()
 
501
        c.Assert(err, jc.ErrorIsNil)
 
502
 
 
503
        s.stub.CheckCalls(c, []testing.StubCall{{
 
504
                FuncName: "RunCommand",
 
505
                Args: []interface{}{
 
506
                        listCmdArg,
 
507
                },
 
508
        }, {
 
509
                FuncName: "ListUnits",
 
510
        }, {
 
511
                FuncName: "Close",
 
512
        }, {
 
513
                FuncName: "StartUnit",
 
514
                Args: []interface{}{
 
515
                        s.name + ".service",
 
516
                        "fail",
 
517
                        (chan<- string)(s.ch),
 
518
                },
 
519
        }, {
 
520
                FuncName: "Close",
 
521
        }})
 
522
}
 
523
 
 
524
func (s *initSystemSuite) TestStartAlreadyRunning(c *gc.C) {
 
525
        s.addService("jujud-machine-0", "active")
 
526
        s.ch <- "done" // just in case
 
527
        s.addListResponse()
 
528
 
 
529
        err := s.service.Start()
 
530
        c.Assert(err, jc.ErrorIsNil)
 
531
 
 
532
        s.stub.CheckCallNames(c,
 
533
                "RunCommand",
 
534
                "ListUnits",
 
535
                "Close",
 
536
        )
 
537
}
 
538
 
 
539
func (s *initSystemSuite) TestStartNotInstalled(c *gc.C) {
 
540
        s.ch <- "done" // just in case
 
541
 
 
542
        err := s.service.Start()
 
543
 
 
544
        c.Check(err, jc.Satisfies, errors.IsNotFound)
 
545
        s.stub.CheckCallNames(c, "RunCommand")
 
546
}
 
547
 
 
548
func (s *initSystemSuite) TestStop(c *gc.C) {
 
549
        s.addService("jujud-machine-0", "active")
 
550
        s.ch <- "done"
 
551
 
 
552
        err := s.service.Stop()
 
553
        c.Assert(err, jc.ErrorIsNil)
 
554
 
 
555
        s.stub.CheckCalls(c, []testing.StubCall{{
 
556
                FuncName: "ListUnits",
 
557
        }, {
 
558
                FuncName: "Close",
 
559
        }, {
 
560
                FuncName: "StopUnit",
 
561
                Args: []interface{}{
 
562
                        s.name + ".service",
 
563
                        "fail",
 
564
                        (chan<- string)(s.ch),
 
565
                },
 
566
        }, {
 
567
                FuncName: "Close",
 
568
        }})
 
569
}
 
570
 
 
571
func (s *initSystemSuite) TestStopNotRunning(c *gc.C) {
 
572
        s.addService("jujud-machine-0", "inactive")
 
573
        s.ch <- "done" // just in case
 
574
 
 
575
        err := s.service.Stop()
 
576
        c.Assert(err, jc.ErrorIsNil)
 
577
 
 
578
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
579
}
 
580
 
 
581
func (s *initSystemSuite) TestStopNotInstalled(c *gc.C) {
 
582
        s.ch <- "done" // just in case
 
583
 
 
584
        err := s.service.Stop()
 
585
        c.Assert(err, jc.ErrorIsNil)
 
586
 
 
587
        s.stub.CheckCallNames(c, "ListUnits", "Close")
 
588
}
 
589
 
 
590
func (s *initSystemSuite) TestRemove(c *gc.C) {
 
591
        s.addService("jujud-machine-0", "inactive")
 
592
        s.addListResponse()
 
593
 
 
594
        err := s.service.Remove()
 
595
        c.Assert(err, jc.ErrorIsNil)
 
596
 
 
597
        s.stub.CheckCalls(c, []testing.StubCall{{
 
598
                FuncName: "RunCommand",
 
599
                Args: []interface{}{
 
600
                        listCmdArg,
 
601
                },
 
602
        }, {
 
603
                FuncName: "DisableUnitFiles",
 
604
                Args: []interface{}{
 
605
                        []string{s.name + ".service"},
 
606
                        false,
 
607
                },
 
608
        }, {
 
609
                FuncName: "Reload",
 
610
        }, {
 
611
                FuncName: "RemoveAll",
 
612
                Args: []interface{}{
 
613
                        fmt.Sprintf("%s/init/%s", s.dataDir, s.name),
 
614
                },
 
615
        }, {
 
616
                FuncName: "Close",
 
617
        }})
 
618
}
 
619
 
 
620
func (s *initSystemSuite) TestRemoveNotInstalled(c *gc.C) {
 
621
        err := s.service.Remove()
 
622
        c.Assert(err, jc.ErrorIsNil)
 
623
 
 
624
        s.stub.CheckCallNames(c, "RunCommand")
 
625
}
 
626
 
 
627
func (s *initSystemSuite) TestInstall(c *gc.C) {
 
628
        err := s.service.Install()
 
629
        c.Assert(err, jc.ErrorIsNil)
 
630
 
 
631
        dirname := fmt.Sprintf("%s/init/%s", s.dataDir, s.name)
 
632
        filename := fmt.Sprintf("%s/%s.service", dirname, s.name)
 
633
        createFileOutput := s.stub.Calls()[2].Args[1] // gross
 
634
        s.stub.CheckCalls(c, []testing.StubCall{{
 
635
                FuncName: "RunCommand",
 
636
                Args: []interface{}{
 
637
                        listCmdArg,
 
638
                },
 
639
        }, {
 
640
                FuncName: "MkdirAll",
 
641
                Args: []interface{}{
 
642
                        dirname,
 
643
                },
 
644
        }, {
 
645
                FuncName: "CreateFile",
 
646
                Args: []interface{}{
 
647
                        filename,
 
648
                        // The contents of the file will always pass this test. We are
 
649
                        // testing the sequence of commands. The output of CreateFile
 
650
                        // is tested by tests that call checkCreateFileCall.
 
651
                        createFileOutput,
 
652
                        os.FileMode(0644),
 
653
                },
 
654
        }, {
 
655
                FuncName: "LinkUnitFiles",
 
656
                Args: []interface{}{
 
657
                        []string{filename},
 
658
                        false,
 
659
                        true,
 
660
                },
 
661
        }, {
 
662
                FuncName: "Reload",
 
663
        }, {
 
664
                FuncName: "EnableUnitFiles",
 
665
                Args: []interface{}{
 
666
                        []string{filename},
 
667
                        false,
 
668
                        true,
 
669
                },
 
670
        }, {
 
671
                FuncName: "Close",
 
672
        }})
 
673
        s.checkCreateFileCall(c, 2, filename, s.newConfStr(s.name), 0644)
 
674
}
 
675
 
 
676
func (s *initSystemSuite) TestInstallAlreadyInstalled(c *gc.C) {
 
677
        s.addService("jujud-machine-0", "inactive")
 
678
        s.addListResponse()
 
679
        s.setConf(c, s.conf)
 
680
 
 
681
        err := s.service.Install()
 
682
        c.Assert(err, jc.ErrorIsNil)
 
683
 
 
684
        s.stub.CheckCallNames(c,
 
685
                "RunCommand",
 
686
                "RunCommand",
 
687
        )
 
688
}
 
689
 
 
690
func (s *initSystemSuite) TestInstallZombie(c *gc.C) {
 
691
        s.addService("jujud-machine-0", "active")
 
692
        s.addListResponse()
 
693
        // We force the systemd API to return a slightly different conf.
 
694
        // In this case we simply set a different Env value between the
 
695
        // conf we are installing and the conf returned by the systemd API.
 
696
        // This causes Service.Exists to return false.
 
697
        conf := common.Conf{
 
698
                Desc:      s.conf.Desc,
 
699
                ExecStart: s.conf.ExecStart,
 
700
                Env:       map[string]string{"a": "b"},
 
701
        }
 
702
        s.setConf(c, conf)
 
703
        s.addListResponse()
 
704
        s.ch <- "done"
 
705
 
 
706
        conf.Env["a"] = "c"
 
707
        service, err := systemd.NewService(s.name, conf, s.dataDir)
 
708
        c.Assert(err, jc.ErrorIsNil)
 
709
        err = service.Install()
 
710
        c.Assert(err, jc.ErrorIsNil)
 
711
 
 
712
        s.stub.CheckCallNames(c,
 
713
                "RunCommand",
 
714
                "RunCommand",
 
715
                "ListUnits",
 
716
                "Close",
 
717
                "StopUnit",
 
718
                "Close",
 
719
                "RunCommand",
 
720
                "DisableUnitFiles",
 
721
                "Reload",
 
722
                "RemoveAll",
 
723
                "Close",
 
724
                "MkdirAll",
 
725
                "CreateFile",
 
726
                "LinkUnitFiles",
 
727
                "Reload",
 
728
                "EnableUnitFiles",
 
729
                "Close",
 
730
        )
 
731
        filename := fmt.Sprintf("%s/init/%s/%s.service", s.dataDir, s.name, s.name)
 
732
        content := s.newConfStrEnv(s.name, `"a=c"`)
 
733
        s.checkCreateFileCall(c, 12, filename, content, 0644)
 
734
}
 
735
 
 
736
func (s *initSystemSuite) TestInstallMultiline(c *gc.C) {
 
737
        scriptPath := fmt.Sprintf("%s/init/%s/exec-start.sh", s.dataDir, s.name)
 
738
        cmd := "a\nb\nc"
 
739
        s.service.Service.Conf.ExecStart = scriptPath
 
740
        s.service.Script = []byte(cmd)
 
741
 
 
742
        err := s.service.Install()
 
743
        c.Assert(err, jc.ErrorIsNil)
 
744
 
 
745
        s.stub.CheckCallNames(c,
 
746
                "RunCommand",
 
747
                "MkdirAll",
 
748
                "CreateFile",
 
749
                "CreateFile",
 
750
                "LinkUnitFiles",
 
751
                "Reload",
 
752
                "EnableUnitFiles",
 
753
                "Close",
 
754
        )
 
755
        s.checkCreateFileCall(c, 2, scriptPath, cmd, 0755)
 
756
        filename := fmt.Sprintf("%s/init/%s/%s.service", s.dataDir, s.name, s.name)
 
757
        content := s.newConfStrCmd(s.name, scriptPath)
 
758
        s.checkCreateFileCall(c, 3, filename, content, 0644)
 
759
}
 
760
 
 
761
func (s *initSystemSuite) TestInstallEmptyConf(c *gc.C) {
 
762
        s.service.Service.Conf = common.Conf{}
 
763
 
 
764
        err := s.service.Install()
 
765
 
 
766
        c.Check(err, gc.ErrorMatches, `.*missing conf.*`)
 
767
        s.stub.CheckCalls(c, nil)
 
768
}
 
769
 
 
770
func (s *initSystemSuite) TestInstallCommands(c *gc.C) {
 
771
        name := "jujud-machine-0"
 
772
        commands, err := s.service.InstallCommands()
 
773
        c.Assert(err, jc.ErrorIsNil)
 
774
 
 
775
        test := systemdtesting.WriteConfTest{
 
776
                Service:  name,
 
777
                DataDir:  s.dataDir,
 
778
                Expected: s.newConfStr(name),
 
779
        }
 
780
        test.CheckCommands(c, commands)
 
781
}
 
782
 
 
783
func (s *initSystemSuite) TestInstallCommandsLogfile(c *gc.C) {
 
784
        name := "jujud-machine-0"
 
785
        s.conf.Logfile = "/var/log/juju/machine-0.log"
 
786
        service := s.newService(c)
 
787
        commands, err := service.InstallCommands()
 
788
        c.Assert(err, jc.ErrorIsNil)
 
789
 
 
790
        user, group := systemd.SyslogUserGroup()
 
791
        test := systemdtesting.WriteConfTest{
 
792
                Service: name,
 
793
                DataDir: s.dataDir,
 
794
                Expected: strings.Replace(
 
795
                        s.newConfStr(name),
 
796
                        "ExecStart=/var/lib/juju/bin/jujud machine-0",
 
797
                        "ExecStart=/var/lib/juju/init/jujud-machine-0/exec-start.sh",
 
798
                        -1),
 
799
                Script: `
 
800
# Set up logging.
 
801
touch '/var/log/juju/machine-0.log'
 
802
chown `[1:] + user + `:` + group + ` '/var/log/juju/machine-0.log'
 
803
chmod 0600 '/var/log/juju/machine-0.log'
 
804
exec >> '/var/log/juju/machine-0.log'
 
805
exec 2>&1
 
806
 
 
807
# Run the script.
 
808
` + jujud + " machine-0",
 
809
        }
 
810
        test.CheckCommands(c, commands)
 
811
}
 
812
 
 
813
func (s *initSystemSuite) TestInstallCommandsShutdown(c *gc.C) {
 
814
        name := "juju-shutdown-job"
 
815
        conf, err := service.ShutdownAfterConf("cloud-final")
 
816
        c.Assert(err, jc.ErrorIsNil)
 
817
        svc, err := systemd.NewService(name, conf, s.dataDir)
 
818
        c.Assert(err, jc.ErrorIsNil)
 
819
        commands, err := svc.InstallCommands()
 
820
        c.Assert(err, jc.ErrorIsNil)
 
821
 
 
822
        test := systemdtesting.WriteConfTest{
 
823
                Service: name,
 
824
                DataDir: s.dataDir,
 
825
                Expected: `
 
826
[Unit]
 
827
Description=juju shutdown job
 
828
After=syslog.target
 
829
After=network.target
 
830
After=systemd-user-sessions.service
 
831
After=cloud-final
 
832
 
 
833
[Service]
 
834
ExecStart=/sbin/shutdown -h now
 
835
ExecStopPost=/bin/systemctl disable juju-shutdown-job.service
 
836
 
 
837
[Install]
 
838
WantedBy=multi-user.target
 
839
`[1:],
 
840
        }
 
841
        test.CheckCommands(c, commands)
 
842
}
 
843
 
 
844
func (s *initSystemSuite) TestInstallCommandsEmptyConf(c *gc.C) {
 
845
        s.service.Service.Conf = common.Conf{}
 
846
 
 
847
        _, err := s.service.InstallCommands()
 
848
 
 
849
        c.Check(err, gc.ErrorMatches, `.*missing conf.*`)
 
850
        s.stub.CheckCalls(c, nil)
 
851
}
 
852
 
 
853
func (s *initSystemSuite) TestStartCommands(c *gc.C) {
 
854
        commands, err := s.service.StartCommands()
 
855
        c.Assert(err, jc.ErrorIsNil)
 
856
 
 
857
        c.Check(commands, jc.DeepEquals, []string{
 
858
                "/bin/systemctl start jujud-machine-0.service",
 
859
        })
 
860
}