diff --git a/go.mod b/go.mod index 6023dca994..c99fefc9a3 100644 --- a/go.mod +++ b/go.mod @@ -22,9 +22,8 @@ require ( github.com/jedisct1/go-sieve-cache v0.1.9 github.com/jedisct1/xsecretbox v0.0.0-20241212092125-3afc4917ac41 github.com/k-sone/critbitgo v1.4.0 - github.com/kardianos/service v1.2.4 + github.com/kardianos/service v1.3.0 github.com/lifenjoiner/dhcpdns v0.0.7 - github.com/miekg/dns v1.1.72 github.com/powerman/check v1.9.1 github.com/quic-go/quic-go v0.60.0 golang.org/x/crypto v0.53.0 @@ -45,10 +44,7 @@ require ( github.com/quic-go/qpack v0.6.0 // indirect github.com/smartystreets/goconvey v1.8.1 // indirect go.uber.org/mock v0.6.0 // indirect - golang.org/x/mod v0.37.0 // indirect - golang.org/x/sync v0.21.0 // indirect golang.org/x/text v0.38.0 // indirect - golang.org/x/tools v0.46.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260618152121-87f3d3e198d3 // indirect google.golang.org/grpc v1.81.1 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/go.sum b/go.sum index f71fbb346a..54c292a91e 100644 --- a/go.sum +++ b/go.sum @@ -54,12 +54,10 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/k-sone/critbitgo v1.4.0 h1:l71cTyBGeh6X5ATh6Fibgw3+rtNT80BA0uNNWgkPrbE= github.com/k-sone/critbitgo v1.4.0/go.mod h1:7E6pyoyADnFxlUBEKcnfS49b7SUAQGMK+OAp/UQvo0s= -github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2OgBk= -github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc= +github.com/kardianos/service v1.3.0 h1:/LGy+xPP2TM+GLTiCZ2di7cy0Jd/qrawlTUfqKYFdTI= +github.com/kardianos/service v1.3.0/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc= github.com/lifenjoiner/dhcpdns v0.0.7 h1:VJM2aFWHU9V7M5v4UYYNaHhIHZkbdvSI6WGGpq6/TNQ= github.com/lifenjoiner/dhcpdns v0.0.7/go.mod h1:BixeaGeafYzDIuDCYIUbSOdi4m+TScpzI9cZGYgzgSk= -github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= -github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= @@ -84,18 +82,12 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= -golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= -golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= -golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= -golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= -golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk= -golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys= google.golang.org/genproto/googleapis/rpc v0.0.0-20260618152121-87f3d3e198d3 h1:phvBWCAQMGN1945mp5fjCXP6jEF0+a0+4TjokS4sxNY= google.golang.org/genproto/googleapis/rpc v0.0.0-20260618152121-87f3d3e198d3/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= diff --git a/vendor/github.com/kardianos/service/service.go b/vendor/github.com/kardianos/service/service.go index 130fc22d48..adef097e15 100644 --- a/vendor/github.com/kardianos/service/service.go +++ b/vendor/github.com/kardianos/service/service.go @@ -231,6 +231,53 @@ func New(i Interface, c *Config) (Service, error) { // - OnFailureDelayDuration string ( "1s" ) - Delay before restarting the service, time.Duration string. // // - OnFailureResetPeriod int ( 10 ) - Reset period for errors, seconds. +// +// # Custom service-file templates +// +// The LaunchdConfig, SystemdScript, UpstartScript, SysvScript, RCSScript, and +// OpenRCScript options each supply a template used to render the service file +// in place of the built-in one. Set one by placing the template string in +// Config.Option under the matching key: +// +// c := &service.Config{ +// Name: "myservice", +// Option: service.KeyValue{ +// "SystemdScript": myScript, // template string, syntax below +// }, +// } +// +// SysvScript is also the key read by the procd, AIX, FreeBSD, and Solaris +// backends; the key set available to a custom script is whatever the active +// init system passes (see below). +// +// Templates are rendered by a small built-in engine (not text/template). The +// supported actions are: +// +// - {{Key}} substitute a value. +// - {{Key | fn | fn}} substitute, piped through function(s). +// - {{if Key}}…{{end}} include the body when Key is non-empty. +// - {{if Key}}…{{else}}…{{end}} with an else branch. +// - {{range Key}}…{{.}}…{{end}} repeat the body once per item of a list +// value, with {{.}} bound to the current item. +// - {{- …}} and {{… -}} trim whitespace before or after the action. +// +// Every value is a string or a list of strings; a list is also truthy in +// {{if}} when non-empty. There is no dotted field access and no arithmetic or +// boolean functions — any such logic is resolved before rendering. The exact +// keys and pipeline functions available for a given platform are precisely +// those used by that platform's default template, so read the corresponding +// source constant to see them: launchdConfig (darwin), systemdScript, +// upstartScript, sysvScript, rcsScript, openRCScript, procdScript, svcConfig +// (AIX), rcScript (FreeBSD), and manifest (Solaris). +// +// Compatibility: earlier versions parsed these options with the standard +// library text/template. Custom scripts written for that engine — using dotted +// fields such as {{.Name}}, the and/or/not/eq/gt functions, or method calls — +// must be rewritten in the syntax above; they will otherwise fail to render +// with an "unknown template key" error. text/template was removed because it +// reaches reflect.Value.MethodByName, which forces the linker into a +// conservative mode that defeats dead-code elimination and substantially +// inflates binaries importing this package. type KeyValue map[string]interface{} // bool returns the value of the given name, assuming the value is a boolean. diff --git a/vendor/github.com/kardianos/service/service_aix.go b/vendor/github.com/kardianos/service/service_aix.go index de7a907272..eda2aa4b1d 100644 --- a/vendor/github.com/kardianos/service/service_aix.go +++ b/vendor/github.com/kardianos/service/service_aix.go @@ -18,7 +18,6 @@ import ( "strconv" "strings" "syscall" - "text/template" "time" ) @@ -96,21 +95,13 @@ func (s *aixService) Platform() string { return version } -func (s *aixService) template() *template.Template { - functions := template.FuncMap{ - "bool": func(v bool) string { - if v { - return "true" - } - return "false" - }, - } +var svcConfigTemplate = mustParse(svcConfig) - customConfig := s.Option.string(optionSysvScript, "") - if customConfig != "" { - return template.Must(template.New("").Funcs(functions).Parse(customConfig)) +func (s *aixService) template() (*tmpl, error) { + if custom := s.Option.string(optionSysvScript, ""); custom != "" { + return parseTemplate(custom) } - return template.Must(template.New("").Funcs(functions).Parse(svcConfig)) + return svcConfigTemplate, nil } func (s *aixService) configPath() (string, error) { @@ -147,15 +138,20 @@ func (s *aixService) Install() error { } defer f.Close() - to := struct { - *Config - Path string - }{ - Config: s.Config, - Path: path, + data := map[string]any{ + "Name": s.Config.Name, + "Path": path, } - if err = s.template().Execute(f, &to); err != nil { + t, err := s.template() + if err != nil { + return err + } + out, err := t.render(data, nil) + if err != nil { + return err + } + if _, err = f.WriteString(out); err != nil { return err } @@ -271,13 +267,13 @@ func (s *aixService) SystemLogger(errs chan<- error) (Logger, error) { return newSysLogger(s.Name, errs) } -var svcConfig = `#!/bin/ksh +const svcConfig = `#!/bin/ksh case "$1" in start) - startsrc -s {{.Name}} + startsrc -s {{Name}} ;; stop) - stopsrc -s {{.Name}} + stopsrc -s {{Name}} ;; *) echo "Usage: $0 {start|stop}" diff --git a/vendor/github.com/kardianos/service/service_darwin.go b/vendor/github.com/kardianos/service/service_darwin.go index 727ef2cb31..4d8fd9fb05 100644 --- a/vendor/github.com/kardianos/service/service_darwin.go +++ b/vendor/github.com/kardianos/service/service_darwin.go @@ -14,7 +14,6 @@ import ( "regexp" "strings" "syscall" - "text/template" "time" ) @@ -134,22 +133,38 @@ func (s *darwinLaunchdService) getLogPath(logDir, logType string) string { return fmt.Sprintf("%s/%s.%s.log", logDir, s.Name, logType) } -func (s *darwinLaunchdService) template() *template.Template { - functions := template.FuncMap{ - "bool": func(v bool) string { - if v { - return "true" - } - return "false" - }, - } +// plistEscaper matches text/template's html escaper, which the launchd plist +// was previously rendered with. +var plistEscaper = strings.NewReplacer( + `&`, "&", + `'`, "'", + `<`, "<", + `>`, ">", + `"`, """, +) + +// launchdFuncs is the pipeline function map for the launchd plist: html escapes +// a value for XML. +var launchdFuncs = map[string]tmplFunc{ + "html": func(s string) (string, error) { return plistEscaper.Replace(s), nil }, +} - customConfig := s.Option.string(optionLaunchdConfig, "") +var launchdTemplate = mustParse(launchdConfig) + +func (s *darwinLaunchdService) template() (*tmpl, error) { + if custom := s.Option.string(optionLaunchdConfig, ""); custom != "" { + return parseTemplate(custom) + } + return launchdTemplate, nil +} - if customConfig != "" { - return template.Must(template.New("").Funcs(functions).Parse(customConfig)) +// launchdBool renders a Go bool as the "true"/"false" element name used in the +// plist (previously the text/template "bool" function). +func launchdBool(v bool) string { + if v { + return "true" } - return template.Must(template.New("").Funcs(functions).Parse(launchdConfig)) + return "false" } func (s *darwinLaunchdService) Install() error { @@ -182,25 +197,37 @@ func (s *darwinLaunchdService) Install() error { } stdOutPath, stdErrPath, _ := s.getLogPaths() - var to = &struct { - *Config - Path string - - KeepAlive, RunAtLoad bool - SessionCreate bool - StandardOutPath string - StandardErrorPath string - }{ - Config: s.Config, - Path: path, - KeepAlive: s.Option.bool(optionKeepAlive, optionKeepAliveDefault), - RunAtLoad: s.Option.bool(optionRunAtLoad, optionRunAtLoadDefault), - SessionCreate: s.Option.bool(optionSessionCreate, optionSessionCreateDefault), - StandardOutPath: stdOutPath, - StandardErrorPath: stdErrPath, + + c := s.Config + data := map[string]any{ + "Name": c.Name, + "Path": path, + "Arguments": c.Arguments, + "ChRoot": c.ChRoot, + "UserName": c.UserName, + "WorkingDirectory": c.WorkingDirectory, + "KeepAlive": launchdBool(s.Option.bool(optionKeepAlive, optionKeepAliveDefault)), + "RunAtLoad": launchdBool(s.Option.bool(optionRunAtLoad, optionRunAtLoadDefault)), + "SessionCreate": launchdBool(s.Option.bool(optionSessionCreate, optionSessionCreateDefault)), + "StandardOutPath": stdOutPath, + "StandardErrorPath": stdErrPath, + // Each entry is the two escaped plist lines for one variable. + "EnvVars": envVars(c.EnvVars, func(k, v string) string { + return "\t\t" + plistEscaper.Replace(k) + "\n" + + "\t\t" + plistEscaper.Replace(v) + "" + }), } - return s.template().Execute(f, to) + t, err := s.template() + if err != nil { + return err + } + out, err := t.render(data, launchdFuncs) + if err != nil { + return err + } + _, err = f.WriteString(out) + return err } func (s *darwinLaunchdService) Uninstall() error { @@ -290,58 +317,39 @@ func (s *darwinLaunchdService) SystemLogger(errs chan<- error) (Logger, error) { return newSysLogger(s.Name, errs) } -var launchdConfig = ` +const launchdConfig = ` Disabled - {{- if .EnvVars}} - EnvironmentVariables + {{if EnvVars}}EnvironmentVariables - {{- range $k, $v := .EnvVars}} - {{html $k}} - {{html $v}} - {{- end}} - - {{- end}} - KeepAlive - <{{bool .KeepAlive}}/> +{{range EnvVars}}{{.}} +{{end}} + {{end}}KeepAlive + <{{KeepAlive}}/> Label - {{html .Name}} + {{Name | html}} ProgramArguments - {{html .Path}} - {{- if .Config.Arguments}} - {{- range .Config.Arguments}} - {{html .}} - {{- end}} - {{- end}} - - {{- if .ChRoot}} - RootDirectory - {{html .ChRoot}} - {{- end}} - RunAtLoad - <{{bool .RunAtLoad}}/> + {{Path | html}} +{{range Arguments}} {{. | html}} +{{end}} + {{if ChRoot}}RootDirectory + {{ChRoot | html}} + {{end}}RunAtLoad + <{{RunAtLoad}}/> SessionCreate - <{{bool .SessionCreate}}/> - {{- if .StandardErrorPath}} - StandardErrorPath - {{html .StandardErrorPath}} - {{- end}} - {{- if .StandardOutPath}} - StandardOutPath - {{html .StandardOutPath}} - {{- end}} - {{- if .UserName}} - UserName - {{html .UserName}} - {{- end}} - {{- if .WorkingDirectory}} - WorkingDirectory - {{html .WorkingDirectory}} - {{- end}} - + <{{SessionCreate}}/> + {{if StandardErrorPath}}StandardErrorPath + {{StandardErrorPath | html}} + {{end}}{{if StandardOutPath}}StandardOutPath + {{StandardOutPath | html}} + {{end}}{{if UserName}}UserName + {{UserName | html}} + {{end}}{{if WorkingDirectory}}WorkingDirectory + {{WorkingDirectory | html}} + {{end}} ` diff --git a/vendor/github.com/kardianos/service/service_freebsd.go b/vendor/github.com/kardianos/service/service_freebsd.go index 752f5feb85..4570773039 100644 --- a/vendor/github.com/kardianos/service/service_freebsd.go +++ b/vendor/github.com/kardianos/service/service_freebsd.go @@ -10,7 +10,6 @@ import ( "os/signal" "path/filepath" "syscall" - "text/template" ) const version = "freebsd" @@ -70,23 +69,13 @@ func (s *freebsdService) Platform() string { return version } -func (s *freebsdService) template() *template.Template { - functions := template.FuncMap{ - "bool": func(v bool) string { - if v { - return "true" - } - return "false" - }, - } - - customConfig := s.Option.string(optionSysvScript, "") +var rcTemplate = mustParse(rcScript) - if customConfig != "" { - return template.Must(template.New("").Funcs(functions).Parse(customConfig)) - } else { - return template.Must(template.New("").Funcs(functions).Parse(rcScript)) +func (s *freebsdService) template() (*tmpl, error) { + if custom := s.Option.string(optionSysvScript, ""); custom != "" { + return parseTemplate(custom) } + return rcTemplate, nil } func (s *freebsdService) configPath() (cp string, err error) { @@ -120,18 +109,25 @@ func (s *freebsdService) Install() error { } defer f.Close() - var to = &struct { - *Config - Path string - }{ - s.Config, - path, + c := s.Config + data := map[string]any{ + "Name": c.Name, + "Path": path, + "Arguments": c.Arguments, + "WorkingDirectory": c.WorkingDirectory, } - err = s.template().Execute(f, to) + t, err := s.template() if err != nil { return err } + out, err := t.render(data, nil) + if err != nil { + return err + } + if _, err = f.WriteString(out); err != nil { + return err + } if err = os.Chmod(confPath, 0755); err != nil { return err @@ -207,20 +203,20 @@ func (s *freebsdService) SystemLogger(errs chan<- error) (Logger, error) { return newSysLogger(s.Name, errs) } -var rcScript = `#!/bin/sh +const rcScript = `#!/bin/sh -# PROVIDE: {{.Name}} +# PROVIDE: {{Name}} # REQUIRE: SERVERS # KEYWORD: shutdown . /etc/rc.subr -name="{{.Name}}" -{{.Name}}_env="IS_DAEMON=1" +name="{{Name}}" +{{Name}}_env="IS_DAEMON=1" pidfile="/var/run/${name}.pid" command="/usr/sbin/daemon" -daemon_args="-P ${pidfile} -r -t \"${name}: daemon\"{{if .WorkingDirectory}} -c {{.WorkingDirectory}}{{end}}" -command_args="${daemon_args} {{.Path}}{{range .Arguments}} {{.}}{{end}}" +daemon_args="-P ${pidfile} -r -t \"${name}: daemon\"{{if WorkingDirectory}} -c {{WorkingDirectory}}{{end}}" +command_args="${daemon_args} {{Path}}{{range Arguments}} {{.}}{{end}}" run_rc_command "$1" ` diff --git a/vendor/github.com/kardianos/service/service_linux.go b/vendor/github.com/kardianos/service/service_linux.go index edd5a0abd3..ea32181768 100644 --- a/vendor/github.com/kardianos/service/service_linux.go +++ b/vendor/github.com/kardianos/service/service_linux.go @@ -209,11 +209,19 @@ func isInContainerCGroup(cgroupPath string) (bool, error) { return false, nil } -var tf = map[string]interface{}{ - "cmd": func(s string) string { - return `"` + strings.Replace(s, `"`, `\"`, -1) + `"` - }, - "cmdEscape": func(s string) string { - return strings.Replace(s, " ", `\x20`, -1) - }, +// cmdQuote and cmdEscape are the plain string transforms used when building +// service files. They are also exposed to custom user templates through tfs. +func cmdQuote(s string) string { + return `"` + strings.ReplaceAll(s, `"`, `\"`) + `"` +} + +func cmdEscape(s string) string { + return strings.ReplaceAll(s, " ", `\x20`) +} + +// tfs is the string-only function map for the mini template engine, exposing +// the cmd/cmdEscape pipeline functions to the built-in and custom templates. +var tfs = map[string]tmplFunc{ + "cmd": func(s string) (string, error) { return cmdQuote(s), nil }, + "cmdEscape": func(s string) (string, error) { return cmdEscape(s), nil }, } diff --git a/vendor/github.com/kardianos/service/service_openrc_linux.go b/vendor/github.com/kardianos/service/service_openrc_linux.go index c678e3aef6..1f12a085dd 100644 --- a/vendor/github.com/kardianos/service/service_openrc_linux.go +++ b/vendor/github.com/kardianos/service/service_openrc_linux.go @@ -9,7 +9,6 @@ import ( "os/signal" "regexp" "syscall" - "text/template" "time" ) @@ -55,13 +54,13 @@ func (s *openrc) Platform() string { return s.platform } -func (s *openrc) template() *template.Template { - customScript := s.Option.string(optionOpenRCScript, "") +var openRCTemplate = mustParse(openRCScript) - if customScript != "" { - return template.Must(template.New("").Funcs(tf).Parse(customScript)) +func (s *openrc) template() (*tmpl, error) { + if custom := s.Option.string(optionOpenRCScript, ""); custom != "" { + return parseTemplate(custom) } - return template.Must(template.New("").Funcs(tf).Parse(openRCScript)) + return openRCTemplate, nil } func newOpenRCService(i Interface, platform string, c *Config) (Service, error) { @@ -110,20 +109,36 @@ func (s *openrc) Install() error { return err } - var to = &struct { - *Config - Path string - LogDirectory string - }{ - s.Config, - path, - s.Option.string(optionLogDirectory, defaultLogDirectory), + c := s.Config + + // depend() lists each dependency on its own tab-indented line; bake the + // tab in here so the template is a plain {{range}}. + deps := make([]string, len(c.Dependencies)) + for i, d := range c.Dependencies { + deps[i] = "\t" + d + } + + data := map[string]any{ + "DisplayName": c.DisplayName, + "Description": c.Description, + "Path": path, + "Arguments": c.Arguments, + "Dependencies": deps, + "LogDirectory": s.Option.string(optionLogDirectory, defaultLogDirectory), + "EnvVars": envVars(c.EnvVars, func(k, v string) string { return "export " + k + "=" + v }), } - err = s.template().Execute(f, to) + t, err := s.template() + if err != nil { + return err + } + out, err := t.render(data, tfs) if err != nil { return err } + if _, err = f.WriteString(out); err != nil { + return err + } // run rc-update return s.runAction("add") } @@ -221,23 +236,16 @@ func (s *openrc) run(action string, args ...string) error { const openRCScript = `#!/sbin/openrc-run supervisor=supervise-daemon -name="{{.DisplayName}}" -description="{{.Description}}" -command={{.Path|cmdEscape}} -{{- if .Arguments }} -command_args="{{range .Arguments}}{{.}} {{end}}" -{{- end }} -name=$(basename $(readlink -f $command)) -supervise_daemon_args="--stdout {{.LogDirectory}}/${name}.log --stderr {{.LogDirectory}}/${name}.err" - -{{range $k, $v := .EnvVars -}} -export {{$k}}={{$v}} -{{end -}} - -{{- if .Dependencies }} -depend() { -{{- range $i, $dep := .Dependencies}} -{{"\t"}}{{$dep}}{{end}} -} -{{- end}} -` +name="{{DisplayName}}" +description="{{Description}}" +command={{Path | cmdEscape}} +{{if Arguments}}command_args="{{range Arguments}}{{.}} {{end}}" +{{end}}name=$(basename $(readlink -f $command)) +supervise_daemon_args="--stdout {{LogDirectory}}/${name}.log --stderr {{LogDirectory}}/${name}.err" + +{{range EnvVars}}{{.}} +{{end}} +{{if Dependencies}}depend() { +{{range Dependencies}}{{.}} +{{end}}} +{{end}}` diff --git a/vendor/github.com/kardianos/service/service_procd_linux.go b/vendor/github.com/kardianos/service/service_procd_linux.go index 3213784cd1..9de40c8d64 100644 --- a/vendor/github.com/kardianos/service/service_procd_linux.go +++ b/vendor/github.com/kardianos/service/service_procd_linux.go @@ -9,7 +9,6 @@ import ( "os" "os/exec" "strings" - "text/template" "time" ) @@ -39,13 +38,13 @@ func newProcdService(i Interface, platform string, c *Config) (Service, error) { return p, nil } -func (p *procd) template() *template.Template { - customScript := p.Option.string(optionSysvScript, "") +var procdTemplate = mustParse(procdScript) - if customScript != "" { - return template.Must(template.New("").Funcs(tf).Parse(customScript)) +func (p *procd) template() (*tmpl, error) { + if custom := p.Option.string(optionSysvScript, ""); custom != "" { + return parseTemplate(custom) } - return template.Must(template.New("").Funcs(tf).Parse(procdScript)) + return procdTemplate, nil } func (p *procd) Install() error { @@ -69,20 +68,24 @@ func (p *procd) Install() error { return err } - var to = &struct { - *Config - Path string - LogDirectory string - }{ - p.Config, - path, - p.Option.string(optionLogDirectory, defaultLogDirectory), + c := p.Config + data := map[string]any{ + "Path": path, + "Name": c.Name, + "Arguments": c.Arguments, } - err = p.template().Execute(f, to) + t, err := p.template() if err != nil { return err } + out, err := t.render(data, tfs) + if err != nil { + return err + } + if _, err = f.WriteString(out); err != nil { + return err + } if err = os.Chmod(confPath, 0755); err != nil { return err @@ -151,8 +154,8 @@ USE_PROCD=1 START=21 # Before network stops STOP=89 -cmd="{{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}" -name="{{.Name}}" +cmd="{{Path}}{{range Arguments}} {{. | cmd}}{{end}}" +name="{{Name}}" pid_file="/var/run/${name}.pid" start_service() { diff --git a/vendor/github.com/kardianos/service/service_rcs_linux.go b/vendor/github.com/kardianos/service/service_rcs_linux.go index 0fca97dcdd..cabf5b1d22 100644 --- a/vendor/github.com/kardianos/service/service_rcs_linux.go +++ b/vendor/github.com/kardianos/service/service_rcs_linux.go @@ -14,7 +14,6 @@ import ( "regexp" "strings" "syscall" - "text/template" "time" ) @@ -85,13 +84,13 @@ func (s *rcs) configPath() (cp string, err error) { return } -func (s *rcs) template() *template.Template { - customScript := s.Option.string(optionRCSScript, "") +var rcsTemplate = mustParse(rcsScript) - if customScript != "" { - return template.Must(template.New("").Funcs(tf).Parse(customScript)) +func (s *rcs) template() (*tmpl, error) { + if custom := s.Option.string(optionRCSScript, ""); custom != "" { + return parseTemplate(custom) } - return template.Must(template.New("").Funcs(tf).Parse(rcsScript)) + return rcsTemplate, nil } func (s *rcs) Install() error { @@ -115,20 +114,28 @@ func (s *rcs) Install() error { return err } - var to = &struct { - *Config - Path string - LogDirectory string - }{ - s.Config, - path, - s.Option.string(optionLogDirectory, defaultLogDirectory), + c := s.Config + data := map[string]any{ + "Description": c.Description, + "DisplayName": c.DisplayName, + "Name": c.Name, + "Path": path, + "Arguments": c.Arguments, + "WorkingDirectory": c.WorkingDirectory, + "LogDirectory": s.Option.string(optionLogDirectory, defaultLogDirectory), } - err = s.template().Execute(f, to) + t, err := s.template() if err != nil { return err } + out, err := t.render(data, tfs) + if err != nil { + return err + } + if _, err = f.WriteString(out); err != nil { + return err + } if err = os.Chmod(confPath, 0755); err != nil { return err @@ -216,25 +223,25 @@ func (s *rcs) Restart() error { const rcsScript = `#!/bin/sh # For RedHat and cousins: # chkconfig: - 99 01 -# description: {{.Description}} -# processname: {{.Path}} +# description: {{Description}} +# processname: {{Path}} ### BEGIN INIT INFO -# Provides: {{.Path}} +# Provides: {{Path}} # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: {{.DisplayName}} -# Description: {{.Description}} +# Short-Description: {{DisplayName}} +# Description: {{Description}} ### END INIT INFO -cmd="{{.Path}}{{range .Arguments}} {{.|cmd}}{{end}}" +cmd="{{Path}}{{range Arguments}} {{. | cmd}}{{end}}" -name={{.Name}} +name={{Name}} pid_file="/var/run/$name.pid" -stdout_log="{{.LogDirectory}}/$name.log" -stderr_log="{{.LogDirectory}}/$name.err" +stdout_log="{{LogDirectory}}/$name.log" +stderr_log="{{LogDirectory}}/$name.err" [ -e /etc/sysconfig/$name ] && . /etc/sysconfig/$name @@ -252,7 +259,7 @@ case "$1" in echo "Already started" else echo "Starting $name" - {{if .WorkingDirectory}}cd '{{.WorkingDirectory}}'{{end}} + {{if WorkingDirectory}}cd '{{WorkingDirectory}}'{{end}} $cmd >> "$stdout_log" 2>> "$stderr_log" & echo $! > "$pid_file" if ! is_running; then diff --git a/vendor/github.com/kardianos/service/service_solaris.go b/vendor/github.com/kardianos/service/service_solaris.go index 55e0074062..96ac4513f9 100644 --- a/vendor/github.com/kardianos/service/service_solaris.go +++ b/vendor/github.com/kardianos/service/service_solaris.go @@ -12,7 +12,6 @@ import ( "os/signal" "regexp" "syscall" - "text/template" "time" ) @@ -79,23 +78,13 @@ func (s *solarisService) Platform() string { return version } -func (s *solarisService) template() *template.Template { - functions := template.FuncMap{ - "bool": func(v bool) string { - if v { - return "true" - } - return "false" - }, - } - - customConfig := s.Option.string(optionSysvScript, "") +var manifestTemplate = mustParse(manifest) - if customConfig != "" { - return template.Must(template.New("").Funcs(functions).Parse(customConfig)) - } else { - return template.Must(template.New("").Funcs(functions).Parse(manifest)) +func (s *solarisService) template() (*tmpl, error) { + if custom := s.Option.string(optionSysvScript, ""); custom != "" { + return parseTemplate(custom) } + return manifestTemplate, nil } func (s *solarisService) configPath() (string, error) { @@ -132,19 +121,22 @@ func (s *solarisService) Install() error { if err := xml.EscapeText(escaped, []byte(s.DisplayName)); err == nil { Display = escaped.String() } - var to = &struct { - *Config - Prefix string - Display string - Path string - }{ - s.Config, - s.Prefix, - Display, - path, + data := map[string]any{ + "Name": s.Config.Name, + "Prefix": s.Prefix, + "Display": Display, + "Path": path, } - err = s.template().Execute(f, to) + t, err := s.template() + if err != nil { + return err + } + out, err := t.render(data, nil) + if err != nil { + return err + } + _, err = f.WriteString(out) if err != nil { return err } @@ -241,12 +233,12 @@ func (s *solarisService) SystemLogger(errs chan<- error) (Logger, error) { return newSysLogger(s.Name, errs) } -var manifest = ` +const manifest = ` - + @@ -278,13 +270,13 @@ var manifest = `