<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/42wim/matterircd/config"
	"github.com/42wim/mm-go-irckit"
	"github.com/sirupsen/logrus"
	"net"
	"os"
	"strings"
)

var (
	flagRestrict, flagDefaultTeam, flagDefaultServer, flagTLSBind, flagTLSDir *string
	flagInsecure, flagSkipTLSVerify                                           *bool
	version                                                                   = "0.17.3"
	githash                                                                   string
	logger                                                                    *logrus.Entry
	cfg                                                                       config.Config
)

func main() {
	ourlog := logrus.New()
	ourlog.Formatter = &logrus.TextFormatter{FullTimestamp: true}
	logger = ourlog.WithFields(logrus.Fields{"module": "matterircd"})
	config.Logger = logger

	// config related. instantiate a new config.Config to store flags
	cfg = config.Config{}
	flagConfig := flag.String("conf", "", "config file")

	// bools for showing version/enabling debug
	flagVersion := flag.Bool("version", false, "show version")
	flag.BoolVar(&cfg.Debug, "debug", false, "enable debug logging")

	// bind related cfg
	flag.StringVar(&cfg.Bind, "bind", "127.0.0.1:6667", "interface:port to bind to.")

	// mattermost related cfg
	flag.StringVar(&cfg.Restrict, "restrict", "", "only allow connection to specified mattermost server/instances. Space delimited")
	flag.StringVar(&cfg.DefaultTeam, "mmteam", "", "specify default mattermost team")
	flag.StringVar(&cfg.DefaultServer, "mmserver", "", "specify default mattermost server/instance")
	flag.BoolVar(&cfg.Insecure, "mminsecure", false, "use http connection to mattermost")

	// TLS related cfg
	flag.BoolVar(&cfg.SkipTLSVerify, "mmskiptlsverify", false, "skip verification of mattermost certificate chain and hostname")
	flag.StringVar(&cfg.TLSBind, "tlsbind", "", "interface:port to bind to. (e.g 127.0.0.1:6697)")
	flag.StringVar(&cfg.TLSDir, "tlsdir", ".", "directory to look for key.pem and cert.pem.")
	flag.Parse()

	// if -config was set, load the config file (overrides args)
	if *flagConfig != "" {
		cfg = *config.LoadConfig(*flagConfig, cfg)
	}

	if cfg.Debug {
		logger.Info("enabling debug")
		ourlog.Level = logrus.DebugLevel
		irckit.SetLogLevel("debug")
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}

	irckit.SetLogger(logger)

	logger.Infof("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		logger.Infof("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}

	if cfg.TLSBind != "" {
		go func() {
			logger.Infof("Listening on %s (TLS)", cfg.TLSBind)
			socket := tlsbind()
			defer socket.Close()
			start(socket)
		}()
	}

	// backwards compatible
	if cfg.Bind == "127.0.0.1:6667" && cfg.BindInterface != "" && cfg.BindPort != 0 {
		cfg.Bind = fmt.Sprintf("%s:%d", cfg.BindInterface, cfg.BindPort)
	}

	if cfg.Bind != "" {
		go func() {
			socket, err := net.Listen("tcp", cfg.Bind)
			if err != nil {
				logger.Errorf("Can not listen on %s: %v", cfg.Bind, err)
			}
			logger.Infof("Listening on %s", cfg.Bind)
			defer socket.Close()
			start(socket)
		}()
	}
	select {}
}

func tlsbind() net.Listener {
	cert, err := tls.LoadX509KeyPair(cfg.TLSDir+"/cert.pem", cfg.TLSDir+"/key.pem")
	if err != nil {
		logger.Errorf("could not load TLS, incorrect directory? Error: %s", err)
		os.Exit(1)
	}
	config := tls.Config{Certificates: []tls.Certificate{cert}}
	listenerTLS, err := tls.Listen("tcp", cfg.TLSBind, &config)
	if err != nil {
		logger.Errorf("Can not listen on %s: %v\n", cfg.TLSBind, err)
		os.Exit(1)
	}
	logger.Info("TLS listening on ", cfg.TLSBind)
	return listenerTLS
}

func start(socket net.Listener) {
	for {
		conn, err := socket.Accept()
		if err != nil {
			logger.Errorf("Failed to accept connection: %v", err)
			return
		}

		go func() {
			irccfg := &irckit.MmCfg{Insecure: cfg.Insecure, SkipTLSVerify: cfg.SkipTLSVerify,
				SlackSettings: cfg.Slack, MattermostSettings: cfg.Mattermost}
			newsrv := irckit.ServerConfig{Name: "matterircd", Version: version}.Server()
			logger.Infof("New connection: %s", conn.RemoteAddr())
			err = newsrv.Connect(irckit.NewUserMM(conn, newsrv, irccfg))
			if err != nil {
				logger.Errorf("Failed to join: %v", err)
				return
			}
		}()
	}
}
<commit_msg>Bump version<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/42wim/matterircd/config"
	"github.com/42wim/mm-go-irckit"
	"github.com/sirupsen/logrus"
	"net"
	"os"
	"strings"
)

var (
	flagRestrict, flagDefaultTeam, flagDefaultServer, flagTLSBind, flagTLSDir *string
	flagInsecure, flagSkipTLSVerify                                           *bool
	version                                                                   = "0.17.4-dev"
	githash                                                                   string
	logger                                                                    *logrus.Entry
	cfg                                                                       config.Config
)

func main() {
	ourlog := logrus.New()
	ourlog.Formatter = &logrus.TextFormatter{FullTimestamp: true}
	logger = ourlog.WithFields(logrus.Fields{"module": "matterircd"})
	config.Logger = logger

	// config related. instantiate a new config.Config to store flags
	cfg = config.Config{}
	flagConfig := flag.String("conf", "", "config file")

	// bools for showing version/enabling debug
	flagVersion := flag.Bool("version", false, "show version")
	flag.BoolVar(&cfg.Debug, "debug", false, "enable debug logging")

	// bind related cfg
	flag.StringVar(&cfg.Bind, "bind", "127.0.0.1:6667", "interface:port to bind to.")

	// mattermost related cfg
	flag.StringVar(&cfg.Restrict, "restrict", "", "only allow connection to specified mattermost server/instances. Space delimited")
	flag.StringVar(&cfg.DefaultTeam, "mmteam", "", "specify default mattermost team")
	flag.StringVar(&cfg.DefaultServer, "mmserver", "", "specify default mattermost server/instance")
	flag.BoolVar(&cfg.Insecure, "mminsecure", false, "use http connection to mattermost")

	// TLS related cfg
	flag.BoolVar(&cfg.SkipTLSVerify, "mmskiptlsverify", false, "skip verification of mattermost certificate chain and hostname")
	flag.StringVar(&cfg.TLSBind, "tlsbind", "", "interface:port to bind to. (e.g 127.0.0.1:6697)")
	flag.StringVar(&cfg.TLSDir, "tlsdir", ".", "directory to look for key.pem and cert.pem.")
	flag.Parse()

	// if -config was set, load the config file (overrides args)
	if *flagConfig != "" {
		cfg = *config.LoadConfig(*flagConfig, cfg)
	}

	if cfg.Debug {
		logger.Info("enabling debug")
		ourlog.Level = logrus.DebugLevel
		irckit.SetLogLevel("debug")
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}

	irckit.SetLogger(logger)

	logger.Infof("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		logger.Infof("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}

	if cfg.TLSBind != "" {
		go func() {
			logger.Infof("Listening on %s (TLS)", cfg.TLSBind)
			socket := tlsbind()
			defer socket.Close()
			start(socket)
		}()
	}

	// backwards compatible
	if cfg.Bind == "127.0.0.1:6667" && cfg.BindInterface != "" && cfg.BindPort != 0 {
		cfg.Bind = fmt.Sprintf("%s:%d", cfg.BindInterface, cfg.BindPort)
	}

	if cfg.Bind != "" {
		go func() {
			socket, err := net.Listen("tcp", cfg.Bind)
			if err != nil {
				logger.Errorf("Can not listen on %s: %v", cfg.Bind, err)
			}
			logger.Infof("Listening on %s", cfg.Bind)
			defer socket.Close()
			start(socket)
		}()
	}
	select {}
}

func tlsbind() net.Listener {
	cert, err := tls.LoadX509KeyPair(cfg.TLSDir+"/cert.pem", cfg.TLSDir+"/key.pem")
	if err != nil {
		logger.Errorf("could not load TLS, incorrect directory? Error: %s", err)
		os.Exit(1)
	}
	config := tls.Config{Certificates: []tls.Certificate{cert}}
	listenerTLS, err := tls.Listen("tcp", cfg.TLSBind, &config)
	if err != nil {
		logger.Errorf("Can not listen on %s: %v\n", cfg.TLSBind, err)
		os.Exit(1)
	}
	logger.Info("TLS listening on ", cfg.TLSBind)
	return listenerTLS
}

func start(socket net.Listener) {
	for {
		conn, err := socket.Accept()
		if err != nil {
			logger.Errorf("Failed to accept connection: %v", err)
			return
		}

		go func() {
			irccfg := &irckit.MmCfg{Insecure: cfg.Insecure, SkipTLSVerify: cfg.SkipTLSVerify,
				SlackSettings: cfg.Slack, MattermostSettings: cfg.Mattermost}
			newsrv := irckit.ServerConfig{Name: "matterircd", Version: version}.Server()
			logger.Infof("New connection: %s", conn.RemoteAddr())
			err = newsrv.Connect(irckit.NewUserMM(conn, newsrv, irccfg))
			if err != nil {
				logger.Errorf("Failed to join: %v", err)
				return
			}
		}()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

type Redirect struct {
	URI          string `json:"uri"`
	Android      string `json:"android"`
	IPhone       string `json:"iphone"`
	IPod         string `json:"ipod"`
	IPad         string `json:"ipad"`
	BlackBerry   string `json:"bb"`
	WindowsPhone string `json:"wp"`
	WinXin       string `json:"wx"`
	Unknown      string `json:"unknown"`
}

type Config struct {
	Address   string      `json:"address"`
	Port      uint16      `json:"port"`
	Redirects []*Redirect `json:"redirect"`
}

var (
	config *Config = new(Config)
)

func handler(w http.ResponseWriter, r *http.Request) {
	var redirect *Redirect = nil
	for _, v := range config.Redirects {
		if v.URI == r.RequestURI {
			redirect = v
			break
		}
	}
	if redirect != nil {
		userAgent := r.UserAgent()
		matched = regexp.MustCompile("MQQBrowser").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched = regexp.MustCompile("TBS").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched := regexp.MustCompile("Android").MatchString(userAgent)
		if matched {
			log.Println("android", redirect.Android)
			http.Redirect(w, r, redirect.Android, 302)
			return
		}
		matched = regexp.MustCompile("iPod").MatchString(userAgent)
		if matched {
			log.Println("ipod", redirect.IPod)
			http.Redirect(w, r, redirect.IPod, 302)
			return
		}
		matched = regexp.MustCompile("iPhone").MatchString(userAgent)
		if matched {
			log.Println("iphone", redirect.IPhone)
			http.Redirect(w, r, redirect.IPhone, 302)
			return
		}
		matched = regexp.MustCompile("iPad").MatchString(userAgent)
		if matched {
			log.Println("ipad", redirect.IPad)
			http.Redirect(w, r, redirect.IPad, 302)
			return
		}
		matched = regexp.MustCompile("BlackBerry").MatchString(userAgent)
		if matched {
			log.Println("bb", redirect.BlackBerry)
			http.Redirect(w, r, redirect.BlackBerry, 302)
			return
		}
		matched = regexp.MustCompile("IEMobile").MatchString(userAgent)
		if matched {
			log.Println("wp", redirect.WindowsPhone)
			http.Redirect(w, r, redirect.WindowsPhone, 302)
			return
		}

		log.Println("unknown", redirect.Unknown)
		http.Redirect(w, r, redirect.Unknown, 302)
		return
	}
	log.Println("unmatched", config.Redirects[0].Unknown)
	http.Redirect(w, r, config.Redirects[0].Unknown, 302)
}

func main() {
	fh, err := os.Open("config.json")
	if err != nil {
		log.Fatal("opening config.json failed")
		return
	}
	defer fh.Close()
	configcontent, err := ioutil.ReadAll(fh)
	if err != nil {
		log.Fatal("reading config.json failed")
		return
	}

	if err = json.Unmarshal(configcontent, config); err != nil {
		log.Fatal("parsing config.json failed")
		return
	}

	http.HandleFunc("/", handler)
	log.Fatal(
		http.ListenAndServe(
			fmt.Sprintf("%s:%d", config.Address, config.Port),
			nil))
}
<commit_msg>(*)fixed build err<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
)

type Redirect struct {
	URI          string `json:"uri"`
	Android      string `json:"android"`
	IPhone       string `json:"iphone"`
	IPod         string `json:"ipod"`
	IPad         string `json:"ipad"`
	BlackBerry   string `json:"bb"`
	WindowsPhone string `json:"wp"`
	WinXin       string `json:"wx"`
	Unknown      string `json:"unknown"`
}

type Config struct {
	Address   string      `json:"address"`
	Port      uint16      `json:"port"`
	Redirects []*Redirect `json:"redirect"`
}

var (
	config *Config = new(Config)
)

func handler(w http.ResponseWriter, r *http.Request) {
	var redirect *Redirect = nil
	for _, v := range config.Redirects {
		if v.URI == r.RequestURI {
			redirect = v
			break
		}
	}
	if redirect != nil {
		userAgent := r.UserAgent()
		matched := regexp.MustCompile("MQQBrowser").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched = regexp.MustCompile("TBS").MatchString(userAgent)
		if matched {
			log.Println("wx", redirect.WinXin)
			http.Redirect(w, r, redirect.WinXin, 302)
			return
		}
		matched = regexp.MustCompile("Android").MatchString(userAgent)
		if matched {
			log.Println("android", redirect.Android)
			http.Redirect(w, r, redirect.Android, 302)
			return
		}
		matched = regexp.MustCompile("iPod").MatchString(userAgent)
		if matched {
			log.Println("ipod", redirect.IPod)
			http.Redirect(w, r, redirect.IPod, 302)
			return
		}
		matched = regexp.MustCompile("iPhone").MatchString(userAgent)
		if matched {
			log.Println("iphone", redirect.IPhone)
			http.Redirect(w, r, redirect.IPhone, 302)
			return
		}
		matched = regexp.MustCompile("iPad").MatchString(userAgent)
		if matched {
			log.Println("ipad", redirect.IPad)
			http.Redirect(w, r, redirect.IPad, 302)
			return
		}
		matched = regexp.MustCompile("BlackBerry").MatchString(userAgent)
		if matched {
			log.Println("bb", redirect.BlackBerry)
			http.Redirect(w, r, redirect.BlackBerry, 302)
			return
		}
		matched = regexp.MustCompile("IEMobile").MatchString(userAgent)
		if matched {
			log.Println("wp", redirect.WindowsPhone)
			http.Redirect(w, r, redirect.WindowsPhone, 302)
			return
		}

		log.Println("unknown", redirect.Unknown)
		http.Redirect(w, r, redirect.Unknown, 302)
		return
	}
	log.Println("unmatched", config.Redirects[0].Unknown)
	http.Redirect(w, r, config.Redirects[0].Unknown, 302)
}

func main() {
	fh, err := os.Open("config.json")
	if err != nil {
		log.Fatal("opening config.json failed")
		return
	}
	defer fh.Close()
	configcontent, err := ioutil.ReadAll(fh)
	if err != nil {
		log.Fatal("reading config.json failed")
		return
	}

	if err = json.Unmarshal(configcontent, config); err != nil {
		log.Fatal("parsing config.json failed")
		return
	}

	http.HandleFunc("/", handler)
	log.Fatal(
		http.ListenAndServe(
			fmt.Sprintf("%s:%d", config.Address, config.Port),
			nil))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"runtime/debug"
	"strconv"
	"time"

	"net/http"
	_ "net/http/pprof"

	"github.com/jessevdk/go-flags"
	"github.com/moncho/dry/app"
	"github.com/moncho/dry/appui"
	"github.com/moncho/dry/docker"
	"github.com/moncho/dry/ui"
	"github.com/moncho/dry/version"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
)

const (
	banner = `     _
    | |
  __| |  ____  _   _
 / _  | / ___)| | | |
( (_| || |    | |_| |
 \____||_|     \__  |
               (____/

`
	cheese     = "<white>made with \U0001F499  (and go) by</> <blue>moncho</>"
	connecting = "\U0001f433  Trying to connect to the Docker Host \U0001f433"
)

var loadMessage = []string{docker.Whale0,
	docker.Whale1,
	docker.Whale2,
	docker.Whale3,
	docker.Whale4,
	docker.Whale5,
	docker.Whale6,
	docker.Whale7,
	docker.Whale}

//options dry's flags
type options struct {
	Description bool   `short:"d" long:"description" description:"Shows the description"`
	MonitorMode string `short:"m" long:"monitor" description:"Starts in monitor mode, given value (if any) is the refresh rate" optional:"yes" optional-value:"500"`
	// enable profiling
	Profile bool `short:"p" long:"profile" description:"Enable profiling"`
	Version bool `short:"v" long:"version" description:"Dry version"`
	//Docker-related properties
	DockerHost       string `short:"H" long:"docker_host" description:"Docker Host"`
	DockerCertPath   string `short:"c" long:"docker_certpath" description:"Docker cert path"`
	DockerTLSVerifiy string `short:"t" long:"docker_tls" description:"Docker TLS verify"`
	//Whale
	Whale uint `short:"w" long:"whale" description:"Show whale for w seconds"`
}

func config(opts options) (app.Config, error) {
	var cfg app.Config
	if opts.DockerHost == "" {
		if os.Getenv("DOCKER_HOST") == "" {
			log.Printf(
				"No DOCKER_HOST env variable found and no Host parameter was given, connecting to %s",
				docker.DefaultDockerHost)
			cfg.DockerHost = docker.DefaultDockerHost
		} else {
			cfg.DockerHost = os.Getenv("DOCKER_HOST")
			cfg.DockerTLSVerify = docker.GetBool(os.Getenv("DOCKER_TLS_VERIFY"))
			cfg.DockerCertPath = os.Getenv("DOCKER_CERT_PATH")
		}
	} else {
		cfg.DockerHost = opts.DockerHost
		cfg.DockerTLSVerify = docker.GetBool(opts.DockerTLSVerifiy)
		cfg.DockerCertPath = opts.DockerCertPath
	}

	if opts.MonitorMode != "" {
		cfg.MonitorMode = true
		refreshRate, err := strconv.Atoi(opts.MonitorMode)
		if err != nil {
			return cfg, errors.Wrap(err, "invalid refresh rate")
		}
		cfg.MonitorRefreshRate = refreshRate
	}
	return cfg, nil
}

func showLoadingScreen(screen *ui.Screen, cfg app.Config) chan<- struct{} {
	screen.Clear()
	midscreen := screen.Dimensions().Width / 2
	height := screen.Dimensions().Height
	screen.RenderAtColumn(midscreen-len(connecting)/2, 1, ui.White(connecting))
	screen.RenderLine(2, height-2, fmt.Sprintf("<blue>Dry Version:</> %s", ui.White(version.VERSION)))
	if cfg.DockerHost != "" {
		screen.RenderLine(2, height-1, fmt.Sprintf("<blue>Docker Host:</> %s", ui.White(cfg.DockerHost)))
	} else {
		screen.RenderLine(2, height-1, ui.White("No Docker host"))
	}

	stop := make(chan struct{})

	//20 is a safe aproximation for the length of interpreted characters from the message
	screen.RenderLine(ui.ActiveScreen.Dimensions().Width-len(cheese)+20, height-1, cheese)
	screen.Flush()
	go func() {
		rotorPos := 0
		forward := true
		ticker := time.NewTicker(250 * time.Millisecond)

		for {
			select {
			case <-ticker.C:
				loadingMessage := loadMessage[rotorPos]
				screen.RenderAtColumn(midscreen-19, height/2-6, ui.Cyan(loadingMessage))
				screen.Flush()
				if rotorPos == len(loadMessage)-1 {
					forward = false
				} else if rotorPos == 0 {
					forward = true
				}
				if forward {
					rotorPos++
				} else {
					rotorPos--
				}

			case <-stop:
				return
			}
		}
	}()
	return stop
}
func main() {
	running := false
	defer func() {
		if r := recover(); r != nil {
			log.Printf(
				"Dry panicked: %v", r)
			log.Error(string(debug.Stack()))
			log.Print("Bye")
			os.Exit(1)
		} else if running {
			log.Print("Bye")
		}
	}()
	// parse flags
	var opts options
	parser := flags.NewParser(&opts, flags.Default)
	_, err := parser.Parse()
	if err != nil {
		flagError := err.(*flags.Error)
		if flagError.Type == flags.ErrHelp {
			return
		}
		if flagError.Type == flags.ErrUnknownFlag {
			log.Print("Use --help to view all available options.")
			return
		}
		log.Printf("Could not parse flags: %s", err)
		return
	}
	if opts.Description {
		fmt.Print(app.ShortHelp)
		return
	}
	if opts.Version {
		fmt.Printf("dry version %s, build %s", version.VERSION, version.GITCOMMIT)
		return
	}
	log.Print("Starting dry")
	// Start profiling (if required)
	if opts.Profile {
		go func() {
			log.Fatal(http.ListenAndServe("localhost:6060", nil))
		}()
	}
	screen, err := ui.NewScreen(appui.DryTheme)
	if err != nil {
		log.Printf("Dry could not start: %s", err)
		return
	}
	running = true
	cfg, err := config(opts)
	if err != nil {
		log.Println(err.Error())
		return
	}

	start := time.Now()
	doneLoading := showLoadingScreen(screen, cfg)

	dry, err := app.NewDry(screen, cfg)

	//if asked to, show whale to bablat a bit longer
	if opts.Whale > 0 {
		showWale, _ := time.ParseDuration(fmt.Sprintf("%ds", opts.Whale))
		time.Sleep(showWale - time.Since(start))
	}
	//dry has loaded, stopping the loading screen
	close(doneLoading)
	if err != nil {
		screen.Close()
		log.Printf("Dry could not start: %s", err)
		return
	}
	app.RenderLoop(dry)
	screen.Close()
}
<commit_msg>use a context to cancel the loading screen<commit_after>package main

import (
	"context"
	"fmt"
	"os"
	"runtime/debug"
	"strconv"
	"time"

	"net/http"
	_ "net/http/pprof"

	"github.com/jessevdk/go-flags"
	"github.com/moncho/dry/app"
	"github.com/moncho/dry/appui"
	"github.com/moncho/dry/docker"
	"github.com/moncho/dry/ui"
	"github.com/moncho/dry/version"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
)

const (
	banner = `     _
    | |
  __| |  ____  _   _
 / _  | / ___)| | | |
( (_| || |    | |_| |
 \____||_|     \__  |
               (____/

`
	cheese     = "<white>made with \U0001F499  (and go) by</> <blue>moncho</>"
	connecting = "\U0001f433  Trying to connect to the Docker Host \U0001f433"
)

var loadMessage = []string{docker.Whale0,
	docker.Whale1,
	docker.Whale2,
	docker.Whale3,
	docker.Whale4,
	docker.Whale5,
	docker.Whale6,
	docker.Whale7,
	docker.Whale}

//options dry's flags
type options struct {
	Description bool   `short:"d" long:"description" description:"Shows the description"`
	MonitorMode string `short:"m" long:"monitor" description:"Starts in monitor mode, given value (if any) is the refresh rate" optional:"yes" optional-value:"500"`
	// enable profiling
	Profile bool `short:"p" long:"profile" description:"Enable profiling"`
	Version bool `short:"v" long:"version" description:"Dry version"`
	//Docker-related properties
	DockerHost       string `short:"H" long:"docker_host" description:"Docker Host"`
	DockerCertPath   string `short:"c" long:"docker_certpath" description:"Docker cert path"`
	DockerTLSVerifiy string `short:"t" long:"docker_tls" description:"Docker TLS verify"`
	//Whale
	Whale uint `short:"w" long:"whale" description:"Show whale for w seconds"`
}

func config(opts options) (app.Config, error) {
	var cfg app.Config
	if opts.DockerHost == "" {
		if os.Getenv("DOCKER_HOST") == "" {
			log.Printf(
				"No DOCKER_HOST env variable found and no Host parameter was given, connecting to %s",
				docker.DefaultDockerHost)
			cfg.DockerHost = docker.DefaultDockerHost
		} else {
			cfg.DockerHost = os.Getenv("DOCKER_HOST")
			cfg.DockerTLSVerify = docker.GetBool(os.Getenv("DOCKER_TLS_VERIFY"))
			cfg.DockerCertPath = os.Getenv("DOCKER_CERT_PATH")
		}
	} else {
		cfg.DockerHost = opts.DockerHost
		cfg.DockerTLSVerify = docker.GetBool(opts.DockerTLSVerifiy)
		cfg.DockerCertPath = opts.DockerCertPath
	}

	if opts.MonitorMode != "" {
		cfg.MonitorMode = true
		refreshRate, err := strconv.Atoi(opts.MonitorMode)
		if err != nil {
			return cfg, errors.Wrap(err, "invalid refresh rate")
		}
		cfg.MonitorRefreshRate = refreshRate
	}
	return cfg, nil
}

func showLoadingScreen(ctx context.Context, screen *ui.Screen, cfg app.Config) {
	screen.Clear()
	midscreen := screen.Dimensions().Width / 2
	height := screen.Dimensions().Height
	screen.RenderAtColumn(midscreen-len(connecting)/2, 1, ui.White(connecting))
	screen.RenderLine(2, height-2, fmt.Sprintf("<blue>Dry Version:</> %s", ui.White(version.VERSION)))
	if cfg.DockerHost != "" {
		screen.RenderLine(2, height-1, fmt.Sprintf("<blue>Docker Host:</> %s", ui.White(cfg.DockerHost)))
	} else {
		screen.RenderLine(2, height-1, ui.White("No Docker host"))
	}

	//20 is a safe aproximation for the length of interpreted characters from the message
	screen.RenderLine(ui.ActiveScreen.Dimensions().Width-len(cheese)+20, height-1, cheese)
	screen.Flush()
	go func() {
		rotorPos := 0
		forward := true
		ticker := time.NewTicker(250 * time.Millisecond)

		for {
			select {
			case <-ticker.C:
				loadingMessage := loadMessage[rotorPos]
				screen.RenderAtColumn(midscreen-19, height/2-6, ui.Cyan(loadingMessage))
				screen.Flush()
				if rotorPos == len(loadMessage)-1 {
					forward = false
				} else if rotorPos == 0 {
					forward = true
				}
				if forward {
					rotorPos++
				} else {
					rotorPos--
				}

			case <-ctx.Done():
				return
			}
		}
	}()
}
func main() {
	running := false
	defer func() {
		if r := recover(); r != nil {
			log.Printf(
				"Dry panicked: %v", r)
			log.Error(string(debug.Stack()))
			log.Print("Bye")
			os.Exit(1)
		} else if running {
			log.Print("Bye")
		}
	}()
	// parse flags
	var opts options
	parser := flags.NewParser(&opts, flags.Default)
	_, err := parser.Parse()
	if err != nil {
		flagError := err.(*flags.Error)
		if flagError.Type == flags.ErrHelp {
			return
		}
		if flagError.Type == flags.ErrUnknownFlag {
			log.Print("Use --help to view all available options.")
			return
		}
		log.Printf("Could not parse flags: %s", err)
		return
	}
	if opts.Description {
		fmt.Print(app.ShortHelp)
		return
	}
	if opts.Version {
		fmt.Printf("dry version %s, build %s", version.VERSION, version.GITCOMMIT)
		return
	}
	log.Print("Starting dry")
	// Start profiling (if required)
	if opts.Profile {
		go func() {
			log.Fatal(http.ListenAndServe("localhost:6060", nil))
		}()
	}
	screen, err := ui.NewScreen(appui.DryTheme)
	if err != nil {
		log.Printf("Dry could not start: %s", err)
		return
	}
	running = true
	cfg, err := config(opts)
	if err != nil {
		log.Println(err.Error())
		return
	}

	start := time.Now()
	ctx, cancel := context.WithCancel(context.Background())
	showLoadingScreen(ctx, screen, cfg)

	dry, err := app.NewDry(screen, cfg)

	//if asked to, show whale to bablat a bit longer
	if opts.Whale > 0 {
		showWale, _ := time.ParseDuration(fmt.Sprintf("%ds", opts.Whale))
		time.Sleep(showWale - time.Since(start))
	}
	//dry has loaded, stopping the loading screen
	cancel()
	if err != nil {
		screen.Close()
		log.Printf("Dry could not start: %s", err)
		return
	}
	app.RenderLoop(dry)
	screen.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"runtime"
	"strconv"
	"strings"
	"sync"

	"github.com/mholt/caddy/config"
	"github.com/mholt/caddy/server"
)

var (
	conf  string
	http2 bool // TODO: temporary flag until http2 is standard
	quiet bool
	cpu   string
)

func init() {
	flag.StringVar(&conf, "conf", config.DefaultConfigFile, "the configuration file to use")
	flag.BoolVar(&http2, "http2", true, "enable HTTP/2 support") // TODO: temporary flag until http2 merged into std lib
	flag.BoolVar(&quiet, "quiet", false, "quiet mode (no initialization output)")
	flag.StringVar(&cpu, "cpu", "100%", "CPU cap")
	flag.StringVar(&config.Host, "host", config.DefaultHost, "Default host")
	flag.StringVar(&config.Port, "port", config.DefaultPort, "Default port")
	flag.Parse()
}

func main() {
	var wg sync.WaitGroup

	// Set CPU cap
	err := setCPU(cpu)
	if err != nil {
		log.Fatal(err)
	}

	// Load config from file
	allConfigs, err := config.Load(conf)
	if err != nil {
		if config.IsNotFound(err) {
			allConfigs = config.Default()
		} else {
			log.Fatal(err)
		}
	}
	if len(allConfigs) == 0 {
		allConfigs = config.Default()
	}

	// Group by address (virtual hosts)
	addresses, err := arrangeBindings(allConfigs)
	if err != nil {
		log.Fatal(err)
	}

	// Start each server with its one or more configurations
	for addr, configs := range addresses {
		s, err := server.New(addr, configs, configs[0].TLS.Enabled)
		if err != nil {
			log.Fatal(err)
		}
		s.HTTP2 = http2 // TODO: This setting is temporary
		wg.Add(1)
		go func(s *server.Server) {
			defer wg.Done()
			err := s.Serve()
			if err != nil {
				log.Println(err)
			}
		}(s)

		if !quiet {
			for _, config := range configs {
				fmt.Println(config.Address())
			}
		}
	}

	wg.Wait()
}

// arrangeBindings groups configurations by their bind address. For example,
// a server that should listen on localhost and another on 127.0.0.1 will
// be grouped into the same address: 127.0.0.1. It will return an error
// if the address lookup fails or if a TLS listener is configured on the
// same address as a plaintext HTTP listener.
func arrangeBindings(allConfigs []config.Config) (map[string][]config.Config, error) {
	addresses := make(map[string][]config.Config)

	// Group configs by bind address
	for _, conf := range allConfigs {
		addr, err := net.ResolveTCPAddr("tcp", conf.Address())
		if err != nil {
			return addresses, err
		}
		addresses[addr.String()] = append(addresses[addr.String()], conf)
	}

	// Don't allow HTTP and HTTPS to be served on the same address
	for _, configs := range addresses {
		isTLS := configs[0].TLS.Enabled
		for _, config := range configs {
			if config.TLS.Enabled != isTLS {
				thisConfigProto, otherConfigProto := "HTTP", "HTTP"
				if config.TLS.Enabled {
					thisConfigProto = "HTTPS"
				}
				if configs[0].TLS.Enabled {
					otherConfigProto = "HTTPS"
				}
				return addresses, fmt.Errorf("Configuration error: Cannot multiplex %s (%s) and %s (%s) on same address",
					configs[0].Address(), otherConfigProto, config.Address(), thisConfigProto)
			}
		}
	}

	return addresses, nil
}

// setCPU parses string cpu and sets GOMAXPROCS
// according to its value. It accepts either
// a number (e.g. 3) or a percent (e.g. 50%).
func setCPU(cpu string) error {
	var numCPU int

	availCPU := runtime.NumCPU()

	if strings.HasSuffix(cpu, "%") {
		// Percent
		var percent float32
		pctStr := cpu[:len(cpu)-1]
		pctInt, err := strconv.Atoi(pctStr)
		if err != nil || pctInt < 1 || pctInt > 100 {
			return errors.New("Invalid CPU value: percentage must be between 1-100")
		}
		percent = float32(pctInt) / 100
		numCPU = int(float32(availCPU) * percent)
	} else {
		// Number
		num, err := strconv.Atoi(cpu)
		if err != nil || num < 1 {
			return errors.New("Invalid CPU value: provide a number or percent greater than 0")
		}
		numCPU = num
	}

	if numCPU > availCPU {
		numCPU = availCPU
	}

	runtime.GOMAXPROCS(numCPU)
	return nil
}
<commit_msg>core: Kill whole process if any server fail to start<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"log"
	"net"
	"runtime"
	"strconv"
	"strings"
	"sync"

	"github.com/mholt/caddy/config"
	"github.com/mholt/caddy/server"
)

var (
	conf  string
	http2 bool // TODO: temporary flag until http2 is standard
	quiet bool
	cpu   string
)

func init() {
	flag.StringVar(&conf, "conf", config.DefaultConfigFile, "the configuration file to use")
	flag.BoolVar(&http2, "http2", true, "enable HTTP/2 support") // TODO: temporary flag until http2 merged into std lib
	flag.BoolVar(&quiet, "quiet", false, "quiet mode (no initialization output)")
	flag.StringVar(&cpu, "cpu", "100%", "CPU cap")
	flag.StringVar(&config.Host, "host", config.DefaultHost, "Default host")
	flag.StringVar(&config.Port, "port", config.DefaultPort, "Default port")
	flag.Parse()
}

func main() {
	var wg sync.WaitGroup

	// Set CPU cap
	err := setCPU(cpu)
	if err != nil {
		log.Fatal(err)
	}

	// Load config from file
	allConfigs, err := config.Load(conf)
	if err != nil {
		if config.IsNotFound(err) {
			allConfigs = config.Default()
		} else {
			log.Fatal(err)
		}
	}
	if len(allConfigs) == 0 {
		allConfigs = config.Default()
	}

	// Group by address (virtual hosts)
	addresses, err := arrangeBindings(allConfigs)
	if err != nil {
		log.Fatal(err)
	}

	// Start each server with its one or more configurations
	for addr, configs := range addresses {
		s, err := server.New(addr, configs, configs[0].TLS.Enabled)
		if err != nil {
			log.Fatal(err)
		}
		s.HTTP2 = http2 // TODO: This setting is temporary
		wg.Add(1)
		go func(s *server.Server) {
			defer wg.Done()
			err := s.Serve()
			if err != nil {
				log.Fatal(err) // kill whole process to avoid a half-alive zombie server
			}
		}(s)

		if !quiet {
			for _, config := range configs {
				fmt.Println(config.Address())
			}
		}
	}

	wg.Wait()
}

// arrangeBindings groups configurations by their bind address. For example,
// a server that should listen on localhost and another on 127.0.0.1 will
// be grouped into the same address: 127.0.0.1. It will return an error
// if the address lookup fails or if a TLS listener is configured on the
// same address as a plaintext HTTP listener.
func arrangeBindings(allConfigs []config.Config) (map[string][]config.Config, error) {
	addresses := make(map[string][]config.Config)

	// Group configs by bind address
	for _, conf := range allConfigs {
		addr, err := net.ResolveTCPAddr("tcp", conf.Address())
		if err != nil {
			return addresses, err
		}
		addresses[addr.String()] = append(addresses[addr.String()], conf)
	}

	// Don't allow HTTP and HTTPS to be served on the same address
	for _, configs := range addresses {
		isTLS := configs[0].TLS.Enabled
		for _, config := range configs {
			if config.TLS.Enabled != isTLS {
				thisConfigProto, otherConfigProto := "HTTP", "HTTP"
				if config.TLS.Enabled {
					thisConfigProto = "HTTPS"
				}
				if configs[0].TLS.Enabled {
					otherConfigProto = "HTTPS"
				}
				return addresses, fmt.Errorf("Configuration error: Cannot multiplex %s (%s) and %s (%s) on same address",
					configs[0].Address(), otherConfigProto, config.Address(), thisConfigProto)
			}
		}
	}

	return addresses, nil
}

// setCPU parses string cpu and sets GOMAXPROCS
// according to its value. It accepts either
// a number (e.g. 3) or a percent (e.g. 50%).
func setCPU(cpu string) error {
	var numCPU int

	availCPU := runtime.NumCPU()

	if strings.HasSuffix(cpu, "%") {
		// Percent
		var percent float32
		pctStr := cpu[:len(cpu)-1]
		pctInt, err := strconv.Atoi(pctStr)
		if err != nil || pctInt < 1 || pctInt > 100 {
			return errors.New("Invalid CPU value: percentage must be between 1-100")
		}
		percent = float32(pctInt) / 100
		numCPU = int(float32(availCPU) * percent)
	} else {
		// Number
		num, err := strconv.Atoi(cpu)
		if err != nil || num < 1 {
			return errors.New("Invalid CPU value: provide a number or percent greater than 0")
		}
		numCPU = num
	}

	if numCPU > availCPU {
		numCPU = availCPU
	}

	runtime.GOMAXPROCS(numCPU)
	return nil
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"log"
	"net/http"
	"math/rand"
	"time"
	"strconv"
	"strings"
	"os"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func random(min, max int) int {
    rand.Seed(time.Now().Unix())
    return rand.Intn(max - min) + min
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				action := strings.Contains(message.Text, "吃")
				target := strings.Contains(message.Text, "什麼")
				if !target {
					target = strings.Contains(message.Text, "啥")
				}

				if action && target {
					log.Print("SIVA: BINGO")

					i := random(1, 10)
					env := strconv.FormatInt(int64(i), 10)
					env = "SWFood"+env
					ans := os.Getenv(env)
					log.Print("SIVA: "+ans)

					if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ans)).Do(); err != nil {
						log.Print(err)
					}
				}
				//if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.ID+":"+message.Text+" OK!")).Do(); err != nil {
				//	log.Print(err)
				//}
			}
		}
	}
}
<commit_msg>try to handle location message<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"log"
	"net/http"
	"math/rand"
	"time"
	"strconv"
	"strings"
	"os"

	"github.com/line/line-bot-sdk-go/linebot"
)

var bot *linebot.Client

func main() {
	var err error
	bot, err = linebot.New(os.Getenv("ChannelSecret"), os.Getenv("ChannelAccessToken"))
	log.Println("Bot:", bot, " err:", err)
	http.HandleFunc("/callback", callbackHandler)
	port := os.Getenv("PORT")
	addr := fmt.Sprintf(":%s", port)
	http.ListenAndServe(addr, nil)
}

func random(min, max int) int {
    rand.Seed(time.Now().Unix())
    return rand.Intn(max - min) + min
}

func callbackHandler(w http.ResponseWriter, r *http.Request) {
	events, err := bot.ParseRequest(r)

	if err != nil {
		if err == linebot.ErrInvalidSignature {
			w.WriteHeader(400)
		} else {
			w.WriteHeader(500)
		}
		return
	}

	for _, event := range events {
		switch event.Type {
		case linebot.EventTypeMessage:
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				if err := handleText(message, event.ReplyToken, event.Source); err != nil {
					log.Print(err)
				}
			case *linebot.ImageMessage:
				if err := handleImage(message, event.ReplyToken); err != nil {
					log.Print(err)
				}
			case *linebot.VideoMessage:
				if err := handleVideo(message, event.ReplyToken); err != nil {
					log.Print(err)
				}
			case *linebot.AudioMessage:
				if err := handleAudio(message, event.ReplyToken); err != nil {
					log.Print(err)
				}
			case *linebot.LocationMessage:
				if err := handleLocation(message, event.ReplyToken); err != nil {
					log.Print(err)
				}
			case *linebot.StickerMessage:
				if err := handleSticker(message, event.ReplyToken); err != nil {
					log.Print(err)
				}
			default:
				log.Printf("Unknown message: %v", message)
			}
		case linebot.EventTypeFollow:
			log.Print("Followed this bot: %v", event)
		case linebot.EventTypeUnfollow:
			log.Printf("Unfollowed this bot: %v", event)
		case linebot.EventTypeJoin:
			log.Print("Join: %v", event)
		case linebot.EventTypeLeave:
			log.Printf("Left: %v", event)
		case linebot.EventTypePostback:
			log.Print("Postback: %v", event)
		case linebot.EventTypeBeacon:
			log.Print("Beacon: %v", event)
		default:
			log.Printf("Unknown event: %v", event)
		}
	}

	/*
	for _, event := range events {
		if event.Type == linebot.EventTypeMessage {
			switch message := event.Message.(type) {
			case *linebot.TextMessage:
				action := strings.Contains(message.Text, "吃")
				target := strings.Contains(message.Text, "什麼")
				if !target {
					target = strings.Contains(message.Text, "啥")
				}

				if action && target {
					log.Print("SIVA: BINGO")

					i := random(1, 10)
					env := strconv.FormatInt(int64(i), 10)
					env = "SWFood"+env
					ans := os.Getenv(env)
					log.Print("SIVA: "+ans)

					if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(ans)).Do(); err != nil {
						log.Print(err)
					}
				}
				//if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.ID+":"+message.Text+" OK!")).Do(); err != nil {
				//	log.Print(err)
				//}
			}
		}
	}
	*/
}

func handleText(message *linebot.TextMessage, replyToken string, source *linebot.EventSource) error {

	action := strings.Contains(message.Text, "吃")
	target := strings.Contains(message.Text, "什麼")
	if !target {
		target = strings.Contains(message.Text, "啥")
	}

	if action && target {
		log.Print("SIVA: BINGO")

		i := random(1, 10)
		env := strconv.FormatInt(int64(i), 10)
		env = "SWFood"+env
		ans := os.Getenv(env)
		log.Print("SIVA: "+ans)

		if _, err := bot.ReplyMessage(replyToken, linebot.NewTextMessage(ans)).Do(); err != nil {
			log.Print(err)
		}
	}

	return nil
}

func handleImage(message *linebot.ImageMessage, replyToken string) error {
	return nil
}

func handleVideo(message *linebot.VideoMessage, replyToken string) error {
	return nil
}

func handleAudio(message *linebot.AudioMessage, replyToken string) error {
	return nil
}

func handleLocation(message *linebot.LocationMessage, replyToken string) error {
	log.Print("handleLocation")
	return nil
}

func handleSticker(message *linebot.StickerMessage, replyToken string) error {
	return nil
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/bgentry/pflag"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

type Command struct {
	Usage string
	Flag  pflag.FlagSet
	Short string
	Long  string
	Run   func(cmd *Command, args []string)
}

func (c *Command) PrintUsage() {
	fmt.Fprintf(os.Stderr, "Usage: zk %s\n", c.Usage)
	fmt.Fprintf(os.Stderr, "Run 'zk help %s' for details.\n", c.Name())
}

func (c *Command) PrintLongUsage() {
	fmt.Printf("Usage: zk %s\n\n", c.Usage)
	fmt.Println(strings.Trim(c.Long, "\n"))
}

func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func printOverviewUsage(w io.Writer) {
	fmt.Fprintf(w, "Usage: zk <command> [options] [arguments]\n")
	fmt.Fprintf(w, "\n")
	fmt.Fprintf(w, "Commands:\n")
	for _, command := range commands {
		fmt.Fprintf(w, "    %-8s    %s\n", command.Name(), command.Short)
	}
	fmt.Fprintf(w, "\n")
	fmt.Fprintf(w, "Run 'zk help <command>' for details.\n")
}

var cmdHelp = &Command{
	Usage: "help [<command>]",
	Short: "show help",
	Long: `
Help shows usage details for a single command if one is given, or
overview usage if no command is specified.`,
	Run: runHelp,
}

func runHelp(cmd *Command, args []string) {
	if len(args) == 0 {
		printOverviewUsage(os.Stdout)
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "error: too many arguments")
		os.Exit(2)
	}
	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			cmd.PrintLongUsage()
			return
		}
	}

	fmt.Fprintf(os.Stderr, "error: unrecognized command: %s\n", args[0])
	fmt.Fprintf(os.Stderr, "Run 'zk help' for usage.\n")
	os.Exit(2)
}

var commands []*Command

func init() {
	commands = []*Command{
		cmdExists,
		cmdStat,
		cmdGet,
		cmdCreate,
		cmdSet,
		cmdDelete,
		cmdChildren,
		cmdHelp,
	}
}

func main() {
	args := os.Args[1:]
	if len(args) < 1 || strings.IndexRune(args[0], '-') == 0 {
		printOverviewUsage(os.Stderr)
		os.Exit(2)
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			cmd.Flag.SetInterspersed(true)
			cmd.Flag.Usage = cmd.PrintUsage
			if err := cmd.Flag.Parse(args[1:]); err == pflag.ErrHelp {
				cmdHelp.Run(cmdHelp, args[:1])
				return
			} else if err != nil {
				fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
				os.Exit(2)
			}
			cmd.Run(cmd, cmd.Flag.Args())
			return
		}
	}

	fmt.Fprintf(os.Stderr, "error: unrecognized command: %s\n", args[0])
	fmt.Fprintf(os.Stderr, "Run 'zk help' for usage.\n")
	os.Exit(2)
}

func inData() []byte {
	data, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	return data
}

func outString(p string, args ...interface{}) {
	_, err := fmt.Fprintf(os.Stdout, p, args...)
	must(err)
}

func outData(d []byte) {
	_, err := os.Stdout.Write(d)
	must(err)
}

func must(err error) {
	if err != nil {
		errString := strings.TrimPrefix(err.Error(), "zk: ")
		fmt.Fprintf(os.Stderr, "error: %s\n", errString)
		os.Exit(1)
	}
}

func failUsage(cmd *Command) {
       cmd.PrintUsage()
       os.Exit(2)
}
<commit_msg>Refactoring<commit_after>package main

import (
	"fmt"
	"github.com/bgentry/pflag"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

type Command struct {
	Usage string
	Flag  pflag.FlagSet
	Short string
	Long  string
	Run   func(cmd *Command, args []string)
}

func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) PrintUsage() {
	fmt.Fprintf(os.Stderr, "Usage: zk %s\n", c.Usage)
	fmt.Fprintf(os.Stderr, "Run 'zk help %s' for details.\n", c.Name())
}

func printOverviewUsage(w io.Writer) {
	fmt.Fprintf(w, "Usage: zk <command> [options] [arguments]\n")
	fmt.Fprintf(w, "\n")
	fmt.Fprintf(w, "Commands:\n")
	for _, command := range commands {
		fmt.Fprintf(w, "    %-8s    %s\n", command.Name(), command.Short)
	}
	fmt.Fprintf(w, "\n")
	fmt.Fprintf(w, "Run 'zk help <command>' for details.\n")
}

func printCommandUsage(c *Command) {
	fmt.Printf("Usage: zk %s\n\n", c.Usage)
	fmt.Println(strings.Trim(c.Long, "\n"))
}

var cmdHelp = &Command{
	Usage: "help [<command>]",
	Short: "show help",
	Long: `
Help shows usage details for a single command if one is given, or
overview usage if no command is specified.`,
	Run: runHelp,
}

func runHelp(cmd *Command, args []string) {
	if len(args) == 0 {
		printOverviewUsage(os.Stdout)
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "error: too many arguments")
		os.Exit(2)
	}
	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			printCommandUsage(cmd)
			return
		}
	}
	fmt.Fprintf(os.Stderr, "error: unrecognized command: %s\n", args[0])
	fmt.Fprintf(os.Stderr, "Run 'zk help' for usage.\n")
	os.Exit(2)
}

var commands []*Command

func init() {
	commands = []*Command{
		cmdExists,
		cmdStat,
		cmdGet,
		cmdCreate,
		cmdSet,
		cmdDelete,
		cmdChildren,
		cmdHelp,
	}
}

func main() {
	args := os.Args[1:]
	if len(args) < 1 || strings.IndexRune(args[0], '-') == 0 {
		printOverviewUsage(os.Stderr)
		os.Exit(2)
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] {
			cmd.Flag.SetInterspersed(true)
			cmd.Flag.Usage = cmd.PrintUsage
			if err := cmd.Flag.Parse(args[1:]); err == pflag.ErrHelp {
				cmdHelp.Run(cmdHelp, args[:1])
				return
			} else if err != nil {
				fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
				os.Exit(2)
			}
			cmd.Run(cmd, cmd.Flag.Args())
			return
		}
	}

	fmt.Fprintf(os.Stderr, "error: unrecognized command: %s\n", args[0])
	fmt.Fprintf(os.Stderr, "Run 'zk help' for usage.\n")
	os.Exit(2)
}

func inData() []byte {
	data, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		panic(err)
	}
	return data
}

func outString(p string, args ...interface{}) {
	_, err := fmt.Fprintf(os.Stdout, p, args...)
	must(err)
}

func outData(d []byte) {
	_, err := os.Stdout.Write(d)
	must(err)
}

func must(err error) {
	if err != nil {
		errString := strings.TrimPrefix(err.Error(), "zk: ")
		fmt.Fprintf(os.Stderr, "error: %s\n", errString)
		os.Exit(1)
	}
}

func failUsage(cmd *Command) {
       cmd.PrintUsage()
       os.Exit(2)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"strings"
	"time"

	"github.com/cloudfoundry-incubator/executor/executor"
	"github.com/cloudfoundry-incubator/executor/taskregistry"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	"github.com/cloudfoundry/storeadapter/workerpool"
	"github.com/vito/gordon"
)

var wardenNetwork = flag.String(
	"wardenNetwork",
	"unix",
	"network mode for warden server (tcp, unix)",
)

var wardenAddr = flag.String(
	"wardenAddr",
	"/tmp/warden.sock",
	"network address for warden server",
)

var etcdMachines = flag.String(
	"etcdMachines",
	"http://127.0.0.1:4001",
	"comma-separated list of etcd addresses (http://ip:port)",
)

var logLevel = flag.String(
	"logLevel",
	"info",
	"the logging level (none, fatal, error, warn, info, debug, debug1, debug2, all)",
)

var memoryMB = flag.Int(
	"memoryMB",
	0,
	"the amount of memory the executor has available in megabytes",
)

var diskMB = flag.Int(
	"diskMB",
	0,
	"the amount of disk the executor has available in megabytes",
)

var registrySnapshotFile = flag.String(
	"registrySnapshotFile",
	"registry_snapshot",
	"the location, on disk, where the task registry snapshot should be stored",
)

func main() {
	flag.Parse()

	l, err := steno.GetLogLevel(*logLevel)
	if err != nil {
		log.Fatalf("Invalid loglevel: %s\n", *logLevel)
	}

	stenoConfig := steno.Config{
		Level: l,
		Sinks: []steno.Sink{steno.NewIOSink(os.Stdout)},
	}

	steno.Init(&stenoConfig)
	logger := steno.NewLogger("main")

	etcdAdapter := etcdstoreadapter.NewETCDStoreAdapter(
		strings.Split(*etcdMachines, ","),
		workerpool.NewWorkerPool(10),
	)

	bbs := Bbs.New(etcdAdapter)
	err = etcdAdapter.Connect()
	if err != nil {
		logger.Errord(map[string]interface{}{
			"error": err,
		}, "failed to get etcdAdapter to connect")
		os.Exit(1)
	}

	wardenClient := gordon.NewClient(&gordon.ConnectionInfo{
		Network: *wardenNetwork,
		Addr:    *wardenAddr,
	})

	err = wardenClient.Connect()
	if err != nil {
		logger.Errord(map[string]interface{}{
			"error": err,
		}, "warden is not up!")
		os.Exit(1)
	}

	if *memoryMB <= 0 || *diskMB <= 0 {
		logger.Error("memory and disk capacity must be specified on startup!")
		os.Exit(1)
	}

	taskRegistry, err := taskregistry.LoadTaskRegistryFromDisk(*registrySnapshotFile, *memoryMB, *diskMB)
	if err != nil {
		taskRegistry = taskregistry.NewTaskRegistry(*registrySnapshotFile, *memoryMB, *diskMB)
	}
	executor := executor.New(bbs, wardenClient, taskRegistry)

	executor.HandleRunOnces()
	logger.Infof("Watching for RunOnces!")

	executor.ConvergeRunOnces(30 * time.Second)
	logger.Infof("Converging RunOnces!")

	select {}
}
<commit_msg>update memory and disk capacity message<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"strings"
	"time"

	"github.com/cloudfoundry-incubator/executor/executor"
	"github.com/cloudfoundry-incubator/executor/taskregistry"
	Bbs "github.com/cloudfoundry-incubator/runtime-schema/bbs"
	steno "github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/storeadapter/etcdstoreadapter"
	"github.com/cloudfoundry/storeadapter/workerpool"
	"github.com/vito/gordon"
)

var wardenNetwork = flag.String(
	"wardenNetwork",
	"unix",
	"network mode for warden server (tcp, unix)",
)

var wardenAddr = flag.String(
	"wardenAddr",
	"/tmp/warden.sock",
	"network address for warden server",
)

var etcdMachines = flag.String(
	"etcdMachines",
	"http://127.0.0.1:4001",
	"comma-separated list of etcd addresses (http://ip:port)",
)

var logLevel = flag.String(
	"logLevel",
	"info",
	"the logging level (none, fatal, error, warn, info, debug, debug1, debug2, all)",
)

var memoryMB = flag.Int(
	"memoryMB",
	0,
	"the amount of memory the executor has available in megabytes",
)

var diskMB = flag.Int(
	"diskMB",
	0,
	"the amount of disk the executor has available in megabytes",
)

var registrySnapshotFile = flag.String(
	"registrySnapshotFile",
	"registry_snapshot",
	"the location, on disk, where the task registry snapshot should be stored",
)

func main() {
	flag.Parse()

	l, err := steno.GetLogLevel(*logLevel)
	if err != nil {
		log.Fatalf("Invalid loglevel: %s\n", *logLevel)
	}

	stenoConfig := steno.Config{
		Level: l,
		Sinks: []steno.Sink{steno.NewIOSink(os.Stdout)},
	}

	steno.Init(&stenoConfig)
	logger := steno.NewLogger("main")

	etcdAdapter := etcdstoreadapter.NewETCDStoreAdapter(
		strings.Split(*etcdMachines, ","),
		workerpool.NewWorkerPool(10),
	)

	bbs := Bbs.New(etcdAdapter)
	err = etcdAdapter.Connect()
	if err != nil {
		logger.Errord(map[string]interface{}{
			"error": err,
		}, "failed to get etcdAdapter to connect")
		os.Exit(1)
	}

	wardenClient := gordon.NewClient(&gordon.ConnectionInfo{
		Network: *wardenNetwork,
		Addr:    *wardenAddr,
	})

	err = wardenClient.Connect()
	if err != nil {
		logger.Errord(map[string]interface{}{
			"error": err,
		}, "warden is not up!")
		os.Exit(1)
	}

	if *memoryMB <= 0 || *diskMB <= 0 {
		logger.Error("valid memory and disk capacity must be specified on startup!")
		os.Exit(1)
	}

	taskRegistry, err := taskregistry.LoadTaskRegistryFromDisk(*registrySnapshotFile, *memoryMB, *diskMB)
	if err != nil {
		taskRegistry = taskregistry.NewTaskRegistry(*registrySnapshotFile, *memoryMB, *diskMB)
	}
	executor := executor.New(bbs, wardenClient, taskRegistry)

	executor.HandleRunOnces()
	logger.Infof("Watching for RunOnces!")

	executor.ConvergeRunOnces(30 * time.Second)
	logger.Infof("Converging RunOnces!")

	select {}
}
<|endoftext|>


<commit_before>package miniprofiler

import (
	"fmt"
	"io"
	"math"
	"sort"
	"strings"
	"time"
)

var (
	mp        *MiniProfiler
	enabled   bool
	condition func() bool
)

type MiniProfilerData struct {
	description string
	steps       map[string]int64
	lastStep    time.Time
	memos       []string
}

type MiniProfiler struct {
	profiles []*MiniProfilerData
}

func init() {
	mp = new(MiniProfiler)
	mp.profiles = make([]*MiniProfilerData, 0)
	enabled = true
	condition = func() bool { return true }
}

func Enable() {
	enabled = true
}

func Disable() {
	enabled = false
}

func SetCondition(c func() bool) {
	condition = c
}

func Begin(description string) *MiniProfilerData {
	if !enabled {
		return nil
	}
	if !condition() {
		return nil
	}
	return &MiniProfilerData{description, make(map[string]int64, 0), time.Now(), make([]string, 0)}
}

func Flush(writer io.Writer) {
	for _, prof := range mp.profiles {
		outputs := []string{"log:MP"}

		for tag, val := range prof.steps {
			outputs = append(outputs, fmt.Sprintf("%s:%d", tag, val))
		}

		outputs = append(outputs, fmt.Sprintf("description:%s", prof.description))

		memoOutput := []string{}
		for _, m := range prof.memos {
			memoOutput = append(memoOutput, m)
		}
		outputs = append(outputs, fmt.Sprintf("memo:%s", strings.Join(memoOutput, ",")))

		fmt.Fprintln(writer, strings.Join(outputs, "\t"))
	}
	mp.profiles = make([]*MiniProfilerData, 0)
}

type Measure struct {
	Description string
	Count       int
	Total       int
	Mean        int
	Min         int
	Max         int
}

type By func(a, b *Measure) bool

func (by By) Sort(measures []*Measure) {
	ms := &measureSorter{
		measures: measures,
		by:       by,
	}
	sort.Sort(ms)
}

type measureSorter struct {
	measures []*Measure
	by       func(a, b *Measure) bool
}

func (s *measureSorter) Len() int {
	return len(s.measures)
}

func (s *measureSorter) Swap(i, j int) {
	s.measures[i], s.measures[j] = s.measures[j], s.measures[i]
}

func (s *measureSorter) Less(i, j int) bool {
	return s.by(s.measures[i], s.measures[j])
}

type Column struct {
	Name    string
	Summary string
	Sort    By
}

var (
	columns = []*Column{
		&Column{Name: "Count", Summary: "Count", Sort: func(a, b *Measure) bool { return a.Count > b.Count }},
		&Column{Name: "Total", Summary: "Total", Sort: func(a, b *Measure) bool { return a.Total > b.Total }},
		&Column{Name: "Mean", Summary: "Mean", Sort: func(a, b *Measure) bool { return a.Mean > b.Mean }},
		&Column{Name: "Min"},
		&Column{Name: "Max", Summary: "Maximum(100 Percentile)", Sort: func(a, b *Measure) bool { return a.Max > b.Max }},
	}
)

func getIntegerDigitWidth(i int) int {
	var w int
	switch {
	case i < 1:
		w = 1
	default:
		w = int(math.Log10(float64(i)) + 1)
	}
	return w
}

func showMeasures(writer io.Writer, measures []*Measure) {
	countWidth := 5
	totalWidth := 5
	meanWidth := 5
	maxWidth := 5

	for _, m := range measures {
		var w int
		w = getIntegerDigitWidth(m.Count)
		if countWidth < w {
			countWidth = w
		}
		w = getIntegerDigitWidth(m.Total)
		if totalWidth < w {
			totalWidth = w
		}
		w = getIntegerDigitWidth(m.Mean)
		if meanWidth < w {
			meanWidth = w
		}
		w = getIntegerDigitWidth(m.Max)
		if maxWidth < w {
			maxWidth = w
		}
	}

	var format string
	for _, column := range columns {
		switch column.Name {
		case "Count":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", countWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", countWidth)
		case "Total":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", totalWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", totalWidth)
		case "Mean":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", meanWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", meanWidth)
		default:
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", maxWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", maxWidth)
		}
	}
	fmt.Fprintln(writer, "Description")
	format += "%s\n"

	for _, m := range measures {
		fmt.Fprintf(writer, format, m.Count, m.Total, m.Mean, m.Min, m.Max, m.Description)
	}
}

func Analyze(writer io.Writer) {
	var times = make(map[string][]int)
	var totals = make(map[string]int)
	for _, prof := range mp.profiles {
		for tag, val := range prof.steps {
			times[tag] = append(times[tag], int(val))
			totals[tag] += int(val)
		}
	}
	var measures []*Measure
	for tag, times := range times {
		sort.Ints(times)
		count := len(times)
		total := totals[tag]
		m := &Measure{
			Description: tag,
			Count:       count,
			Total:       total,
			Mean:        total / count,
			Min:         times[0],
			Max:         times[count-1],
		}
		measures = append(measures, m)
	}

	for _, column := range columns {
		if column.Sort != nil {
			fmt.Fprintf(writer, "Sort by %s\n", column.Summary)
			By(column.Sort).Sort(measures)
			showMeasures(writer, measures)
			fmt.Fprintln(writer)
		}
	}
}

func (mpd *MiniProfilerData) Step(tag string) {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	now := time.Now()
	thisstep := now.Sub(mpd.lastStep).Nanoseconds()

	mpd.steps[tag] = thisstep
	mpd.lastStep = now
}

func (mpd *MiniProfilerData) Memo(memo string) {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	memo = memoFilter(memo)
	mpd.memos = append(mpd.memos, memo)
}

/*
remove (,|\t|\r|\n)
*/
func memoFilter(memo string) string {
	memo = strings.Replace(memo, ",", "", -1)
	memo = strings.Replace(memo, "\t", "", -1)
	memo = strings.Replace(memo, "\r", "", -1)
	memo = strings.Replace(memo, "\n", "", -1)
	return memo
}

func (mpd *MiniProfilerData) End() {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	mpd.Step("Last Step to End")
	mp.profiles = append(mp.profiles, mpd)
}
<commit_msg>add Begin-description to analyze<commit_after>package miniprofiler

import (
	"fmt"
	"io"
	"math"
	"sort"
	"strings"
	"time"
)

var (
	mp        *MiniProfiler
	enabled   bool
	condition func() bool
)

type MiniProfilerData struct {
	description string
	steps       map[string]int64
	lastStep    time.Time
	memos       []string
}

type MiniProfiler struct {
	profiles []*MiniProfilerData
}

func init() {
	mp = new(MiniProfiler)
	mp.profiles = make([]*MiniProfilerData, 0)
	enabled = true
	condition = func() bool { return true }
}

func Enable() {
	enabled = true
}

func Disable() {
	enabled = false
}

func SetCondition(c func() bool) {
	condition = c
}

func Begin(description string) *MiniProfilerData {
	if !enabled {
		return nil
	}
	if !condition() {
		return nil
	}
	return &MiniProfilerData{description, make(map[string]int64, 0), time.Now(), make([]string, 0)}
}

func Flush(writer io.Writer) {
	for _, prof := range mp.profiles {
		outputs := []string{"log:MP"}

		for tag, val := range prof.steps {
			outputs = append(outputs, fmt.Sprintf("%s:%d", tag, val))
		}

		outputs = append(outputs, fmt.Sprintf("description:%s", prof.description))

		memoOutput := []string{}
		for _, m := range prof.memos {
			memoOutput = append(memoOutput, m)
		}
		outputs = append(outputs, fmt.Sprintf("memo:%s", strings.Join(memoOutput, ",")))

		fmt.Fprintln(writer, strings.Join(outputs, "\t"))
	}
	mp.profiles = make([]*MiniProfilerData, 0)
}

type Measure struct {
	Description string
	Count       int
	Total       int
	Mean        int
	Min         int
	Max         int
}

type By func(a, b *Measure) bool

func (by By) Sort(measures []*Measure) {
	ms := &measureSorter{
		measures: measures,
		by:       by,
	}
	sort.Sort(ms)
}

type measureSorter struct {
	measures []*Measure
	by       func(a, b *Measure) bool
}

func (s *measureSorter) Len() int {
	return len(s.measures)
}

func (s *measureSorter) Swap(i, j int) {
	s.measures[i], s.measures[j] = s.measures[j], s.measures[i]
}

func (s *measureSorter) Less(i, j int) bool {
	return s.by(s.measures[i], s.measures[j])
}

type Column struct {
	Name    string
	Summary string
	Sort    By
}

var (
	columns = []*Column{
		&Column{Name: "Count", Summary: "Count", Sort: func(a, b *Measure) bool { return a.Count > b.Count }},
		&Column{Name: "Total", Summary: "Total", Sort: func(a, b *Measure) bool { return a.Total > b.Total }},
		&Column{Name: "Mean", Summary: "Mean", Sort: func(a, b *Measure) bool { return a.Mean > b.Mean }},
		&Column{Name: "Min"},
		&Column{Name: "Max", Summary: "Maximum(100 Percentile)", Sort: func(a, b *Measure) bool { return a.Max > b.Max }},
	}
)

func getIntegerDigitWidth(i int) int {
	var w int
	switch {
	case i < 1:
		w = 1
	default:
		w = int(math.Log10(float64(i)) + 1)
	}
	return w
}

func showMeasures(writer io.Writer, measures []*Measure) {
	countWidth := 5
	totalWidth := 5
	meanWidth := 5
	maxWidth := 5

	for _, m := range measures {
		var w int
		w = getIntegerDigitWidth(m.Count)
		if countWidth < w {
			countWidth = w
		}
		w = getIntegerDigitWidth(m.Total)
		if totalWidth < w {
			totalWidth = w
		}
		w = getIntegerDigitWidth(m.Mean)
		if meanWidth < w {
			meanWidth = w
		}
		w = getIntegerDigitWidth(m.Max)
		if maxWidth < w {
			maxWidth = w
		}
	}

	var format string
	for _, column := range columns {
		switch column.Name {
		case "Count":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", countWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", countWidth)
		case "Total":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", totalWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", totalWidth)
		case "Mean":
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", meanWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", meanWidth)
		default:
			fmt.Fprintf(writer, fmt.Sprintf("%%%ds  ", maxWidth), column.Name)
			format += fmt.Sprintf("%%%dd  ", maxWidth)
		}
	}
	fmt.Fprintln(writer, "Description")
	format += "%s\n"

	for _, m := range measures {
		fmt.Fprintf(writer, format, m.Count, m.Total, m.Mean, m.Min, m.Max, m.Description)
	}
}

func Analyze(writer io.Writer) {
	var times = make(map[string][]int)
	var totals = make(map[string]int)
	for _, prof := range mp.profiles {
		for tag, val := range prof.steps {
			description := fmt.Sprintf("%s/%s", prof.description, tag)
			times[description] = append(times[description], int(val))
			totals[description] += int(val)
		}
	}
	var measures []*Measure
	for description, times := range times {
		sort.Ints(times)
		count := len(times)
		total := totals[description]
		m := &Measure{
			Description: description,
			Count:       count,
			Total:       total,
			Mean:        total / count,
			Min:         times[0],
			Max:         times[count-1],
		}
		measures = append(measures, m)
	}

	for _, column := range columns {
		if column.Sort != nil {
			fmt.Fprintf(writer, "Sort by %s\n", column.Summary)
			By(column.Sort).Sort(measures)
			showMeasures(writer, measures)
			fmt.Fprintln(writer)
		}
	}
}

func (mpd *MiniProfilerData) Step(tag string) {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	now := time.Now()
	thisstep := now.Sub(mpd.lastStep).Nanoseconds()

	mpd.steps[tag] = thisstep
	mpd.lastStep = now
}

func (mpd *MiniProfilerData) Memo(memo string) {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	memo = memoFilter(memo)
	mpd.memos = append(mpd.memos, memo)
}

/*
remove (,|\t|\r|\n)
*/
func memoFilter(memo string) string {
	memo = strings.Replace(memo, ",", "", -1)
	memo = strings.Replace(memo, "\t", "", -1)
	memo = strings.Replace(memo, "\r", "", -1)
	memo = strings.Replace(memo, "\n", "", -1)
	return memo
}

func (mpd *MiniProfilerData) End() {
	if !enabled {
		return
	}
	if mpd == nil {
		return
	}
	mpd.Step("Last Step to End")
	mp.profiles = append(mp.profiles, mpd)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/mrmorphic/hwio"
	"log"
	"os"
	"os/signal"
	"os/user"
	"time"
)

const (
	TEMP_SENSOR      = "/sys/bus/w1/devices/28-0000061504ee/w1_slave"
	START_TEMP       = 69
	END_TEMP         = 71
	MONITOR_INTERVAL = 30 * time.Second
	TEMP_BUFFER      = 2 // Buffer temp by 2 degrees celsius
)

type Context struct {
	Thermostat  *Thermostat
	Thermometer *Thermometer
}

func buildContext() *Context {
	return &Context{
		Thermostat: &Thermostat{
			On:                false,
			TargetTemperature: 20,
			pin:               openPin(),
		},
		Thermometer: &Thermometer{},
	}
}

func openPin() hwio.Pin {
	hwio.SetDriver(new(hwio.RaspberryPiDTDriver))
	time.Sleep(2 * time.Second)
	pin, err := hwio.GetPinWithMode("gpio17", hwio.OUTPUT)

	if err != nil {
		log.Printf("Error opening pin! %s\n", err)
	}

	time.Sleep(2 * time.Second)
	// PIN OFF ON BOOT
	hwio.DigitalWrite(pin, hwio.HIGH)

	return pin
}

func main() {
	log.Println("Booting termo!")

	currentUser, _ := user.Current()
	log.Printf("User: %s, Group: %s", currentUser.Uid, currentUser.Gid)

	if os.Getenv("API_KEY") != "" {
		log.Printf("Using key %s", os.Getenv("API_KEY"))

		context := buildContext()

		// CLEAN UP
		c := make(chan os.Signal, 1)
		signal.Notify(c, os.Interrupt)
		go func() {
			for sig := range c {
				log.Printf("Caught %v", sig)
				log.Println("Exiting Termo!!")

				context.Thermostat.turnOff()

				hwio.CloseAll()
				os.Exit(1)
			}
		}()

		go monitorRun(context)
		apiRun(context)
	}
}

func monitorRun(context *Context) {
	for {
		context.Thermometer.setCurrentTemp()
		context.Thermostat.adjust(context.Thermometer.CurrentTemp)
		time.Sleep(MONITOR_INTERVAL)
	}
}
<commit_msg>uncomment key support<commit_after>package main

import (
	"github.com/mrmorphic/hwio"
	"log"
	"os"
	"os/signal"
	"time"
)

const (
	TEMP_SENSOR      = "/sys/bus/w1/devices/28-0000061504ee/w1_slave"
	START_TEMP       = 69
	END_TEMP         = 71
	MONITOR_INTERVAL = 30 * time.Second
	TEMP_BUFFER      = 2 // Buffer temp by 2 degrees celsius
)

type Context struct {
	Thermostat  *Thermostat
	Thermometer *Thermometer
}

func buildContext() *Context {
	return &Context{
		Thermostat: &Thermostat{
			On:                false,
			TargetTemperature: 20,
			pin:               openPin(),
		},
		Thermometer: &Thermometer{},
	}
}

func openPin() hwio.Pin {
	hwio.SetDriver(new(hwio.RaspberryPiDTDriver))
	time.Sleep(2 * time.Second)
	pin, err := hwio.GetPinWithMode("gpio17", hwio.OUTPUT)

	if err != nil {
		log.Printf("Error opening pin! %s\n", err)
	}

	time.Sleep(2 * time.Second)
	// PIN OFF ON BOOT
	hwio.DigitalWrite(pin, hwio.HIGH)

	return pin
}

func main() {
	log.Println("Booting termo!")

	// if os.Getenv("API_KEY") != "" {
	// log.Printf("Using key %s", os.Getenv("API_KEY"))

	context := buildContext()

	// CLEAN UP
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			log.Printf("Caught %v", sig)
			log.Println("Exiting Termo!!")

			context.Thermostat.turnOff()

			hwio.CloseAll()
			os.Exit(1)
		}
	}()

	go monitorRun(context)
	apiRun(context)
	// }
}

func monitorRun(context *Context) {
	for {
		context.Thermometer.setCurrentTemp()
		context.Thermostat.adjust(context.Thermometer.CurrentTemp)
		time.Sleep(MONITOR_INTERVAL)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strings"
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

//Exists reports whether the named file or directory exists.
func Exists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func main() {
	args := os.Args[1:]
	if len(args) != 1 {
		log.Fatal("Wrong number of arguments!")
	}

	//Source filename
	source_filename := args[0]

	if !Exists(source_filename) {
		log.Fatal("Specified filename does not exist")
	}

	//Read the lines of the source file into a slice
	lines, er := readLines(source_filename)
	if er != nil {
		log.Fatal(er)
	}

	for _, line := range lines {
		words := strings.Split(line, " ")
		statement := fmt.Sprintf("*%d\r\n", len(words))
		for i := 0; i < len(words); i++ {
			word := words[i]
			statement += fmt.Sprintf("$%d\r\n%s\r\n", len(word), word)
		}
		fmt.Print(statement)
	}
}
<commit_msg>Use flag package instead<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
)

var (
	inputFilename string
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

//Exists reports whether the named file or directory exists.
func Exists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func main() {
	flag.StringVar(&inputFilename, "i", "", "input filename")
	flag.Parse()

	if len(inputFilename) == 0 {
		log.Fatal("Please specify an input filename using the -i option")
	}

	if !Exists(inputFilename) {
		log.Fatal("Specified filename does not exist")
	}

	//Read the lines of the source file into a slice
	lines, er := readLines(inputFilename)
	if er != nil {
		log.Fatal(er)
	}

	for _, line := range lines {
		words := strings.Split(line, " ")
		statement := fmt.Sprintf("*%d\r\n", len(words))
		for i := 0; i < len(words); i++ {
			word := words[i]
			statement += fmt.Sprintf("$%d\r\n%s\r\n", len(word), word)
		}
		fmt.Print(statement)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Qubit Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/sync/errgroup"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	cfgFile = flag.String("config.file", "expexp.yaml", "The path to the configuration file.")

	addr = flag.String("web.listen-address", ":9999", "The address to listen on for HTTP requests.")

	certPath = flag.String("web.tls.cert", "cert.pem", "Path to cert")
	keyPath  = flag.String("web.tls.key", "key.pem", "Path to key")
	caPath   = flag.String("web.tls.ca", "ca.pem", "Path to CA to auth clients against")
	noverify = flag.Bool("web.tls.no-verify", false, "Disable client verification")
	regexStr = flag.String("web.tls.client-regex", ".*", "Regular expression to match against CNs (start and end anchors will be added)")
	tlsAddr  = flag.String("web.tls.listen-address", "", "The address to listen on for HTTPS requests.")

	tPath = flag.String("web.telemetry-path", "/metrics", "The address to listen on for HTTP requests.")
	mPath = flag.String("web.proxy-path", "/proxy", "The address to listen on for HTTP requests.")

	proxyDuration = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Name: "expexp_proxy_duration_seconds",
			Help: "Duration of queries to the yahoo API",
		},
		[]string{"module"},
	)
	proxyErrorCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_proxy_errors_total",
			Help: "Counts of errors",
		},
		[]string{"module"},
	)
	proxyTimeoutCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_proxy_timeout_errors_total",
			Help: "Counts of the number of times a proxy timeout occurred",
		},
		[]string{"module"},
	)

	proxyMalformedCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_malformed_content_errors_total",
			Help: "Counts of unparsable scrape content errors",
		},
		[]string{"module"},
	)
)

func init() {
	// register the collector metrics in the default
	// registry.
	prometheus.MustRegister(proxyDuration)
	prometheus.MustRegister(proxyTimeoutCount)
	prometheus.MustRegister(proxyErrorCount)
	prometheus.MustRegister(proxyMalformedCount)
	prometheus.MustRegister(cmdStartsCount)
	prometheus.MustRegister(cmdFailsCount)
}

func main() {
	flag.Parse()

	r, err := os.Open(*cfgFile)
	if err != nil {
		glog.Fatalf("%+v", err)
	}

	cfg, err := readConfig(r)
	if err != nil {
		glog.Fatalf("%+v", err)
	}

	http.HandleFunc("/proxy", cfg.doProxy)
	http.Handle("/metrics", promhttp.Handler())

	eg, ctx := errgroup.WithContext(context.Background())

	if *addr != "" {
		eg.Go(func() error {
			return http.ListenAndServe(*addr, nil)
		})
	}

	if *tlsAddr != "" {
		eg.Go(func() error {
			cert, err := tls.LoadX509KeyPair(*certPath, *keyPath)
			if err != nil {
				glog.Fatalf("Could not parse key/cert, " + err.Error())
			}

			cabs, err := ioutil.ReadFile(*caPath)
			if err != nil {
				glog.Fatalf("Could not open ca file,, " + err.Error())
			}
			pool := x509.NewCertPool()
			ok := pool.AppendCertsFromPEM(cabs)
			if !ok {
				glog.Fatalf("Failed loading ca certs")
			}

			tlsConfig := tls.Config{
				Certificates: []tls.Certificate{cert},
				RootCAs:      pool,
			}
			tlsConfig.BuildNameToCertificate()

			if !*noverify {
				tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
				tlsConfig.ClientCAs = pool
			}

			srvr := http.Server{
				Addr:      *tlsAddr,
				TLSConfig: &tlsConfig,
			}
			return srvr.ListenAndServeTLS(*certPath, *keyPath)
		})
	}

	<-ctx.Done()
	log.Fatal(ctx.Err())
}

func (cfg *config) doProxy(w http.ResponseWriter, r *http.Request) {
	mod, ok := r.URL.Query()["module"]
	if !ok {
		glog.Infof("no module given")
		return
	}

	if len(mod) != 1 {
		glog.Infof("you must pass exactly one module parameter")
		return
	}

	if glog.V(3) {
		glog.Infof("running module %v\n", mod)
	}

	var h http.Handler
	if m, ok := cfg.Modules[mod[0]]; !ok {
		proxyErrorCount.WithLabelValues("unknown").Inc()
		glog.Infof("unknown module requested  %v\n", mod)
		http.Error(w, fmt.Sprintf("unknown module %v\n", mod), http.StatusNotFound)
		return
	} else {
		m.name = mod[0]
		h = m
	}

	h.ServeHTTP(w, r)
}

func (m moduleConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	st := time.Now()
	defer func() {
		proxyDuration.WithLabelValues(m.name).Observe(float64(time.Since(st)) / float64(time.Second))
	}()

	nr := r
	cancel := func() {}
	if m.Timeout != 0 {
		if glog.V(3) {
			glog.Infof("setting module %v timeout to %v", m.name, m.Timeout)
		}

		var ctx context.Context
		ctx, cancel = context.WithTimeout(r.Context(), m.Timeout)
		nr = r.WithContext(ctx)
	}
	defer cancel()

	switch m.Method {
	case "exec":
		m.Exec.mcfg = &m
		m.Exec.ServeHTTP(w, nr)
	case "http":
		m.HTTP.mcfg = &m
		m.HTTP.ServeHTTP(w, nr)
	default:
		glog.Infof("unknown module method  %v\n", m.Method)
		proxyErrorCount.WithLabelValues(m.name).Inc()
		http.Error(w, fmt.Sprintf("unknown module method %v\n", m.Method), http.StatusNotFound)
		return
	}
}
<commit_msg>Exit if there is nothing to do<commit_after>// Copyright 2016 Qubit Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/sync/errgroup"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	cfgFile = flag.String("config.file", "expexp.yaml", "The path to the configuration file.")

	addr = flag.String("web.listen-address", ":9999", "The address to listen on for HTTP requests.")

	certPath = flag.String("web.tls.cert", "cert.pem", "Path to cert")
	keyPath  = flag.String("web.tls.key", "key.pem", "Path to key")
	caPath   = flag.String("web.tls.ca", "ca.pem", "Path to CA to auth clients against")
	noverify = flag.Bool("web.tls.no-verify", false, "Disable client verification")
	regexStr = flag.String("web.tls.client-regex", ".*", "Regular expression to match against CNs (start and end anchors will be added)")
	tlsAddr  = flag.String("web.tls.listen-address", "", "The address to listen on for HTTPS requests.")

	tPath = flag.String("web.telemetry-path", "/metrics", "The address to listen on for HTTP requests.")
	mPath = flag.String("web.proxy-path", "/proxy", "The address to listen on for HTTP requests.")

	proxyDuration = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Name: "expexp_proxy_duration_seconds",
			Help: "Duration of queries to the yahoo API",
		},
		[]string{"module"},
	)
	proxyErrorCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_proxy_errors_total",
			Help: "Counts of errors",
		},
		[]string{"module"},
	)
	proxyTimeoutCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_proxy_timeout_errors_total",
			Help: "Counts of the number of times a proxy timeout occurred",
		},
		[]string{"module"},
	)

	proxyMalformedCount = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "expexp_malformed_content_errors_total",
			Help: "Counts of unparsable scrape content errors",
		},
		[]string{"module"},
	)
)

func init() {
	// register the collector metrics in the default
	// registry.
	prometheus.MustRegister(proxyDuration)
	prometheus.MustRegister(proxyTimeoutCount)
	prometheus.MustRegister(proxyErrorCount)
	prometheus.MustRegister(proxyMalformedCount)
	prometheus.MustRegister(cmdStartsCount)
	prometheus.MustRegister(cmdFailsCount)
}

func main() {
	flag.Parse()

	r, err := os.Open(*cfgFile)
	if err != nil {
		glog.Fatalf("%+v", err)
	}

	cfg, err := readConfig(r)
	if err != nil {
		glog.Fatalf("%+v", err)
	}

	http.HandleFunc("/proxy", cfg.doProxy)
	http.Handle("/metrics", promhttp.Handler())

	eg, ctx := errgroup.WithContext(context.Background())

	if *addr == "" && *tlsAddr == "" {
		glog.Info("No web addresses to listen on, nothing to do!")
		os.Exit(0)
	}

	if *addr != "" {
		eg.Go(func() error {
			return http.ListenAndServe(*addr, nil)
		})
	}

	if *tlsAddr != "" {
		eg.Go(func() error {
			cert, err := tls.LoadX509KeyPair(*certPath, *keyPath)
			if err != nil {
				glog.Fatalf("Could not parse key/cert, " + err.Error())
			}

			cabs, err := ioutil.ReadFile(*caPath)
			if err != nil {
				glog.Fatalf("Could not open ca file,, " + err.Error())
			}
			pool := x509.NewCertPool()
			ok := pool.AppendCertsFromPEM(cabs)
			if !ok {
				glog.Fatalf("Failed loading ca certs")
			}

			tlsConfig := tls.Config{
				Certificates: []tls.Certificate{cert},
				RootCAs:      pool,
			}
			tlsConfig.BuildNameToCertificate()

			if !*noverify {
				tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
				tlsConfig.ClientCAs = pool
			}

			srvr := http.Server{
				Addr:      *tlsAddr,
				TLSConfig: &tlsConfig,
			}
			return srvr.ListenAndServeTLS(*certPath, *keyPath)
		})
	}

	<-ctx.Done()
	log.Fatal(ctx.Err())
}

func (cfg *config) doProxy(w http.ResponseWriter, r *http.Request) {
	mod, ok := r.URL.Query()["module"]
	if !ok {
		glog.Infof("no module given")
		return
	}

	if len(mod) != 1 {
		glog.Infof("you must pass exactly one module parameter")
		return
	}

	if glog.V(3) {
		glog.Infof("running module %v\n", mod)
	}

	var h http.Handler
	if m, ok := cfg.Modules[mod[0]]; !ok {
		proxyErrorCount.WithLabelValues("unknown").Inc()
		glog.Infof("unknown module requested  %v\n", mod)
		http.Error(w, fmt.Sprintf("unknown module %v\n", mod), http.StatusNotFound)
		return
	} else {
		m.name = mod[0]
		h = m
	}

	h.ServeHTTP(w, r)
}

func (m moduleConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	st := time.Now()
	defer func() {
		proxyDuration.WithLabelValues(m.name).Observe(float64(time.Since(st)) / float64(time.Second))
	}()

	nr := r
	cancel := func() {}
	if m.Timeout != 0 {
		if glog.V(3) {
			glog.Infof("setting module %v timeout to %v", m.name, m.Timeout)
		}

		var ctx context.Context
		ctx, cancel = context.WithTimeout(r.Context(), m.Timeout)
		nr = r.WithContext(ctx)
	}
	defer cancel()

	switch m.Method {
	case "exec":
		m.Exec.mcfg = &m
		m.Exec.ServeHTTP(w, nr)
	case "http":
		m.HTTP.mcfg = &m
		m.HTTP.ServeHTTP(w, nr)
	default:
		glog.Infof("unknown module method  %v\n", m.Method)
		proxyErrorCount.WithLabelValues(m.name).Inc()
		http.Error(w, fmt.Sprintf("unknown module method %v\n", m.Method), http.StatusNotFound)
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
  "flag"
  log "github.com/Sirupsen/logrus"
  "github.com/go-ini/ini"
  "io/ioutil"
  "strings"
)

type Config struct {
  BaseUrl string
  Username string
  Password string
}
var config Config = getConfig()
var allTemplates map[string]interface{}
var allPipelines []interface{}
func getPipelines(filename string) {
  data, err := parseFile(filename)

  if err != nil {
    log.WithFields(log.Fields{
      "error":    err.Error(),
      "filename": filename,
    }).Error("Unable to parse pipeline file")
    return
  }
  templates := data.(map[string]interface{})["templates"]
  pipelines := data.(map[string]interface{})["pipelines"]

  if templates != nil {
    for k,v := range templates.(map[string]interface {}) {
      allTemplates[k] = v.(map[string]interface {})["pipeline"]
    }
  }
  for _, v := range pipelines.([]interface{}){
    allPipelines = append(allPipelines, v.(map[string]interface{}))
  }

}

func processPipelines() {
  for _, p := range allPipelines{
    processPipeline(p.(map[string]interface{}))
  }
}

func processPipeline(pipeline map[string]interface{}) {
  var template map[string]interface{}
  if pipeline["pipeline_template"] != nil {
    template = allTemplates[pipeline["pipeline_template"].(string)].(map[string]interface{})
  }
  pipelineConf := pipeline["pipeline"].(map[string]interface{})
  if template != nil {
    pipeline["pipeline"] = merge(template, pipelineConf)

  }
  createOrEditPipeline(pipeline)
}

func main() {

  files, _ := ioutil.ReadDir(".")
  for _, f := range files {

		if f.IsDir() {
			continue
		}
    if !strings.HasSuffix(f.Name(),".yml") {
      continue
    }
    getPipelines(f.Name())
  }
  processPipelines()

}

func getConfig() Config{
  config_file := flag.String("config", "/etc/gocd-plumber/config.ini", "Config file path")
  debug_option := flag.Bool("debug", false, "Verbose debug output")
  flag.Parse()
  if *debug_option {
     log.SetLevel(log.DebugLevel)
  }
  inifile, err := ini.Load(*config_file)
  if err != nil {
    log.WithFields(log.Fields{
      "error": err.Error(),
    }).Fatal("Unable to open config file")
  }
  var config Config
  err = inifile.MapTo(&config)
  if err != nil {
    log.WithFields(log.Fields{
      "error": err.Error(),
    }).Fatal("Unable to parse config file")
  }
  return config
}

func init(){
  allTemplates = make(map[string]interface{})
}
<commit_msg>Default config file location<commit_after>package main

import (
  "flag"
  log "github.com/Sirupsen/logrus"
  "github.com/go-ini/ini"
  "io/ioutil"
  "strings"
)

type Config struct {
  BaseUrl string
  Username string
  Password string
}
var config Config = getConfig()
var allTemplates map[string]interface{}
var allPipelines []interface{}
func getPipelines(filename string) {
  data, err := parseFile(filename)

  if err != nil {
    log.WithFields(log.Fields{
      "error":    err.Error(),
      "filename": filename,
    }).Error("Unable to parse pipeline file")
    return
  }
  templates := data.(map[string]interface{})["templates"]
  pipelines := data.(map[string]interface{})["pipelines"]

  if templates != nil {
    for k,v := range templates.(map[string]interface {}) {
      allTemplates[k] = v.(map[string]interface {})["pipeline"]
    }
  }
  for _, v := range pipelines.([]interface{}){
    allPipelines = append(allPipelines, v.(map[string]interface{}))
  }

}

func processPipelines() {
  for _, p := range allPipelines{
    processPipeline(p.(map[string]interface{}))
  }
}

func processPipeline(pipeline map[string]interface{}) {
  var template map[string]interface{}
  if pipeline["pipeline_template"] != nil {
    template = allTemplates[pipeline["pipeline_template"].(string)].(map[string]interface{})
  }
  pipelineConf := pipeline["pipeline"].(map[string]interface{})
  if template != nil {
    pipeline["pipeline"] = merge(template, pipelineConf)

  }
  createOrEditPipeline(pipeline)
}

func main() {

  files, _ := ioutil.ReadDir(".")
  for _, f := range files {

		if f.IsDir() {
			continue
		}
    if !strings.HasSuffix(f.Name(),".yml") {
      continue
    }
    getPipelines(f.Name())
  }
  processPipelines()

}

func getConfig() Config{
  config_file := flag.String("config", "root/etc/gocd-plumber/config.ini", "Config file path")
  debug_option := flag.Bool("debug", false, "Verbose debug output")
  flag.Parse()
  if *debug_option {
     log.SetLevel(log.DebugLevel)
  }
  inifile, err := ini.Load(*config_file)
  if err != nil {
    log.WithFields(log.Fields{
      "error": err.Error(),
    }).Fatal("Unable to open config file")
  }
  var config Config
  err = inifile.MapTo(&config)
  if err != nil {
    log.WithFields(log.Fields{
      "error": err.Error(),
    }).Fatal("Unable to parse config file")
  }
  return config
}

func init(){
  allTemplates = make(map[string]interface{})
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/gcfg"
	"flag"
	"github.com/boredomist/mixport/mixpanel"
	"github.com/boredomist/mixport/streaming"
	"log"
	"path"
	"runtime"
	"sync"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON struct {
		State     bool
		Directory string
	}

	CSV struct {
		State     bool
		Directory string
	}
}

const (
	defaultConfig = "mixport.conf"
	defaultDate   = ""
)

var configFile string
var dateString string

func init() {
	// XXX: This one goes to 11.
	runtime.GOMAXPROCS(runtime.NumCPU() * 5)

	const (
		confUsage = "path to configuration file"
		dateUsage = "date (YYYY-MM-DD) of data to pull, default is yesterday"
	)
	flag.StringVar(&configFile, "config", defaultConfig, confUsage)
	flag.StringVar(&configFile, "c", defaultConfig, confUsage)
	flag.StringVar(&dateString, "date", defaultDate, dateUsage)
	flag.StringVar(&dateString, "d", defaultDate, dateUsage)
}

func main() {
	flag.Parse()

	cfg := configFormat{}
	if err := gcfg.ReadFileInto(&cfg, configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", configFile, err)
	}

	var exportDate time.Time

	// Default to yesterday (should be newest available data)
	if dateString == "" {
		exportDate = time.Now().UTC().AddDate(0, 0, -1)
	} else {
		if d, err := time.Parse("2006-01-02", dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY-MM-DD format",
				dateString)
		} else {
			exportDate = d
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range cfg.Product {
		// Run each individual product in a new thread.
		go func(product string, creds mixpanelCredentials) {
			defer wg.Done()

			client := mixpanel.New(product, creds.Key, creds.Secret)
			eventData := make(chan mixpanel.EventData)

			// We need to mux eventData into multiple channels
			var chans []chan mixpanel.EventData

			if cfg.Kinesis.State {
				// TODO: Call kinesis
				// append(chans, make(chan mixpanel.EventData))
			}

			if cfg.JSON.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(cfg.JSON.Directory, product+".json")
				go streaming.JSONStreamer(name, ch)
			}

			if cfg.CSV.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(cfg.JSON.Directory, product+".csv")
				go streaming.CSVStreamer(name, ch)
			}

			// FIXME: need to be able to change dates
			go client.ExportDate(exportDate, eventData, nil)

			for data := range eventData {
				for _, ch := range chans {
					ch <- data
				}
			}

			for _, ch := range chans {
				close(ch)
			}

			// XXX: It's completely possible for execution to die
			// here before all of the channels have time to finish
			// processing. Need another waitgroup, maybe
		}(product, *creds)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()
}
<commit_msg>Remove outdated comment<commit_after>package main

import (
	"code.google.com/p/gcfg"
	"flag"
	"github.com/boredomist/mixport/mixpanel"
	"github.com/boredomist/mixport/streaming"
	"log"
	"path"
	"runtime"
	"sync"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON struct {
		State     bool
		Directory string
	}

	CSV struct {
		State     bool
		Directory string
	}
}

const (
	defaultConfig = "mixport.conf"
	defaultDate   = ""
)

var configFile string
var dateString string

func init() {
	// XXX: This one goes to 11.
	runtime.GOMAXPROCS(runtime.NumCPU() * 5)

	const (
		confUsage = "path to configuration file"
		dateUsage = "date (YYYY-MM-DD) of data to pull, default is yesterday"
	)
	flag.StringVar(&configFile, "config", defaultConfig, confUsage)
	flag.StringVar(&configFile, "c", defaultConfig, confUsage)
	flag.StringVar(&dateString, "date", defaultDate, dateUsage)
	flag.StringVar(&dateString, "d", defaultDate, dateUsage)
}

func main() {
	flag.Parse()

	cfg := configFormat{}
	if err := gcfg.ReadFileInto(&cfg, configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", configFile, err)
	}

	var exportDate time.Time

	// Default to yesterday (should be newest available data)
	if dateString == "" {
		exportDate = time.Now().UTC().AddDate(0, 0, -1)
	} else {
		if d, err := time.Parse("2006-01-02", dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY-MM-DD format",
				dateString)
		} else {
			exportDate = d
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range cfg.Product {
		// Run each individual product in a new thread.
		go func(product string, creds mixpanelCredentials) {
			defer wg.Done()

			client := mixpanel.New(product, creds.Key, creds.Secret)
			eventData := make(chan mixpanel.EventData)

			// We need to mux eventData into multiple channels
			var chans []chan mixpanel.EventData

			if cfg.Kinesis.State {
				// TODO: Call kinesis
				// append(chans, make(chan mixpanel.EventData))
			}

			if cfg.JSON.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(cfg.JSON.Directory, product+".json")
				go streaming.JSONStreamer(name, ch)
			}

			if cfg.CSV.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(cfg.JSON.Directory, product+".csv")
				go streaming.CSVStreamer(name, ch)
			}

			go client.ExportDate(exportDate, eventData, nil)

			for data := range eventData {
				for _, ch := range chans {
					ch <- data
				}
			}

			for _, ch := range chans {
				close(ch)
			}

			// XXX: It's completely possible for execution to die
			// here before all of the channels have time to finish
			// processing. Need another waitgroup, maybe
		}(product, *creds)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()
}
<|endoftext|>