github.com/secure-build/gitlab-runner@v12.5.0+incompatible/commands/service.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"runtime"
     7  
     8  	"github.com/ayufan/golang-kardianos-service"
     9  	"github.com/sirupsen/logrus"
    10  	"github.com/urfave/cli"
    11  
    12  	"gitlab.com/gitlab-org/gitlab-runner/common"
    13  	"gitlab.com/gitlab-org/gitlab-runner/helpers"
    14  	"gitlab.com/gitlab-org/gitlab-runner/helpers/service"
    15  )
    16  
    17  const (
    18  	defaultServiceName = "gitlab-runner"
    19  	defaultDescription = "GitLab Runner"
    20  )
    21  
    22  type NullService struct {
    23  }
    24  
    25  func (n *NullService) Start(s service.Service) error {
    26  	return nil
    27  }
    28  
    29  func (n *NullService) Stop(s service.Service) error {
    30  	return nil
    31  }
    32  
    33  func runServiceInstall(s service.Service, c *cli.Context) error {
    34  	if user := c.String("user"); user == "" && os.Getuid() == 0 {
    35  		logrus.Fatal("Please specify user that will run gitlab-runner service")
    36  	}
    37  
    38  	if configFile := c.String("config"); configFile != "" {
    39  		// try to load existing config
    40  		config := common.NewConfig()
    41  		err := config.LoadConfig(configFile)
    42  		if err != nil {
    43  			return err
    44  		}
    45  
    46  		// save config for the first time
    47  		if !config.Loaded {
    48  			err = config.SaveConfig(configFile)
    49  			if err != nil {
    50  				return err
    51  			}
    52  		}
    53  	}
    54  	return service.Control(s, "install")
    55  }
    56  
    57  func runServiceStatus(displayName string, s service.Service) error {
    58  	err := s.Status()
    59  	if err == nil {
    60  		fmt.Println(displayName+":", "Service is running!")
    61  	} else {
    62  		fmt.Fprintln(os.Stderr, displayName+":", err)
    63  		os.Exit(1)
    64  	}
    65  	return nil
    66  }
    67  
    68  func getServiceArguments(c *cli.Context) (arguments []string) {
    69  	if wd := c.String("working-directory"); wd != "" {
    70  		arguments = append(arguments, "--working-directory", wd)
    71  	}
    72  
    73  	if config := c.String("config"); config != "" {
    74  		arguments = append(arguments, "--config", config)
    75  	}
    76  
    77  	if sn := c.String("service"); sn != "" {
    78  		arguments = append(arguments, "--service", sn)
    79  	}
    80  
    81  	syslog := !c.IsSet("syslog") || c.Bool("syslog")
    82  	if syslog {
    83  		arguments = append(arguments, "--syslog")
    84  	}
    85  
    86  	return
    87  }
    88  
    89  func createServiceConfig(c *cli.Context) (svcConfig *service.Config) {
    90  	svcConfig = &service.Config{
    91  		Name:        c.String("service"),
    92  		DisplayName: c.String("service"),
    93  		Description: defaultDescription,
    94  		Arguments:   []string{"run"},
    95  	}
    96  	svcConfig.Arguments = append(svcConfig.Arguments, getServiceArguments(c)...)
    97  
    98  	switch runtime.GOOS {
    99  	case "linux":
   100  		if os.Getuid() != 0 {
   101  			logrus.Fatal("Please run the commands as root")
   102  		}
   103  		if user := c.String("user"); user != "" {
   104  			svcConfig.Arguments = append(svcConfig.Arguments, "--user", user)
   105  		}
   106  
   107  	case "darwin":
   108  		svcConfig.Option = service.KeyValue{
   109  			"KeepAlive":   true,
   110  			"RunAtLoad":   true,
   111  			"UserService": os.Getuid() != 0,
   112  		}
   113  
   114  		if user := c.String("user"); user != "" {
   115  			if os.Getuid() == 0 {
   116  				svcConfig.Arguments = append(svcConfig.Arguments, "--user", user)
   117  			} else {
   118  				logrus.Fatalln("The --user is not supported for non-root users")
   119  			}
   120  		}
   121  
   122  	case "windows":
   123  		svcConfig.Option = service.KeyValue{
   124  			"Password": c.String("password"),
   125  		}
   126  		svcConfig.UserName = c.String("user")
   127  	}
   128  	return
   129  }
   130  
   131  func RunServiceControl(c *cli.Context) {
   132  	svcConfig := createServiceConfig(c)
   133  
   134  	s, err := service_helpers.New(&NullService{}, svcConfig)
   135  	if err != nil {
   136  		logrus.Fatal(err)
   137  	}
   138  
   139  	switch c.Command.Name {
   140  	case "install":
   141  		err = runServiceInstall(s, c)
   142  	case "status":
   143  		err = runServiceStatus(svcConfig.DisplayName, s)
   144  	default:
   145  		err = service.Control(s, c.Command.Name)
   146  	}
   147  
   148  	if err != nil {
   149  		logrus.Fatal(err)
   150  	}
   151  }
   152  
   153  func getFlags() []cli.Flag {
   154  	return []cli.Flag{
   155  		cli.StringFlag{
   156  			Name:  "service, n",
   157  			Value: defaultServiceName,
   158  			Usage: "Specify service name to use",
   159  		},
   160  	}
   161  }
   162  
   163  func getInstallFlags() []cli.Flag {
   164  	installFlags := getFlags()
   165  	installFlags = append(installFlags, cli.StringFlag{
   166  		Name:  "working-directory, d",
   167  		Value: helpers.GetCurrentWorkingDirectory(),
   168  		Usage: "Specify custom root directory where all data are stored",
   169  	})
   170  	installFlags = append(installFlags, cli.StringFlag{
   171  		Name:  "config, c",
   172  		Value: getDefaultConfigFile(),
   173  		Usage: "Specify custom config file",
   174  	})
   175  	installFlags = append(installFlags, cli.BoolFlag{
   176  		Name:  "syslog",
   177  		Usage: "Setup system logging integration",
   178  	})
   179  
   180  	if runtime.GOOS == "windows" {
   181  		installFlags = append(installFlags, cli.StringFlag{
   182  			Name:  "user, u",
   183  			Value: "",
   184  			Usage: "Specify user-name to secure the runner",
   185  		})
   186  		installFlags = append(installFlags, cli.StringFlag{
   187  			Name:  "password, p",
   188  			Value: "",
   189  			Usage: "Specify user password to install service (required)",
   190  		})
   191  	} else if os.Getuid() == 0 {
   192  		installFlags = append(installFlags, cli.StringFlag{
   193  			Name:  "user, u",
   194  			Value: "",
   195  			Usage: "Specify user-name to secure the runner",
   196  		})
   197  	}
   198  
   199  	return installFlags
   200  }
   201  
   202  func init() {
   203  	flags := getFlags()
   204  	installFlags := getInstallFlags()
   205  
   206  	common.RegisterCommand(cli.Command{
   207  		Name:   "install",
   208  		Usage:  "install service",
   209  		Action: RunServiceControl,
   210  		Flags:  installFlags,
   211  	})
   212  	common.RegisterCommand(cli.Command{
   213  		Name:   "uninstall",
   214  		Usage:  "uninstall service",
   215  		Action: RunServiceControl,
   216  		Flags:  flags,
   217  	})
   218  	common.RegisterCommand(cli.Command{
   219  		Name:   "start",
   220  		Usage:  "start service",
   221  		Action: RunServiceControl,
   222  		Flags:  flags,
   223  	})
   224  	common.RegisterCommand(cli.Command{
   225  		Name:   "stop",
   226  		Usage:  "stop service",
   227  		Action: RunServiceControl,
   228  		Flags:  flags,
   229  	})
   230  	common.RegisterCommand(cli.Command{
   231  		Name:   "restart",
   232  		Usage:  "restart service",
   233  		Action: RunServiceControl,
   234  		Flags:  flags,
   235  	})
   236  	common.RegisterCommand(cli.Command{
   237  		Name:   "status",
   238  		Usage:  "get status of a service",
   239  		Action: RunServiceControl,
   240  		Flags:  flags,
   241  	})
   242  }