github.com/creichlin/pentaconta@v0.1.1-0.20170602155716-6b53e3be0bdb/main.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "flag" 6 "fmt" 7 "github.com/ghodss/yaml" 8 "gitlab.com/creichlin/pentaconta/declaration" 9 "gitlab.com/creichlin/pentaconta/evaluation" 10 "gitlab.com/creichlin/pentaconta/logger" 11 "gitlab.com/creichlin/pentaconta/services" 12 "io/ioutil" 13 "log" 14 "os" 15 "path/filepath" 16 "strings" 17 "time" 18 ) 19 20 func main() { 21 configName, help := readConfigParams() 22 if help { 23 printHelp() 24 return 25 } 26 location, err := probeLocation(configName) 27 28 if err != nil { 29 log.Fatal(err) 30 } 31 32 data, err := readData(location) 33 if err != nil { 34 log.Fatal(err) 35 } 36 37 runWithDeclaration(data, time.Hour*24*356*100) 38 } 39 40 func runWithDeclaration(data interface{}, duration time.Duration) { 41 dec, err := declaration.Parse(data) 42 if err != nil { 43 log.Fatal(err) 44 } 45 46 var logs logger.Logger 47 var eval *evaluation.Collector 48 if dec.Stats != nil { 49 eval = evaluation.EvaluationCollector() 50 logs = logger.NewSplitLogger( 51 logger.NewStdoutLogger(), 52 eval, 53 ) 54 } else { 55 logs = logger.NewStdoutLogger() 56 } 57 58 services := &services.Services{ 59 Logs: logs, 60 Executors: map[string]*services.Executor{}, 61 FSListeners: map[string]*services.FSListener{}, 62 } 63 64 createAndStartExecutors(services, dec) 65 createAndStartFsTriggers(services, dec) 66 67 startTime := time.Now() 68 69 for time.Now().Before(startTime.Add(duration)) { 70 time.Sleep(time.Second * 1) 71 72 if eval != nil { 73 stats := eval.Status(dec.Stats.Seconds) 74 bin, err := json.MarshalIndent(stats, "", " ") 75 if err != nil { 76 panic(err) 77 } 78 err = ioutil.WriteFile(dec.Stats.File, bin, 0644) 79 if err != nil { 80 panic(err) 81 } 82 } 83 } 84 } 85 86 func createAndStartFsTriggers(svs *services.Services, data *declaration.Root) { 87 for name, fsTrigger := range data.FSTriggers { 88 fsListener, err := services.NewFSListener(name, fsTrigger, svs) 89 if err != nil { 90 panic(err) 91 } 92 svs.FSListeners[name] = fsListener 93 go func() { 94 err := fsListener.Start() 95 log.Fatal(err) 96 }() 97 } 98 } 99 100 func createAndStartExecutors(svs *services.Services, data *declaration.Root) { 101 for name, service := range data.Services { 102 executor, err := services.NewExecutor(name, service, svs.Logs) 103 if err != nil { 104 panic(err) 105 } 106 107 svs.Executors[name] = executor 108 go executor.Start() 109 } 110 } 111 112 func readConfigParams() (string, bool) { 113 var configName string 114 var help bool 115 executable := filepath.Base(os.Args[0]) 116 flags := flag.NewFlagSet("pentacota", flag.ContinueOnError) 117 flags.StringVar(&configName, "config", executable, "name of config file to use, no .yaml or .json extension.") 118 flags.BoolVar(&help, "help", false, "Print help text and exit") 119 flags.Parse(os.Args[1:]) 120 return configName, help 121 } 122 123 func printHelp() { 124 fmt.Println("pentaconta help") 125 fmt.Println(declaration.Doc()) 126 } 127 128 func readData(file string) (interface{}, error) { 129 binData, err := ioutil.ReadFile(file) 130 if err != nil { 131 return nil, err 132 } 133 134 data := interface{}(nil) 135 136 if strings.HasSuffix(file, ".json") { 137 err = json.Unmarshal(binData, &data) 138 if err != nil { 139 return nil, err 140 } 141 return data, nil 142 } else if strings.HasSuffix(file, ".yaml") { 143 err = yaml.Unmarshal(binData, &data) 144 if err != nil { 145 return nil, err 146 } 147 return data, nil 148 } 149 panic("Returned path must have .json or .yaml extension") 150 } 151 152 func probeLocation(path string) (string, error) { 153 locations := []string{} 154 if filepath.IsAbs(path) { 155 locations = append(locations, path+".json") 156 locations = append(locations, path+".yaml") 157 } else { 158 wd, err := os.Getwd() 159 if err == nil { 160 abspath := filepath.Join(wd, path) 161 locations = append(locations, abspath+".json") 162 locations = append(locations, abspath+".yaml") 163 } 164 abspath := filepath.Join("/etc", path) 165 locations = append(locations, abspath+".json") 166 locations = append(locations, abspath+".yaml") 167 } 168 169 for _, location := range locations { 170 _, err := ioutil.ReadFile(location) 171 if err == nil { 172 return location, nil 173 } 174 } 175 176 return "", fmt.Errorf("Could not find config file in locations %v", locations) 177 }