github.com/go-graphite/carbonapi@v0.17.0/cmd/mockbackend/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "flag" 6 "log" 7 "net/http" 8 "os" 9 "sync" 10 "time" 11 12 "go.uber.org/zap" 13 "gopkg.in/yaml.v2" 14 ) 15 16 type MainConfig struct { 17 Version string `yaml:"version"` 18 Test *TestSchema `yaml:"test"` 19 Listeners []Listener `yaml:"listeners"` 20 } 21 22 type Listener struct { 23 Address string `yaml:"address"` 24 Code int `yaml:"httpCode"` // global responce code 25 ShuffleResults bool `yaml:"shuffleResults"` 26 EmptyBody bool `yaml:"emptyBody"` 27 Expressions map[string]Response `yaml:"expressions"` 28 } 29 30 var cfg = MainConfig{} 31 32 type listener struct { 33 Listener 34 logger *zap.Logger 35 } 36 37 func main() { 38 config := flag.String("config", "average.yaml", "yaml where it would be possible to get data") 39 verbose := flag.Bool("verbose", false, "verbose reporting") 40 testonly := flag.Bool("testonly", false, "run only unit test") 41 noapp := flag.Bool("noapp", false, "do not run application") 42 test := flag.Bool("test", false, "run unit test if present") 43 breakOnError := flag.Bool("break", false, "break and wait user response if request failed") 44 flag.Parse() 45 logger, err := zap.NewProduction() 46 if err != nil { 47 log.Fatal(err) 48 } 49 50 if *config == "" { 51 logger.Fatal("failed to get config, it should be non-null") 52 } 53 54 f, err := os.Open(*config) 55 if err != nil { 56 logger.Fatal("failed to read config", zap.Error(err)) 57 } 58 59 decoder := yaml.NewDecoder(f) 60 decoder.SetStrict(true) 61 err = decoder.Decode(&cfg) 62 if err != nil { 63 logger.Fatal("failed to read config", zap.Error(err)) 64 return 65 } 66 67 logger.Info("starting mockbackend", 68 zap.Any("config", cfg), 69 ) 70 71 httpServers := make([]*http.Server, 0) 72 wg := sync.WaitGroup{} 73 wgStart := sync.WaitGroup{} 74 if !*testonly { 75 for _, c := range cfg.Listeners { 76 logger := logger.With(zap.String("listener", c.Address)) 77 listener := listener{ 78 Listener: c, 79 logger: logger, 80 } 81 82 if listener.Address == "" { 83 listener.Address = ":9070" 84 } 85 86 if listener.Code == 0 { 87 listener.Code = http.StatusOK 88 } 89 90 logger.Info("started", 91 zap.String("listener", listener.Address), 92 zap.Any("config", c), 93 ) 94 95 mux := http.NewServeMux() 96 mux.HandleFunc("/render", listener.renderHandler) 97 mux.HandleFunc("/render/", listener.renderHandler) 98 mux.HandleFunc("/metrics/find", listener.findHandler) 99 mux.HandleFunc("/metrics/find/", listener.findHandler) 100 mux.HandleFunc("/tags/autoComplete/values", listener.tagsValuesHandler) 101 mux.HandleFunc("/tags/autoComplete/tags", listener.tagsNamesHandler) 102 103 wg.Add(1) 104 wgStart.Add(1) 105 server := &http.Server{ 106 Addr: listener.Address, 107 Handler: mux, 108 } 109 go func(h *http.Server) { 110 wgStart.Done() 111 err = h.ListenAndServe() 112 if err != nil && err != http.ErrServerClosed { 113 logger.Error("failed to start server", 114 zap.Error(err), 115 ) 116 } 117 wg.Done() 118 }(server) 119 120 wgStart.Wait() 121 httpServers = append(httpServers, server) 122 } 123 logger.Info("all listeners started") 124 } 125 126 failed := false 127 if cfg.Test != nil && (*test || *testonly) { 128 failed = e2eTest(logger, *noapp, *breakOnError, *verbose) 129 } 130 131 if !*testonly { 132 if *test { 133 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 134 for i := range httpServers { 135 // we don't care about error here 136 _ = httpServers[i].Shutdown(ctx) 137 } 138 cancel() 139 } 140 141 wg.Wait() 142 } 143 144 if failed { 145 // skipcq: CRT-D0011 146 os.Exit(1) 147 } 148 }