Skip to content

Commit

Permalink
Merge pull request #2920 from ssweeny/fix-oneshot-daemons
Browse files Browse the repository at this point in the history
wrappers/services: RemainAfterExit=yes for oneshot daemons w/ stop cmds
  • Loading branch information
chipaca authored Feb 23, 2017
2 parents c84bc4c + a4f0c67 commit e8fc228
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 7 deletions.
16 changes: 15 additions & 1 deletion wrappers/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func RemoveSnapServices(s *snap.Info, inter interacter) error {

func genServiceFile(appInfo *snap.AppInfo) string {
serviceTemplate := `[Unit]
# Auto-generated, DO NO EDIT
# Auto-generated, DO NOT EDIT
Description=Service for snap application {{.App.Snap.Name}}.{{.App.Name}}
Requires={{.MountUnit}}
Wants={{.PrerequisiteTarget}}
Expand All @@ -186,6 +186,7 @@ WorkingDirectory={{.App.Snap.DataDir}}
{{if .App.PostStopCommand}}ExecStopPost={{.App.LauncherPostStopCommand}}{{end}}
{{if .StopTimeout}}TimeoutStopSec={{.StopTimeout.Seconds}}{{end}}
Type={{.App.Daemon}}
{{if .Remain}}RemainAfterExit={{.Remain}}{{end}}
{{if .App.BusName}}BusName={{.App.BusName}}{{end}}
[Install]
Expand All @@ -204,6 +205,17 @@ WantedBy={{.ServicesTarget}}
restartCond = systemd.RestartOnFailure.String()
}

var remain string
if appInfo.Daemon == "oneshot" {
// any restart condition other than "no" is invalid for oneshot daemons
restartCond = "no"
// If StopExec is present for a oneshot service than we also need
// RemainAfterExit=yes
if appInfo.StopCommand != "" {
remain = "yes"
}
}

wrapperData := struct {
App *snap.AppInfo

Expand All @@ -212,6 +224,7 @@ WantedBy={{.ServicesTarget}}
ServicesTarget string
PrerequisiteTarget string
MountUnit string
Remain string

Home string
EnvVars string
Expand All @@ -223,6 +236,7 @@ WantedBy={{.ServicesTarget}}
ServicesTarget: systemd.ServicesTarget,
PrerequisiteTarget: systemd.PrerequisiteTarget,
MountUnit: filepath.Base(systemd.MountUnitPath(appInfo.Snap.MountDir())),
Remain: remain,

// systemd runs as PID 1 so %h will not work.
Home: "/root",
Expand Down
37 changes: 31 additions & 6 deletions wrappers/services_gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
. "gopkg.in/check.v1"

"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/snap/snaptest"
"github.com/snapcore/snapd/systemd"
"github.com/snapcore/snapd/timeout"
"github.com/snapcore/snapd/wrappers"
Expand All @@ -35,7 +36,7 @@ type servicesWrapperGenSuite struct{}
var _ = Suite(&servicesWrapperGenSuite{})

const expectedServiceFmt = `[Unit]
# Auto-generated, DO NO EDIT
# Auto-generated, DO NOT EDIT
Description=Service for snap application snap.app
Requires=snap-snap-44.mount
Wants=network-online.target
Expand All @@ -44,7 +45,7 @@ X-Snappy=yes
[Service]
ExecStart=/usr/bin/snap run snap.app
Restart=on-failure
Restart=%s
WorkingDirectory=/var/snap/snap/44
ExecStop=/usr/bin/snap run --command=stop snap.app
ExecReload=/usr/bin/snap run --command=reload snap.app
Expand All @@ -57,13 +58,14 @@ WantedBy=multi-user.target
`

var (
expectedAppService = fmt.Sprintf(expectedServiceFmt, "simple\n")
expectedDbusService = fmt.Sprintf(expectedServiceFmt, "dbus\nBusName=foo.bar.baz")
expectedAppService = fmt.Sprintf(expectedServiceFmt, "on-failure", "simple\n\n")
expectedDbusService = fmt.Sprintf(expectedServiceFmt, "on-failure", "dbus\n\nBusName=foo.bar.baz")
expectedOneshotService = fmt.Sprintf(expectedServiceFmt, "no", "oneshot\nRemainAfterExit=yes\n")
)

var (
expectedServiceWrapperFmt = `[Unit]
# Auto-generated, DO NO EDIT
# Auto-generated, DO NOT EDIT
Description=Service for snap application xkcd-webserver.xkcd-webserver
Requires=snap-xkcd\x2dwebserver-44.mount
Wants=network-online.target
Expand All @@ -81,7 +83,7 @@ TimeoutStopSec=30
Type=%s
%s
`
expectedTypeForkingWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "forking\n", "\n[Install]\nWantedBy=multi-user.target")
expectedTypeForkingWrapper = fmt.Sprintf(expectedServiceWrapperFmt, "forking", "\n\n\n[Install]\nWantedBy=multi-user.target")
)

func (s *servicesWrapperGenSuite) TestGenerateSnapServiceFile(c *C) {
Expand Down Expand Up @@ -201,3 +203,26 @@ apps:

c.Assert(wrapperText, Equals, expectedDbusService)
}

func (s *servicesWrapperGenSuite) TestGenOneshotServiceFile(c *C) {

info := snaptest.MockInfo(c, `
name: snap
version: 1.0
apps:
app:
command: bin/start
stop-command: bin/stop
reload-command: bin/reload
post-stop-command: bin/stop --post
stop-timeout: 10s
daemon: oneshot
`, &snap.SideInfo{Revision: snap.R(44)})

app := info.Apps["app"]

wrapperText, err := wrappers.GenerateSnapServiceFile(app)
c.Assert(err, IsNil)

c.Assert(wrapperText, Equals, expectedOneshotService)
}

0 comments on commit e8fc228

Please sign in to comment.