github.com/slackhq/nebula@v1.9.0/cmd/nebula-service/service.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/kardianos/service"
    10  	"github.com/sirupsen/logrus"
    11  	"github.com/slackhq/nebula"
    12  	"github.com/slackhq/nebula/config"
    13  )
    14  
    15  var logger service.Logger
    16  
    17  type program struct {
    18  	configPath *string
    19  	configTest *bool
    20  	build      string
    21  	control    *nebula.Control
    22  }
    23  
    24  func (p *program) Start(s service.Service) error {
    25  	// Start should not block.
    26  	logger.Info("Nebula service starting.")
    27  
    28  	l := logrus.New()
    29  	HookLogger(l)
    30  
    31  	c := config.NewC(l)
    32  	err := c.Load(*p.configPath)
    33  	if err != nil {
    34  		return fmt.Errorf("failed to load config: %s", err)
    35  	}
    36  
    37  	p.control, err = nebula.Main(c, *p.configTest, Build, l, nil)
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	p.control.Start()
    43  	return nil
    44  }
    45  
    46  func (p *program) Stop(s service.Service) error {
    47  	logger.Info("Nebula service stopping.")
    48  	p.control.Stop()
    49  	return nil
    50  }
    51  
    52  func fileExists(filename string) bool {
    53  	_, err := os.Stat(filename)
    54  	if os.IsNotExist(err) {
    55  		return false
    56  	}
    57  	return true
    58  }
    59  
    60  func doService(configPath *string, configTest *bool, build string, serviceFlag *string) {
    61  	if *configPath == "" {
    62  		ex, err := os.Executable()
    63  		if err != nil {
    64  			panic(err)
    65  		}
    66  		*configPath = filepath.Dir(ex) + "/config.yaml"
    67  		if !fileExists(*configPath) {
    68  			*configPath = filepath.Dir(ex) + "/config.yml"
    69  		}
    70  	}
    71  
    72  	svcConfig := &service.Config{
    73  		Name:        "Nebula",
    74  		DisplayName: "Nebula Network Service",
    75  		Description: "Nebula network connectivity daemon for encrypted communications",
    76  		Arguments:   []string{"-service", "run", "-config", *configPath},
    77  	}
    78  
    79  	prg := &program{
    80  		configPath: configPath,
    81  		configTest: configTest,
    82  		build:      build,
    83  	}
    84  
    85  	// Here are what the different loggers are doing:
    86  	// - `log` is the standard go log utility, meant to be used while the process is still attached to stdout/stderr
    87  	// - `logger` is the service log utility that may be attached to a special place depending on OS (Windows will have it attached to the event log)
    88  	// - above, in `Run` we create a `logrus.Logger` which is what nebula expects to use
    89  	s, err := service.New(prg, svcConfig)
    90  	if err != nil {
    91  		log.Fatal(err)
    92  	}
    93  
    94  	errs := make(chan error, 5)
    95  	logger, err = s.Logger(errs)
    96  	if err != nil {
    97  		log.Fatal(err)
    98  	}
    99  
   100  	go func() {
   101  		for {
   102  			err := <-errs
   103  			if err != nil {
   104  				// Route any errors from the system logger to stdout as a best effort to notice issues there
   105  				log.Print(err)
   106  			}
   107  		}
   108  	}()
   109  
   110  	switch *serviceFlag {
   111  	case "run":
   112  		err = s.Run()
   113  		if err != nil {
   114  			// Route any errors to the system logger
   115  			logger.Error(err)
   116  		}
   117  	default:
   118  		err := service.Control(s, *serviceFlag)
   119  		if err != nil {
   120  			log.Printf("Valid actions: %q\n", service.ControlAction)
   121  			log.Fatal(err)
   122  		}
   123  		return
   124  	}
   125  
   126  }