func (s *systemd) GenServiceFile(desc *ServiceDescription) string { serviceTemplate := `[Unit] Description={{.Description}} After=snapd.frameworks.target{{ if .Socket }} {{.SocketFileName}}{{end}} Requires=snapd.frameworks.target{{ if .Socket }} {{.SocketFileName}}{{end}} X-Snappy=yes [Service] ExecStart=/usr/bin/ubuntu-core-launcher {{.UdevAppName}} {{.AaProfile}} {{.FullPathStart}} Restart={{.Restart}} WorkingDirectory=/var{{.SnapPath}} Environment={{.EnvVars}} {{if .Stop}}ExecStop=/usr/bin/ubuntu-core-launcher {{.UdevAppName}} {{.AaProfile}} {{.FullPathStop}}{{end}} {{if .PostStop}}ExecStopPost=/usr/bin/ubuntu-core-launcher {{.UdevAppName}} {{.AaProfile}} {{.FullPathPostStop}}{{end}} {{if .StopTimeout}}TimeoutStopSec={{.StopTimeout.Seconds}}{{end}} Type={{.Type}} {{if .BusName}}BusName={{.BusName}}{{end}} [Install] WantedBy={{.ServiceSystemdTarget}} ` var templateOut bytes.Buffer t := template.Must(template.New("wrapper").Parse(serviceTemplate)) restartCond := desc.Restart.String() if restartCond == "" { restartCond = RestartOnFailure.String() } wrapperData := struct { // the service description ServiceDescription // and some composed values FullPathStart string FullPathStop string FullPathPostStop string ServiceSystemdTarget string SnapArch string Home string EnvVars string SocketFileName string Restart string Type string }{ *desc, filepath.Join(desc.SnapPath, desc.Start), filepath.Join(desc.SnapPath, desc.Stop), filepath.Join(desc.SnapPath, desc.PostStop), servicesSystemdTarget, arch.UbuntuArchitecture(), // systemd runs as PID 1 so %h will not work. "/root", "", desc.SocketFileName, restartCond, desc.Type, } allVars := snapenv.GetBasicSnapEnvVars(wrapperData) allVars = append(allVars, snapenv.GetUserSnapEnvVars(wrapperData)...) wrapperData.EnvVars = "\"" + strings.Join(allVars, "\" \"") + "\"" // allVars won't be empty if err := t.Execute(&templateOut, wrapperData); err != nil { // this can never happen, except we forget a variable logger.Panicf("Unable to execute template: %v", err) } return templateOut.String() }
func generateSnapBinaryWrapper(app *snap.AppInfo, pkgPath string) (string, error) { wrapperTemplate := `#!/bin/sh set -e # snap info {{.NewAppVars}} if [ ! -d "$SNAP_USER_DATA" ]; then mkdir -p "$SNAP_USER_DATA" fi export HOME="$SNAP_USER_DATA" # Snap name is: {{.SnapName}} # App name is: {{.AppName}} ubuntu-core-launcher {{.UdevAppName}} {{.AaProfile}} {{.Target}} "$@" ` if err := snap.ValidateApp(app); err != nil { return "", err } actualBinPath := binPathForBinary(pkgPath, app) var templateOut bytes.Buffer t := template.Must(template.New("wrapper").Parse(wrapperTemplate)) wrapperData := struct { SnapName string AppName string SnapArch string SnapPath string Version string Revision int UdevAppName string Home string Target string AaProfile string OldAppVars string NewAppVars string }{ SnapName: app.Snap.Name(), AppName: app.Name, SnapArch: arch.UbuntuArchitecture(), SnapPath: pkgPath, Version: app.Snap.Version, Revision: app.Snap.Revision, UdevAppName: app.SecurityTag(), Home: "$HOME", Target: actualBinPath, AaProfile: app.SecurityTag(), } newVars := []string{} for _, envVar := range append( snapenv.GetBasicSnapEnvVars(wrapperData), snapenv.GetUserSnapEnvVars(wrapperData)...) { newVars = append(newVars, quoteEnvVar(envVar)) } wrapperData.NewAppVars = strings.Join(newVars, "\n") t.Execute(&templateOut, wrapperData) return templateOut.String(), nil }