func main() { opts.New(&c).Repo("github.com/jpillora/installer").Version(VERSION).Parse() log.Printf("Default user is '%s' and listening on %d...", c.User, c.Port) if err := http.ListenAndServe(":"+strconv.Itoa(c.Port), http.HandlerFunc(install)); err != nil { log.Fatal(err) } }
func main() { c := config{ Host: "0.0.0.0", Port: 3000, } opts.New(&c). Repo("github.com/jpillora/scraper"). Version(VERSION). Parse() h := &scraper.Handler{Log: true} go func() { for { sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGHUP) <-sig if err := h.LoadConfigFile(c.ConfigFile); err != nil { log.Printf("failed to load configuration: %s", err) } else { log.Printf("successfully loaded new configuration") } } }() if err := h.LoadConfigFile(c.ConfigFile); err != nil { log.Fatal(err) } log.Printf("listening on %d...", c.Port) log.Fatal(http.ListenAndServe(c.Host+":"+strconv.Itoa(c.Port), h)) }
func main() { c := Config{} //In this case UseEnv() is equivalent to //adding `env:"FOO"` and `env:"BAR"` tags opts.New(&c).UseEnv().Parse() fmt.Println(c.Foo) fmt.Println(c.Bar) }
func main() { c := Config{} opts.New(&c).Parse() fmt.Println(c.Foo) fmt.Println(c.Bar) }
func main() { c := Config{} opts.New(&c).Parse() for i, foo := range c.Bazzes { fmt.Println(i, foo) } }
func main() { c := Config{} opts.New(&c). ConfigPath("config.json"). Parse() fmt.Println(c.Foo) fmt.Println(c.Bar) }
func main() { c := HelpConfig{ Foo: "42", } opts.New(&c). Name("help"). Version("1.0.0"). Repo("https://github.com/jpillora/foo"). Parse() }
func main() { c := Config2{} //UseEnv() essentially adds an `env` tag on all fields, //infering the env var name from the field name. //Specifically adding the `env` tag will only enable it //for a single field. opts.New(&c).Parse() fmt.Println(c.Foo) fmt.Println(c.Bar) }
func main() { c := &daemon.Config{ Interval: 30 * time.Second, } opts.New(c). Version("0.2.0"). PkgRepo(). Parse() log.SetOutput(os.Stderr) daemon.Run(*c) }
func main() { s := ct.Server{ Port: 3000, } opts.New(&s). Version(VERSION). PkgRepo(). Parse() if err := s.Run(); err != nil { log.Fatal(err) } }
func main() { c := Config{} //see default templates and the default template order //in the opts/help.go file o := opts.New(&c). DocAfter("usage", "mytext", "\nthis is a some text!\n"). //add new entry Repo("myfoo.com/bar"). DocSet("repo", "\nMy awesome repo:\n {{.Repo}}"). //change existing entry Parse() fmt.Println(o.Help()) }
func main() { c := config{Port: 3000, Config: podsling.Config{Log: true}} opts.New(&c). Version(VERSION). Repo("github.com/jpillora/podsling"). Parse() h, err := podsling.NewHandler(c.Config) if err != nil { log.Fatal(err) } log.Printf("Listening on %d...", c.Port) log.Fatal(http.ListenAndServe(":"+strconv.Itoa(c.Port), h)) }
func main() { a := App{ Handler: &webfontdownloader.Handler{}, Port: 3000, } opts. New(&a). Version(VERSION). Repo("github.com/jpillora/webfont-downloader"). Parse() log.Printf("Listening on %d...", a.Port) log.Fatal(http.ListenAndServe(":"+strconv.Itoa(a.Port), a.Handler)) }
func main() { s := server.Server{ Port: 3000, ConfigPath: "cloud-torrent.json", } opts.New(&s). Version(VERSION). PkgRepo(). Parse() if err := s.Run(VERSION); err != nil { log.Fatal(err) } }
func main() { c := struct { Port int `help:"Port" env:"PORT"` echo.Config `type:"embedded"` }{ Port: 3000, } opts.New(&c). Name("go-echo-server"). Version(VERSION). Repo("github.com/jpillora/go-echo-server"). Parse() h := echo.New(c.Config) log.Printf("Listening on %d...", c.Port) log.Fatal(http.ListenAndServe(":"+strconv.Itoa(c.Port), h)) }
func main() { s := server.Server{ Title: "Cloud Torrent", Port: 9000, ConfigPath: "cloud-torrent.json", } o := opts.New(&s) o.Version(VERSION) o.PkgRepo() o.LineWidth = 96 o.Parse() if err := s.Run(VERSION); err != nil { log.Fatal(err) } }
func main() { s := server.Server{ Title: "TorrentSaga", Port: 3000, ConfigPath: "settings.json", } o := opts.New(&s) o.Version(VERSION) o.PkgRepo() o.LineWidth = 96 o.Parse() if err := s.Run(VERSION); err != nil { log.Fatal(err) } }
func main() { //defaults c := Config{ Host: "0.0.0.0", Port: 3000, Config: serve.Config{ Directory: ".", }, } //parse opts.New(&c). Name("serve"). Version(VERSION). Repo("github.com/jpillora/serve"). Parse() //ready! h, err := serve.NewHandler(c.Config) if err != nil { log.Fatal(err) } port := strconv.Itoa(c.Port) if c.Open { go func() { time.Sleep(500 * time.Millisecond) cmd := exec.Command("open", "http://localhost:"+port) cmd.Run() }() } fmt.Printf("%sserving %s%s %son port %s%d%s\n", requestlog.DefaultOptions.Colors.Grey, requestlog.DefaultOptions.Colors.Cyan, c.Config.Directory, requestlog.DefaultOptions.Colors.Grey, requestlog.DefaultOptions.Colors.Cyan, c.Port, requestlog.DefaultOptions.Colors.Reset, ) log.Fatal(http.ListenAndServe(":"+port, h)) }
func main() { //cli config config := struct { Port int `help:"listening port"` uploader.Config `type:"embedded"` }{ Port: 3000, Config: uploader.Config{Dir: "."}, } opts.New(&config). Name("uploader"). Repo("github.com/jpillora/uploader"). Version(VERSION). Parse() log.Printf("listening on %d...", config.Port) http.ListenAndServe(fmt.Sprintf(":%d", config.Port), uploader.New(config.Config)) }
func main() { //configuration with defaults c := lib.Config{ Ping: "!", Pong: "?", } //parse config, note the library version, and extract the //repository link from the config package import path opts.New(&c). Name("foo"). //explicitly name (otherwise it will use the project name from the pkg import path) Version(VERSION). PkgRepo(). Parse() //construct a foo foo, err := lib.NewFoo(c) if err != nil { log.Fatal(err) } //ready! run foo! foo.Run() }
func main() { c := mediasort.Config{ Extensions: "mp4,avi,mkv", Concurrency: 6, FileLimit: 1000, MinFileSize: sizestr.Bytes(sizestr.MustParse("25MB")), WatchDelay: 3 * time.Second, } opts.New(&c). Name("media-sort"). Repo("github.com/jpillora/media-sort"). DocAfter("usage", "info", info). DocAfter("options", "pathtemplates", pathTemplates). Version(VERSION). Parse() if err := mediasort.FileSystemSort(c); err != nil { log.Fatal(err) } }
func main() { //configuration with defaults c := foo.Config{ Ping: "hello", Pong: "world", } //parse config, note the library version, and extract the //repository link from the config package import path opts.New(&c). Name("foo"). Version(VERSION). PkgRepo(). //includes the infered URL to the package in the help text Parse() //construct a foo f, err := foo.New(c) if err != nil { log.Fatal(err) } //ready! run foo! f.Run() }
func main() { //configuration defaults conf := config{ Server: "http://localhost:8086", Database: "test", Username: "", Password: "", Measurement: "data", BatchSize: 5000, ForceFloat: false, ForceString: false, TreatNull: false, TimestampColumn: "timestamp", TimestampFormat: "2006-01-02 15:04:05", HttpTimeout: 10, } //parse config opts.New(&conf). Name("csv-to-influxdb"). Repo("github.com/jpillora/csv-to-influxdb"). Version(VERSION). Parse() //set tag names tagNames := map[string]bool{} for _, name := range strings.Split(conf.TagColumns, ",") { name = strings.TrimSpace(name) if name != "" { tagNames[name] = true } } //regular expressions numbersRe := regexp.MustCompile(`\d`) integerRe := regexp.MustCompile(`^\d+$`) floatRe := regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$`) trueRe := regexp.MustCompile(`^(true|T|True|TRUE)$`) falseRe := regexp.MustCompile(`^(false|F|False|FALSE)$`) nullRe := regexp.MustCompile(`^(null|Null|NULL)$`) timestampRe, err := regexp.Compile("^" + numbersRe.ReplaceAllString(conf.TimestampFormat, `\d`) + "$") if err != nil { log.Fatalf("time stamp regexp creation failed") } //influxdb client //u, err := url.Parse(conf.Server) //if err != nil { // log.Fatalf("Invalid server address: %s", err) //} c, err := client.NewHTTPClient(client.HTTPConfig{Addr: conf.Server, Username: conf.Username, Password: conf.Password, Timeout: time.Duration(conf.HttpTimeout) * time.Second}) defer c.Close() dbsResp, err := c.Query(client.Query{Command: "SHOW DATABASES"}) if err != nil { log.Fatalf("Invalid server address: %s", err) } dbExists := false if len(dbsResp.Results) == 0 { log.Fatalf("No databases found, probably an authentication issue, please provide username and password.") } for _, v := range dbsResp.Results[0].Series[0].Values { dbName := v[0].(string) if conf.Database == dbName { dbExists = true break } } if !dbExists { if conf.NoAutoCreate { log.Fatalf("Database '%s' does not exist", conf.Database) } _, err := c.Query(client.Query{Command: "CREATE DATABASE \"" + conf.Database + "\""}) if err != nil { log.Fatalf("Failed to create database: %s", err) } } //open csv file f, err := os.Open(conf.CSVFile) if err != nil { log.Fatalf("Failed to open %s", conf.CSVFile) } //headers and init fn var firstField string var headers []string setHeaders := func(hdrs []string) { //check timestamp and tag columns hasTs := false n := len(tagNames) for _, h := range hdrs { if h == conf.TimestampColumn { hasTs = true } else if tagNames[h] { log.Println(h) n-- } else if firstField == "" { firstField = h } } if firstField == "" { log.Fatalf("You must have at least one field (non-tag)") } if !hasTs { log.Fatalf("Timestamp column (%s) does not match any header (%s)", conf.TimestampColumn, strings.Join(headers, ",")) } if n > 0 { log.Fatalf("Tag names (%s) to do not all have matching headers (%s)", conf.TagColumns, strings.Join(headers, ",")) } headers = hdrs } var bpConfig = client.BatchPointsConfig{Database: conf.Database} bp, _ := client.NewBatchPoints(bpConfig) //current batch bpSize := 0 totalSize := 0 // lastCount := "" //write the current batch write := func() { if bpSize == 0 { return } b := backoff.Backoff{} for { if err := c.Write(bp); err != nil { d := b.Duration() log.Printf("Write failed: %s (retrying in %s)", err, d) if int(b.Attempt()) == conf.Attempts { log.Fatalf("Failed to write to db after %d attempts", int(b.Attempt())) } time.Sleep(d) continue } break } //TODO(jpillora): wait until the new points become readable // count := "" // for count == lastCount { // resp, err := c.Query(client.Query{Command: "SELECT count(" + firstField + ") FROM " + conf.Measurement, Database: conf.Database}) // if err != nil { // log.Fatal("failed to count rows") // } // count = resp.Results[0].Series[0].Values[0][1].(string) // } //reset bp, _ = client.NewBatchPoints(bpConfig) bpSize = 0 } //read csv, line by line r := csv.NewReader(f) for i := 0; ; i++ { records, err := r.Read() if err != nil { if err == io.EOF { break } log.Fatalf("CSV error: %s", err) } if i == 0 { setHeaders(records) continue } // Create a point and add to batch tags := map[string]string{} fields := map[string]interface{}{} var ts time.Time //move all into tags and fields for hi, h := range headers { r := records[hi] if len(r) == 0 { continue } //tags are just strings if tagNames[h] { tags[h] = r continue } //fields require string parsing if timestampRe.MatchString(r) { t, err := time.Parse(conf.TimestampFormat, r) if err != nil { fmt.Printf("#%d: %s: Invalid time: %s\n", i, h, err) continue } if conf.TimestampColumn == h { ts = t //the timestamp column! continue } fields[h] = t } else if !conf.ForceFloat && !conf.ForceString && integerRe.MatchString(r) { i, _ := strconv.Atoi(r) fields[h] = i } else if !conf.ForceString && floatRe.MatchString(r) { f, _ := strconv.ParseFloat(r, 64) fields[h] = f } else if trueRe.MatchString(r) { fields[h] = true } else if falseRe.MatchString(r) { fields[h] = false } else if conf.TreatNull && nullRe.MatchString(r) { // null values must not be inserted into InfluxDB continue } else { fields[h] = r } } p, err := client.NewPoint(conf.Measurement, tags, fields, ts) bp.AddPoint(p) bpSize++ totalSize++ if bpSize == conf.BatchSize { write() } } //send remainder write() log.Printf("Done (wrote %d points)", totalSize) }
func main() { c := config{ URL: "http://localhost:8086", Database: "test", Interval: 5 * time.Minute, } opts.New(&c).Name("sysflux").Version(VERSION).Parse() //validate config u, err := url.Parse(c.URL) if err != nil { log.Fatal("Invalid URL") } host, port, err := net.SplitHostPort(u.Host) if err != nil { log.Fatal("Invalid host and port") } if u.Path == "" { u.Path = "/write" } v := url.Values{} v.Set("db", c.Database) u.RawQuery = v.Encode() tags := "" if c.Tags != "" { tags = "," + c.Tags } //good to go log.Printf("Using InfluxDB endpoint: %s", u) success := false lock := sync.Mutex{} entries := []string{} send := func() error { body := strings.NewReader(strings.Join(entries, "\n")) if c.DNS != "" { //lookup host every POST ips, err := lookup(host, c.DNS) if err != nil { return fmt.Errorf("Lookup failed: %s", err) } u.Host = ips[0] + ":" + port } resp, err := http.Post(u.String(), "application/x-www-form-urlencoded", body) if err != nil { return fmt.Errorf("HTTP POST failed: %s", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusNoContent { msg, err := ioutil.ReadAll(resp.Body) if err != nil { return fmt.Errorf("Response download failed: %s", err) } return fmt.Errorf("Response: %d => %s", resp.StatusCode, msg) } //show first success if !success { log.Printf("Success") success = true } //clear once recieved! entries = nil return nil } report := func() { t := time.Now().UnixNano() if l, err := load.LoadAvg(); err == nil { entries = append(entries, fmt.Sprintf("cpu_load_short%s value=%f %d", tags, l.Load1*100, t)) entries = append(entries, fmt.Sprintf("cpu_load_medium%s value=%f %d", tags, l.Load5*100, t)) entries = append(entries, fmt.Sprintf("cpu_load_long%s value=%f %d", tags, l.Load15*100, t)) } if v, err := mem.VirtualMemory(); err == nil { entries = append(entries, fmt.Sprintf("mem_usage%s value=%f %d", tags, v.UsedPercent, t)) } if len(entries) > MAX_QUEUED { entries = entries[len(entries)-MAX_QUEUED:] } } //send loop go func() { b := backoff.Backoff{} for { wait := time.Second lock.Lock() if len(entries) > 0 { if err := send(); err == nil { b.Reset() } else { log.Println(err) wait = b.Duration() } } lock.Unlock() time.Sleep(wait) } }() //report loop for { lock.Lock() report() lock.Unlock() time.Sleep(c.Interval) } }