func Validate(c *cli.Context, startTime time.Time) { gossConfig := getGossConfig(c) sys := system.New(c) outputer := getOutputer(c) sleep := c.Duration("sleep") retryTimeout := c.Duration("retry-timeout") i := 1 for { iStartTime := time.Now() out := validate(sys, gossConfig, c.Int("max-concurrent")) exitCode := outputer.Output(os.Stdout, out, iStartTime) if retryTimeout == 0 || exitCode == 0 { os.Exit(exitCode) } elapsed := time.Since(startTime) if elapsed+sleep > retryTimeout { color.Red("\nERROR: Timeout of %s reached before tests entered a passing state", retryTimeout) os.Exit(3) } color.Red("Retrying in %s (elapsed/timeout time: %.3fs/%s)\n\n\n", sleep, elapsed.Seconds(), retryTimeout) // Reset cache sys = system.New(c) time.Sleep(sleep) i++ fmt.Printf("Attempt #%d:\n", i) } }
// Simple wrapper to add multiple resources func AutoAddResources(fileName string, keys []string, c *cli.Context) error { setStoreFormatFromFileName(fileName) config := util.Config{ IgnoreList: c.GlobalStringSlice("exclude-attr"), Timeout: int(c.Duration("timeout") / time.Millisecond), } var gossConfig GossConfig if _, err := os.Stat(fileName); err == nil { gossConfig = ReadJSON(fileName) } else { gossConfig = *NewGossConfig() } sys := system.New(c) for _, key := range keys { if err := AutoAddResource(fileName, gossConfig, key, c, config, sys); err != nil { return err } } WriteJSON(fileName, gossConfig) return nil }
func (h healthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.Printf("%v: requesting health probe", r.RemoteAddr) var resp res tmp, found := h.cache.Get("res") if found { resp = tmp.(res) } else { h.gossMu.Lock() defer h.gossMu.Unlock() tmp, found := h.cache.Get("res") if found { resp = tmp.(res) } else { h.sys = system.New(h.c) log.Printf("%v: Stale cache, running tests", r.RemoteAddr) iStartTime := time.Now() out := validate(h.sys, h.gossConfig, h.maxConcurrent) var b bytes.Buffer exitCode := h.outputer.Output(&b, out, iStartTime) resp = res{exitCode: exitCode, b: b} h.cache.Set("res", resp, cache.DefaultExpiration) } } if h.contentType != "" { w.Header().Set("Content-Type", h.contentType) } if resp.exitCode == 0 { resp.b.WriteTo(w) } else { w.WriteHeader(http.StatusServiceUnavailable) resp.b.WriteTo(w) } }
func AppendResource(fileName, resourceName, key string, c *cli.Context) error { ignoreList := c.GlobalStringSlice("exclude-attr") var configJSON ConfigJSON if _, err := os.Stat(fileName); err == nil { configJSON = ReadJSON(fileName) } else { configJSON = *NewConfigJSON() } sys := system.New(c) // Need to figure out a good way to refactor this switch resourceName { case "Addr": res, _ := configJSON.Addrs.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Command": res, _ := configJSON.Commands.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "DNS": res, _ := configJSON.DNS.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "File": res, _ := configJSON.Files.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Group": res, _ := configJSON.Groups.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Package": res, _ := configJSON.Packages.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Port": res, _ := configJSON.Ports.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Process": res, _ := configJSON.Processes.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Service": res, _ := configJSON.Services.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "User": res, _ := configJSON.Users.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) case "Gossfile": res, _ := configJSON.Gossfiles.AppendSysResource(key, sys, ignoreList) resourcePrint(fileName, res) } WriteJSON(fileName, configJSON) return nil }
func Serve(c *cli.Context) { endpoint := c.String("endpoint") color.NoColor = true cache := cache.New(c.Duration("cache"), 30*time.Second) health := healthHandler{ c: c, gossConfig: getGossConfig(c), sys: system.New(c), outputer: getOutputer(c), cache: cache, gossMu: &sync.Mutex{}, maxConcurrent: c.Int("max-concurrent"), } if c.String("format") == "json" { health.contentType = "application/json" } http.Handle(endpoint, health) listenAddr := c.String("listen-addr") log.Printf("Starting to listen on: %s", listenAddr) log.Fatal(http.ListenAndServe(c.String("listen-addr"), nil)) }
func AutoAppendResource(fileName, key string, c *cli.Context) error { var configJSON ConfigJSON if _, err := os.Stat(fileName); err == nil { configJSON = ReadJSON(fileName) } else { configJSON = *NewConfigJSON() } sys := system.New(c) // file if strings.Contains(key, "/") { if res, _, ok := configJSON.Files.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } } // group if res, _, ok := configJSON.Groups.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } // package if res, _, ok := configJSON.Packages.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } // port if res, _, ok := configJSON.Ports.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } // process if res, sysres, ok := configJSON.Processes.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) ports := system.GetPorts(true) pids, _ := sysres.Pids() for _, pid := range pids { pidS := strconv.Itoa(pid) for port, entry := range ports { if entry.Pid == pidS { // port if res, _, ok := configJSON.Ports.AppendSysResourceIfExists(port, sys); ok == true { resourcePrint(fileName, res) } } } } } // Service if res, _, ok := configJSON.Services.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } // user if res, _, ok := configJSON.Users.AppendSysResourceIfExists(key, sys); ok == true { resourcePrint(fileName, res) } WriteJSON(fileName, configJSON) return nil }
func Run(specFile string, c *cli.Context) { sys := system.New(c) // handle stdin var fh *os.File var err error var path string if hasStdin() { fh = os.Stdin } else { path = filepath.Dir(specFile) fh, err = os.Open(specFile) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } } data, err := ioutil.ReadAll(fh) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } configJSON := mergeJSONData(ReadJSONData(data), 0, path) out := make(chan resource.TestResult) in := make(chan resource.Resource) go func() { for _, t := range configJSON.Resources() { in <- t } close(in) }() if os.Getenv("GOMAXPROCS") == "" { runtime.GOMAXPROCS(runtime.NumCPU()) } gomaxprocs := runtime.GOMAXPROCS(-1) workerCount := gomaxprocs * 5 if workerCount > 50 { workerCount = 50 } var wg sync.WaitGroup for i := 0; i < workerCount; i++ { wg.Add(1) go func() { defer wg.Done() for f := range in { for _, r := range f.Validate(sys) { out <- r } } }() } go func() { wg.Wait() close(out) }() testCount := 0 var failed []resource.TestResult for testResult := range out { //fmt.Printf("%v: %s.\n", testResult.Duration, testResult.Desc) if testResult.Result { fmt.Printf(".") testCount++ } else { fmt.Printf("F") failed = append(failed, testResult) testCount++ } } for _, testResult := range failed { fmt.Printf("\n%s\n", testResult.Desc) } fmt.Printf("\n\nCount: %d failed: %d\n", testCount, len(failed)) if len(failed) > 0 { os.Exit(1) } }
func Run(c *cli.Context, startTime time.Time) { sys := system.New(c) // handle stdin var fh *os.File var err error var path string if !c.GlobalIsSet("gossfile") && hasStdin() { fh = os.Stdin } else { specFile := c.GlobalString("gossfile") path = filepath.Dir(specFile) fh, err = os.Open(specFile) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } } data, err := ioutil.ReadAll(fh) if err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } configJSON := mergeJSONData(ReadJSONData(data), 0, path) out := make(chan []resource.TestResult) in := make(chan resource.Resource) go func() { for _, t := range configJSON.Resources() { in <- t } close(in) }() if os.Getenv("GOMAXPROCS") == "" { runtime.GOMAXPROCS(runtime.NumCPU()) } gomaxprocs := runtime.GOMAXPROCS(-1) workerCount := gomaxprocs * 5 if workerCount > 50 { workerCount = 50 } var wg sync.WaitGroup for i := 0; i < workerCount; i++ { wg.Add(1) go func() { defer wg.Done() for f := range in { out <- f.Validate(sys) } }() } go func() { wg.Wait() close(out) }() //var outputer outputs.Outputer if c.Bool("no-color") { color.NoColor = true } outputer := outputs.GetOutputer(c.String("format")) exitCode := outputer.Output(out, startTime) os.Exit(exitCode) }
func AppendResource(fileName, resourceName, key string, c *cli.Context) error { var configJSON ConfigJSON if _, err := os.Stat(fileName); err == nil { configJSON = ReadJSON(fileName) } else { configJSON = ConfigJSON{} } sys := system.New(c) // Need to figure out a good way to refactor this switch resourceName { case "Addr": sysResource := sys.NewAddr(key, sys) resource := resource.NewAddr(*sysResource) resourcePrint(fileName, resource) configJSON.Addrs = append(configJSON.Addrs, resource) case "Command": sysResource := sys.NewCommand(key, sys) resource := resource.NewCommand(*sysResource) resourcePrint(fileName, resource) configJSON.Commands = append(configJSON.Commands, resource) case "DNS": sysResource := sys.NewDNS(key, sys) resource := resource.NewDNS(*sysResource) resourcePrint(fileName, resource) configJSON.DNS = append(configJSON.DNS, resource) case "File": sysResource := sys.NewFile(key, sys) resource := resource.NewFile(*sysResource) resourcePrint(fileName, resource) configJSON.Files = append(configJSON.Files, resource) case "Group": sysResource := sys.NewGroup(key, sys) resource := resource.NewGroup(*sysResource) resourcePrint(fileName, resource) configJSON.Groups = append(configJSON.Groups, resource) case "Package": sysResource := sys.NewPackage(key, sys) resource := resource.NewPackage(sysResource) resourcePrint(fileName, resource) configJSON.Packages = append(configJSON.Packages, resource) case "Port": sysResource := sys.NewPort(key, sys) resource := resource.NewPort(*sysResource) resourcePrint(fileName, resource) configJSON.Ports = append(configJSON.Ports, resource) case "Process": sysResource := sys.NewProcess(key, sys) resource := resource.NewProcess(*sysResource) resourcePrint(fileName, resource) configJSON.Processes = append(configJSON.Processes, resource) case "Service": sysResource := sys.NewService(key, sys) resource := resource.NewService(sysResource) resourcePrint(fileName, resource) configJSON.Services = append(configJSON.Services, resource) case "User": sysResource := sys.NewUser(key, sys) resource := resource.NewUser(*sysResource) resourcePrint(fileName, resource) configJSON.Users = append(configJSON.Users, resource) case "Gossfile": sysResource := sys.NewGossfile(key, sys) resource := resource.NewGossfile(*sysResource) resourcePrint(fileName, resource) configJSON.Gossfiles = append(configJSON.Gossfiles, resource) } WriteJSON(fileName, configJSON) return nil }
func AppendResource(fileName, resourceName, key string, c *cli.Context) error { config := util.Config{ IgnoreList: c.GlobalStringSlice("exclude-attr"), Timeout: int(c.Duration("timeout") / time.Millisecond), } var configJSON ConfigJSON if _, err := os.Stat(fileName); err == nil { configJSON = ReadJSON(fileName) } else { configJSON = *NewConfigJSON() } sys := system.New(c) // Need to figure out a good way to refactor this switch resourceName { case "Addr": res, err := configJSON.Addrs.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Command": res, err := configJSON.Commands.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "DNS": res, err := configJSON.DNS.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "File": res, err := configJSON.Files.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Group": res, err := configJSON.Groups.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Package": res, err := configJSON.Packages.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Port": res, err := configJSON.Ports.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Process": res, err := configJSON.Processes.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Service": res, err := configJSON.Services.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "User": res, err := configJSON.Users.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) case "Gossfile": res, err := configJSON.Gossfiles.AppendSysResource(key, sys, config) if err != nil { fmt.Println(err) os.Exit(1) } resourcePrint(fileName, res) } WriteJSON(fileName, configJSON) return nil }