github.com/vlifesystems/rulehunter@v0.0.0-20180501090014-673078aa4a83/cmd/cmd.go (about)

     1  // Copyright (C) 2016-2018 vLife Systems Ltd <http://vlifesystems.com>
     2  // Licensed under an MIT licence.  Please see LICENSE.md for details.
     3  
     4  package cmd
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	"time"
    11  
    12  	"github.com/kardianos/service"
    13  	"github.com/vlifesystems/rulehunter/config"
    14  	"github.com/vlifesystems/rulehunter/html"
    15  	"github.com/vlifesystems/rulehunter/logger"
    16  	"github.com/vlifesystems/rulehunter/program"
    17  	"github.com/vlifesystems/rulehunter/progress"
    18  	"github.com/vlifesystems/rulehunter/quitter"
    19  )
    20  
    21  type Setup struct {
    22  	prg *program.Program
    23  	svc service.Service
    24  	cfg *config.Config
    25  }
    26  
    27  func InitSetup(
    28  	l logger.Logger,
    29  	q *quitter.Quitter,
    30  	configFilename string,
    31  ) (*Setup, error) {
    32  	config, err := config.Load(configFilename)
    33  	if err != nil {
    34  		return nil, errConfigLoad{filename: configFilename, err: err}
    35  	}
    36  
    37  	if err := buildConfigDirs(config); err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	pm, err := progress.NewMonitor(
    42  		filepath.Join(config.BuildDir, "progress"),
    43  	)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	prg := program.New(config, pm, l, q)
    48  
    49  	s, err := newService(prg, flagUser, configFilename)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	svcLogger, err := s.Logger(nil)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	l.SetSvcLogger(svcLogger)
    59  	h := html.New(config, pm, l)
    60  	go l.Run(q)
    61  	go h.Run(q)
    62  
    63  	for i := 0; i < 10; i++ {
    64  		// This helps to ensure that quitter is properly established
    65  		// in goroutine before returning and being able to call Quit on quitter
    66  		if l.Running() && h.Running() {
    67  			break
    68  		}
    69  		time.Sleep(10 * time.Millisecond)
    70  	}
    71  	return &Setup{
    72  		prg: prg,
    73  		svc: s,
    74  		cfg: config,
    75  	}, nil
    76  }
    77  
    78  func newService(
    79  	prg *program.Program,
    80  	user string,
    81  	configFilename string,
    82  ) (service.Service, error) {
    83  	svcConfig := &service.Config{
    84  		Name:        "rulehunter",
    85  		DisplayName: "Rulehunter server",
    86  		Description: "Rulehunter finds rules in data based on user defined goals.",
    87  	}
    88  
    89  	if user != "" {
    90  		svcConfig.UserName = user
    91  	}
    92  
    93  	if len(os.Args) >= 2 && os.Args[1] == "service" {
    94  		svcConfig.Arguments = []string{
    95  			"serve",
    96  			fmt.Sprintf("--config=%s", configFilename),
    97  		}
    98  	} else {
    99  		svcConfig.Arguments = os.Args[1:]
   100  	}
   101  	return service.New(prg, svcConfig)
   102  }
   103  
   104  func buildConfigDirs(cfg *config.Config) error {
   105  	// File mode permission:
   106  	// No special permission bits
   107  	// User: Read, Write Execute
   108  	// Group: None
   109  	// Other: None
   110  	const modePerm = 0700
   111  
   112  	dirs := []string{
   113  		filepath.Join(cfg.WWWDir, "reports"),
   114  		filepath.Join(cfg.WWWDir, "progress"),
   115  		filepath.Join(cfg.BuildDir, "progress"),
   116  		filepath.Join(cfg.BuildDir, "reports"),
   117  	}
   118  	for _, dir := range dirs {
   119  		if err := os.MkdirAll(dir, modePerm); err != nil {
   120  			return err
   121  		}
   122  	}
   123  
   124  	return nil
   125  }