Select Git revision
Forked from
GitLab.org / gitlab-runner
9707 commits behind the upstream repository.
-
Lorenzo Villani authored
`entry.String()` returns both the string representation of the log entry and a possible error. Before this patch we were sending both to the log writer, which accepts a varargs `interface{}` ending up with spurious `<nil>` lines in syslog. With this patch we try to get to the string representation and perform an early return in case of errors, then pass only the string to the underlying `service.Logger`. Ref #2453
Lorenzo Villani authored`entry.String()` returns both the string representation of the log entry and a possible error. Before this patch we were sending both to the log writer, which accepts a varargs `interface{}` ending up with spurious `<nil>` lines in syslog. With this patch we try to get to the string representation and perform an early return in case of errors, then pass only the string to the underlying `service.Logger`. Ref #2453
service.go 5.75 KiB
package commands
import (
"fmt"
"os"
"runtime"
"github.com/Sirupsen/logrus"
"github.com/ayufan/golang-kardianos-service"
"github.com/urfave/cli"
"gitlab.com/gitlab-org/gitlab-runner/common"
"gitlab.com/gitlab-org/gitlab-runner/helpers"
"gitlab.com/gitlab-org/gitlab-runner/helpers/service"
)
const (
defaultServiceName = "gitlab-runner"
defaultDisplayName = "GitLab Runner"
defaultDescription = "GitLab Runner"
)
type ServiceLogHook struct {
service.Logger
Level logrus.Level
}
func (s *ServiceLogHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
logrus.WarnLevel,
logrus.InfoLevel,
}
}
func (s *ServiceLogHook) Fire(entry *logrus.Entry) error {
if entry.Level > s.Level {
return nil
}
msg, err := entry.String()
if err != nil {
return err
}
switch entry.Level {
case logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel:
s.Error(msg)
case logrus.WarnLevel:
s.Warning(msg)
case logrus.InfoLevel:
s.Info(msg)
}
return nil
}
type NullService struct {
}
func (n *NullService) Start(s service.Service) error {
return nil
}
func (n *NullService) Stop(s service.Service) error {
return nil
}
func runServiceInstall(s service.Service, c *cli.Context) error {
if user := c.String("user"); user == "" && os.Getuid() == 0 {
logrus.Fatal("Please specify user that will run gitlab-runner service")
}
if configFile := c.String("config"); configFile != "" {
// try to load existing config
config := common.NewConfig()
err := config.LoadConfig(configFile)
if err != nil {
return err
}
// save config for the first time
if !config.Loaded {
err = config.SaveConfig(configFile)
if err != nil {
return err
}
}
}
return service.Control(s, "install")
}
func runServiceStatus(displayName string, s service.Service, c *cli.Context) error {
err := s.Status()
if err == nil {
fmt.Println(displayName+":", "Service is running!")
} else {
fmt.Fprintln(os.Stderr, displayName+":", err)
os.Exit(1)
}
return nil
}
func getServiceArguments(c *cli.Context) (arguments []string) {
if wd := c.String("working-directory"); wd != "" {
arguments = append(arguments, "--working-directory", wd)
}
if config := c.String("config"); config != "" {
arguments = append(arguments, "--config", config)
}
if sn := c.String("service"); sn != "" {
arguments = append(arguments, "--service", sn)
}
arguments = append(arguments, "--syslog")
return
}
func createServiceConfig(c *cli.Context) (svcConfig *service.Config) {
svcConfig = &service.Config{
Name: c.String("service"),
DisplayName: c.String("service"),
Description: defaultDescription,
Arguments: []string{"run"},
}
svcConfig.Arguments = append(svcConfig.Arguments, getServiceArguments(c)...)
switch runtime.GOOS {
case "linux":
if os.Getuid() != 0 {
logrus.Fatal("Please run the commands as root")
}
if user := c.String("user"); user != "" {
svcConfig.Arguments = append(svcConfig.Arguments, "--user", user)
}
case "darwin":
svcConfig.Option = service.KeyValue{
"KeepAlive": true,
"RunAtLoad": true,
"UserService": os.Getuid() != 0,
}
if user := c.String("user"); user != "" {
if os.Getuid() == 0 {
svcConfig.Arguments = append(svcConfig.Arguments, "--user", user)
} else {
logrus.Fatalln("The --user is not supported for non-root users")
}
}
case "windows":
svcConfig.Option = service.KeyValue{
"Password": c.String("password"),
}
svcConfig.UserName = c.String("user")
}
return
}
func RunServiceControl(c *cli.Context) {
svcConfig := createServiceConfig(c)
s, err := service_helpers.New(&NullService{}, svcConfig)
if err != nil {
logrus.Fatal(err)
}
switch c.Command.Name {
case "install":
err = runServiceInstall(s, c)
case "status":
err = runServiceStatus(svcConfig.DisplayName, s, c)
default:
err = service.Control(s, c.Command.Name)
}
if err != nil {
logrus.Fatal(err)
}
}
func init() {
flags := []cli.Flag{
cli.StringFlag{
Name: "service, n",
Value: defaultServiceName,
Usage: "Specify service name to use",
},
}
installFlags := flags
installFlags = append(installFlags, cli.StringFlag{
Name: "working-directory, d",
Value: helpers.GetCurrentWorkingDirectory(),
Usage: "Specify custom root directory where all data are stored",
})
installFlags = append(installFlags, cli.StringFlag{
Name: "config, c",
Value: getDefaultConfigFile(),
Usage: "Specify custom config file",
})
if runtime.GOOS == "windows" {
installFlags = append(installFlags, cli.StringFlag{
Name: "user, u",
Value: "",
Usage: "Specify user-name to secure the runner",
})
installFlags = append(installFlags, cli.StringFlag{
Name: "password, p",
Value: "",
Usage: "Specify user password to install service (required)",
})
} else if os.Getuid() == 0 {
installFlags = append(installFlags, cli.StringFlag{
Name: "user, u",
Value: "",
Usage: "Specify user-name to secure the runner",
})
}
common.RegisterCommand(cli.Command{
Name: "install",
Usage: "install service",
Action: RunServiceControl,
Flags: installFlags,
})
common.RegisterCommand(cli.Command{
Name: "uninstall",
Usage: "uninstall service",
Action: RunServiceControl,
Flags: flags,
})
common.RegisterCommand(cli.Command{
Name: "start",
Usage: "start service",
Action: RunServiceControl,
Flags: flags,
})
common.RegisterCommand(cli.Command{
Name: "stop",
Usage: "stop service",
Action: RunServiceControl,
Flags: flags,
})
common.RegisterCommand(cli.Command{
Name: "restart",
Usage: "restart service",
Action: RunServiceControl,
Flags: flags,
})
common.RegisterCommand(cli.Command{
Name: "status",
Usage: "get status of a service",
Action: RunServiceControl,
Flags: flags,
})
}