<commit_before>package main

import (
	"encoding/json"
	"errors"
	_ "expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	_ "net/http/pprof"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var queryCache bytesCache
var findCache bytesCache

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")
	useCache := r.FormValue("noCache") == ""

	// make sure the cache key doesn't say noCache, because it will never hit
	r.Form.Del("noCache")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); useCache && ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response)
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse

			if response, ok := findCache.get(metric); ok {
				proto.Unmarshal(response, &glob)
			} else {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				b, err := proto.Marshal(&glob)
				if err == nil {
					findCache.set(metric, b)
				}
			}

			// For each metric returned in the Find response, query Render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			leaves := 0
			for _, m := range glob.GetMatches() {
				if !m.GetIsLeaf() {
					continue
				}
				leaves++
				Limiter.enter()
				go func(m *pb.GlobMatch) {
					var rptr *pb.FetchResponse
					r, err := Zipper.Render(m.GetPath(), from, until)
					if err == nil {
						rptr = &r
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < leaves; i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	queryCache = &expireCache{cache: make(map[string]cacheElement)}
	go queryCache.(*expireCache).cleaner()

	findCache = &expireCache{cache: make(map[string]cacheElement)}
	go findCache.(*expireCache).cleaner()

	Zipper = zipper(*z)

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<commit_msg>Make noCache disable findCache as well.<commit_after>package main

import (
	"encoding/json"
	"errors"
	_ "expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	_ "net/http/pprof"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"

	"code.google.com/p/gogoprotobuf/proto"

	pb "github.com/dgryski/carbonzipper/carbonzipperpb"
)

type zipper string

var Zipper zipper

var queryCache bytesCache
var findCache bytesCache

var timeFormats = []string{"15:04 20060102", "20060102", "01/02/06"}

// dateParamToEpoch turns a passed string parameter into an epoch we can send to the Zipper
func dateParamToEpoch(s string, d int64) string {

	if s == "" {
		// return the default if nothing was passed
		return strconv.Itoa(int(d))
	}

	// relative timestamp
	if s[0] == '-' {

		offset, err := intervalString(s[1:])
		if err != nil {
			return strconv.Itoa(int(d))
		}

		return strconv.Itoa(int(timeNow().Add(-time.Duration(offset) * time.Second).Unix()))
	}

	_, err := strconv.Atoi(s)
	if err == nil && len(s) > 8 {
		return s // We got a timestamp so returning it
	}

	if strings.Contains(s, "_") {
		s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings
	}

	for _, format := range timeFormats {
		t, err := time.Parse(format, s)
		if err == nil {
			return strconv.Itoa(int(t.Unix()))
		}
	}
	return strconv.Itoa(int(d))
}

func intervalString(s string) (int32, error) {

	var j int

	for j < len(s) && s[j] >= '0' && s[j] <= '9' {
		j++
	}
	offsetStr, unitStr := s[:j], s[j:]

	var units int
	switch unitStr {
	case "s", "sec", "secs", "second", "seconds":
		units = 1
	case "min", "minute", "minutes":
		units = 60
	case "h", "hour", "hours":
		units = 60 * 60
	case "d", "day", "days":
		units = 24 * 60 * 60
	case "w", "week", "weeks":
		units = 7 * 24 * 60 * 60
	case "mon", "month", "months":
		units = 30 * 24 * 60 * 60
	case "y", "year", "years":
		units = 365 * 24 * 60 * 60
	default:
		return 0, errors.New("unknown time units")
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		return 0, err
	}

	return int32(offset * units), nil
}

// FIXME(dgryski): extract the http.Get + unproto code into its own function

func (z zipper) Find(metric string) (pb.GlobResponse, error) {

	u, _ := url.Parse(string(z) + "/metrics/find/")

	u.RawQuery = url.Values{
		"query":  []string{metric},
		"format": []string{"protobuf"},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Find: http.Get: %+v\n", err)
		return pb.GlobResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Find: ioutil.ReadAll: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	var pbresp pb.GlobResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Find: proto.Unmarshal: %+v\n", err)
		return pb.GlobResponse{}, err
	}

	return pbresp, nil
}

func (z zipper) Render(metric, from, until string) (pb.FetchResponse, error) {

	u, _ := url.Parse(string(z) + "/render/")

	u.RawQuery = url.Values{
		"target": []string{metric},
		"format": []string{"protobuf"},
		"from":   []string{from},
		"until":  []string{until},
	}.Encode()

	resp, err := http.Get(u.String())
	if err != nil {
		log.Printf("Render: http.Get: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Render: ioutil.ReadAll: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	var pbresp pb.FetchResponse

	err = proto.Unmarshal(body, &pbresp)
	if err != nil {
		log.Printf("Render: proto.Unmarshal: %s: %+v\n", metric, err)
		return pb.FetchResponse{}, err
	}

	return pbresp, nil
}

type limiter chan struct{}

func (l limiter) enter() { l <- struct{}{} }
func (l limiter) leave() { <-l }

var Limiter limiter

// for testing
var timeNow = time.Now

type graphitePoint struct {
	value float64
	t     int32
}

func (g graphitePoint) MarshalJSON() ([]byte, error) {
	// TODO(dgryski): fmt.Sprintf() is slow, use strconv.Append{Float,Int}
	if math.IsNaN(g.value) {
		return []byte(fmt.Sprintf("[null,%d]", g.t)), nil
	}
	return []byte(fmt.Sprintf("[%g,%d]", g.value, g.t)), nil
}

type jsonResponse struct {
	Target     string          `json:"target"`
	Datapoints []graphitePoint `json:"datapoints"`
}

func renderHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	targets := r.Form["target"]
	from := r.FormValue("from")
	until := r.FormValue("until")
	useCache := r.FormValue("noCache") == ""

	// make sure the cache key doesn't say noCache, because it will never hit
	r.Form.Del("noCache")

	cacheKey := r.Form.Encode()

	if response, ok := queryCache.get(cacheKey); useCache && ok {
		w.Header().Set("Content-Type", "application/json")
		w.Write(response)
		return
	}

	// normalize from and until values
	from = dateParamToEpoch(from, timeNow().Add(-24*time.Hour).Unix())
	until = dateParamToEpoch(until, timeNow().Unix())

	var results []*pb.FetchResponse

	for _, target := range targets {

		exp, e, err := parseExpr(target)
		if err != nil || e != "" {
			http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
			return
		}

		metricMap := make(map[string][]*pb.FetchResponse)

		for _, metric := range exp.metrics() {

			var glob pb.GlobResponse
			var haveCacheData bool

			if response, ok := findCache.get(metric); useCache && ok {
				err := proto.Unmarshal(response, &glob)
				haveCacheData = err == nil
			}

			if !haveCacheData {
				var err error
				glob, err = Zipper.Find(metric)
				if err != nil {
					continue
				}
				b, err := proto.Marshal(&glob)
				if err == nil {
					findCache.set(metric, b)
				}
			}

			// For each metric returned in the Find response, query Render
			rch := make(chan *pb.FetchResponse, len(glob.GetMatches()))
			leaves := 0
			for _, m := range glob.GetMatches() {
				if !m.GetIsLeaf() {
					continue
				}
				leaves++
				Limiter.enter()
				go func(m *pb.GlobMatch) {
					var rptr *pb.FetchResponse
					r, err := Zipper.Render(m.GetPath(), from, until)
					if err == nil {
						rptr = &r
					}
					rch <- rptr
					Limiter.leave()
				}(m)
			}

			for i := 0; i < leaves; i++ {
				r := <-rch
				if r != nil {
					metricMap[metric] = append(metricMap[metric], r)
				}
			}
		}

		exprs := evalExpr(exp, metricMap)
		results = append(results, exprs...)
	}

	var jresults []jsonResponse

	for _, r := range results {
		if r == nil {
			log.Println("skipping nil result")
		}
		datapoints := make([]graphitePoint, 0, len(r.Values))
		t := *r.StartTime
		for i, v := range r.Values {
			if r.IsAbsent[i] {
				v = math.NaN()
			}
			datapoints = append(datapoints, graphitePoint{value: v, t: t})
			t += *r.StepTime
		}
		jresults = append(jresults, jsonResponse{Target: r.GetName(), Datapoints: datapoints})
	}

	jout, err := json.Marshal(jresults)
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	queryCache.set(cacheKey, jout)

	w.Header().Set("Content-Type", "application/json")
	w.Write(jout)
}

func main() {

	z := flag.String("z", "", "zipper")
	port := flag.Int("p", 8080, "port")
	l := flag.Int("l", 20, "concurrency limit")

	flag.Parse()

	if *z == "" {
		log.Fatal("no zipper (-z) provided")
	}

	if p := os.Getenv("PORT"); p != "" {
		*port, _ = strconv.Atoi(p)
	}

	Limiter = make(chan struct{}, *l)

	if *z == "" {
		log.Fatal("no zipper provided")
	}

	if _, err := url.Parse(*z); err != nil {
		log.Fatal("unable to parze zipper:", err)
	}

	log.Println("using zipper", *z)

	queryCache = &expireCache{cache: make(map[string]cacheElement)}
	go queryCache.(*expireCache).cleaner()

	findCache = &expireCache{cache: make(map[string]cacheElement)}
	go findCache.(*expireCache).cleaner()

	Zipper = zipper(*z)

	http.HandleFunc("/render/", renderHandler)

	log.Println("listening on port", *port)
	log.Fatalln(http.ListenAndServe(":"+strconv.Itoa(*port), nil))

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
)

func main() {
	index, err := ioutil.ReadFile("assets/index.html")
	if err != nil {
		log.Fatal(err)
	}

	r := httprouter.New()
	r.GET("/assets/*file", serveFile)
	r.GET("/index", func(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
		w.Header().Add("Content-Type", "text/html")
		w.Write(index)
	})

	r.GET("/api/entries", listEntries)

	err = http.ListenAndServe(":8081", r)
	if err != nil {
		log.Fatal(err)
	}
}

func serveFile(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
	file := p.ByName("file")

	b, err := ioutil.ReadFile("assets/" + file)
	if err != nil {
		log.Printf("Could not read file %s\n", err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	var contentType string
	if strings.HasSuffix(file, ".html") {
		contentType = "text/html"
	} else if strings.HasSuffix(file, ".css") {
		contentType = "text/css"
	} else if strings.HasSuffix(file, ".js") {
		contentType = "application/javascript"
	} else {
		log.Printf("Could not determine content type %s\n", file)
	}

	w.Header().Add("Content-Type", contentType)
	w.Write(b)
}

type entry struct {
	Broker     string    `json:"broker"`
	TripNumber int       `json:"trip_number"`
	Date       time.Time `json:"date"`
}

func listEntries(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	w.Header().Add("Content-Type", "application/json")

	e := []entry{
		entry{Broker: "Joe", TripNumber: 1, Date: <-time.After(time.Second)},
		entry{Broker: "Toe", TripNumber: 2, Date: <-time.After(time.Second)},
		entry{Broker: "Moe", TripNumber: 3, Date: <-time.After(time.Second)},
	}

	if err := json.NewEncoder(w).Encode(&e); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		log.Println("Error encoding: %s\n", err)
	}
}
<commit_msg>changing removing /index route and having that display at root<commit_after>package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
)

func main() {
	index, err := ioutil.ReadFile("assets/index.html")
	if err != nil {
		log.Fatal(err)
	}

	r := httprouter.New()
	r.GET("/assets/*file", serveFile)
	r.GET("/", func(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
		w.Header().Add("Content-Type", "text/html")
		w.Write(index)
	})

	r.GET("/api/entries", listEntries)

	err = http.ListenAndServe(":8081", r)
	if err != nil {
		log.Fatal(err)
	}
}

func serveFile(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
	file := p.ByName("file")

	b, err := ioutil.ReadFile("assets/" + file)
	if err != nil {
		log.Printf("Could not read file %s\n", err)
		w.WriteHeader(http.StatusNotFound)
		return
	}

	var contentType string
	if strings.HasSuffix(file, ".html") {
		contentType = "text/html"
	} else if strings.HasSuffix(file, ".css") {
		contentType = "text/css"
	} else if strings.HasSuffix(file, ".js") {
		contentType = "application/javascript"
	} else {
		log.Printf("Could not determine content type %s\n", file)
	}

	w.Header().Add("Content-Type", contentType)
	w.Write(b)
}

type entry struct {
	Broker     string    `json:"broker"`
	TripNumber int       `json:"trip_number"`
	Date       time.Time `json:"date"`
}

func listEntries(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	w.Header().Add("Content-Type", "application/json")

	e := []entry{
		entry{Broker: "Joe", TripNumber: 1, Date: <-time.After(time.Second)},
		entry{Broker: "Toe", TripNumber: 2, Date: <-time.After(time.Second)},
		entry{Broker: "Moe", TripNumber: 3, Date: <-time.After(time.Second)},
	}

	if err := json.NewEncoder(w).Encode(&e); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		log.Println("Error encoding: %s\n", err)
	}
}
<|endoftext|>


<commit_before>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package main

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/fatih/color"
	"github.com/mattn/go-isatty"
	"gopkg.in/urfave/cli.v1"
)

var isTTY = isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())

func main() {
	// This won't be needed in cli v2
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help"
	cli.HelpFlag.Hidden = true

	app := cli.NewApp()
	app.Name = "k6"
	app.Usage = "a next generation load generator"
	app.Version = "0.13.0"
	app.Commands = []cli.Command{
		commandRun,
		commandInspect,
		commandStatus,
		commandStats,
		commandScale,
		commandPause,
		commandResume,
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "show debug messages",
		},
		cli.StringFlag{
			Name:   "address, a",
			Usage:  "address for the API",
			Value:  "127.0.0.1:6565",
			EnvVar: "K6_ADDRESS",
		},
		cli.BoolFlag{
			Name:   "no-color, n",
			Usage:  "disable colored output",
			EnvVar: "K6_NO_COLOR",
		},
	}
	app.Before = func(cc *cli.Context) error {
		if cc.Bool("verbose") {
			log.SetLevel(log.DebugLevel)
		}
		if cc.Bool("no-color") {
			color.NoColor = true
		}

		return nil
	}
	if err := app.Run(os.Args); err != nil {
		os.Exit(1)
	}
}
<commit_msg>v0.14.0<commit_after>/*
 *
 * k6 - a next-generation load testing tool
 * Copyright (C) 2016 Load Impact
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package main

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/fatih/color"
	"github.com/mattn/go-isatty"
	"gopkg.in/urfave/cli.v1"
)

var isTTY = isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())

func main() {
	// This won't be needed in cli v2
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help"
	cli.HelpFlag.Hidden = true

	app := cli.NewApp()
	app.Name = "k6"
	app.Usage = "a next generation load generator"
	app.Version = "0.14.0"
	app.Commands = []cli.Command{
		commandRun,
		commandInspect,
		commandStatus,
		commandStats,
		commandScale,
		commandPause,
		commandResume,
	}
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "show debug messages",
		},
		cli.StringFlag{
			Name:   "address, a",
			Usage:  "address for the API",
			Value:  "127.0.0.1:6565",
			EnvVar: "K6_ADDRESS",
		},
		cli.BoolFlag{
			Name:   "no-color, n",
			Usage:  "disable colored output",
			EnvVar: "K6_NO_COLOR",
		},
	}
	app.Before = func(cc *cli.Context) error {
		if cc.Bool("verbose") {
			log.SetLevel(log.DebugLevel)
		}
		if cc.Bool("no-color") {
			color.NoColor = true
		}

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


<commit_before>package main

import (
	"os"
)

func main() {
	command := "help"
	if len(os.Args) >= 2 {
		command = os.Args[1]
	}
	switch(command) {
	case "help":
		a := "help"
		if len(os.Args) >= 3 {
			a = os.Args[2]
		}
		help(a)
	case "put":
		put()
	case "get":
		get()
	case "mkchain":
		mkchain()
	}
}

//import (
//	"encoding/hex"
//	"encoding/json"
//	"flag"
//	"fmt"
//	"net/http"
//	"net/url"
//	"os"
//)
//const usage = "factom -s [server] -c [chainid] -e [extid] -e [extid2] <data"
//
//type entry struct {
//	ChainID string
//	ExtIDs  []string
//	Data    string
//}
//
//type extids []string
//
//func (e *extids) String() string {
//	return fmt.Sprint(*e)
//}
//
//func (e *extids) Set(s string) error {
//	*e = append(*e, s)
//	return nil
//}
//
//func main() {
//	var (
//		help = flag.Bool("h", false, usage)
//		cid  = flag.String("c", "", "hex encoded chainid for the entry")
//		serv = flag.String("s", "localhost:8088", "path to the factomclient")
//		eids extids
//	)
//
//	flag.Var(&eids, "e", "external id for the entry")
//	flag.Parse()
//
//	if *help {
//		fmt.Println(usage)
//		return
//	}
//
//	server := "http://" + *serv + "/v1/submitentry"
//
//	fmt.Println(server)
//
//	d := make([]byte, 1024)
//	n, _ := os.Stdin.Read(d)
//	d = d[:n]
//
//	e := new(entry)
//	e.ChainID = *cid
//	for _, v := range eids {
//		e.ExtIDs = append(e.ExtIDs, string(v))
//	}
//	e.Data = hex.EncodeToString(d)
//
//	b, err := json.Marshal(e)
//	if err != nil {
//		return
//	}
//
//	data := url.Values{
//		"datatype": {"entry"},
//		"format":   {"json"},
//		"entry":    {string(b)},
//	}
//
//	_, err = http.PostForm(server, data)
//	if err != nil {
//		fmt.Println("Error: ", err)
//	}
//
//	return
//}
<commit_msg>main.go: removed old commented code<commit_after>package main

import (
	"os"
)

func main() {
	command := "help"
	if len(os.Args) >= 2 {
		command = os.Args[1]
	}
	switch(command) {
	case "help":
		a := "help"
		if len(os.Args) >= 3 {
			a = os.Args[2]
		}
		help(a)
	case "put":
		put()
	case "get":
		get()
	case "mkchain":
		mkchain()
	}
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Package membership:
//-----------------------------------------------------------------------------

package main

//-----------------------------------------------------------------------------
// Package factored import statement:
//-----------------------------------------------------------------------------

import (

	// Standard library:
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"text/template"

	// Community:
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/packethost/packngo"
	"gopkg.in/alecthomas/kingpin.v2"
)

//----------------------------------------------------------------------------
// Typedefs:
//----------------------------------------------------------------------------

type Udata struct {
	HostName         string
	HostId           string
	Domain           string
	Role             string
	Ns1ApiKey        string
	FleetTags        string
	CaCert           string
	EtcdToken        string
	FlannelNetwork   string
	FlannelSubnetLen string
	FlannelSubnetMin string
	FlannelSubnetMax string
	FlannelBackend   string
}

//-----------------------------------------------------------------------------
// Package variable declarations factored into a block:
//-----------------------------------------------------------------------------

var (

	//----------------------------
	// katoctl: top level command
	//----------------------------

	app = kingpin.New("katoctl", "Katoctl defines and deploys CoreOS clusters.")

	//-----------------------
	// udata: nested command
	//-----------------------

	cmdUdata = app.Command("udata", "Generate CoreOS cloud-config user-data.")

	flHostName = cmdUdata.Flag("hostname", "Short host name as in (hostname -s)").
			Required().PlaceHolder("CS_HOSTNAME").
			OverrideDefaultFromEnvar("CS_HOSTNAME").
			Short('h').String()

	flDomain = cmdUdata.Flag("domain", "Domain name as in (hostname -d)").
			Required().PlaceHolder("CS_DOMAIN").
			OverrideDefaultFromEnvar("CS_DOMAIN").
			Short('d').String()

	flRole = cmdUdata.Flag("role", "Choose one of [ master | node | edge ]").
			Required().PlaceHolder("CS_ROLE").
			OverrideDefaultFromEnvar("CS_ROLE").
			Short('r').String()

	flNs1Apikey = cmdUdata.Flag("ns1-api-key", "NS1 private API key.").
			Required().PlaceHolder("CS_NS1_API_KEY").
			OverrideDefaultFromEnvar("CS_NS1_API_KEY").
			Short('k').String()

	flFleetTags = cmdUdata.Flag("fleet-tags", "Comma separated list of fleet tags.").
			PlaceHolder("CS_FLEET_TAGS").
			OverrideDefaultFromEnvar("CS_FLEET_TAGS").
			Short('t').String()

	flCAcert = cmdUdata.Flag("ca-cert", "Path to CA certificate.").
			PlaceHolder("CS_CA_CERT").
			OverrideDefaultFromEnvar("CS_CA_CERT").
			Short('c').String()

	flEtcdToken = cmdUdata.Flag("etcd-token", "Provide an etcd discovery token.").
			PlaceHolder("CS_ETCD_TOKEN").
			OverrideDefaultFromEnvar("CS_ETCD_TOKEN").
			Short('e').String()

	flFlannelNetwork = cmdUdata.Flag("flannel-network", "Flannel entire overlay network.").
			PlaceHolder("CS_FLANNEL_NETWORK").
			OverrideDefaultFromEnvar("CS_FLANNEL_NETWORK").
			Short('n').String()

	flFlannelSubnetLen = cmdUdata.Flag("flannel-subnet-len", "Subnet len to llocate to each host.").
			PlaceHolder("CS_FLANNEL_SUBNET_LEN").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_LEN").
			Short('s').String()

	flFlannelSubnetMin = cmdUdata.Flag("flannel-subnet-min", "Minimum subnet IP addresses.").
			PlaceHolder("CS_FLANNEL_SUBNET_MIN").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MIN").
			Short('m').String()

	flFlannelSubnetMax = cmdUdata.Flag("flannel-subnet-max", "Maximum subnet IP addresses.").
			PlaceHolder("CS_FLANNEL_SUBNET_MAX").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MAX").
			Short('x').String()

	flFlannelBackend = cmdUdata.Flag("flannel-backend", "Flannel backend type: [ udp | vxlan | gce | aws-vpc ]").
			PlaceHolder("CS_FLANNEL_SUBNET_MAX").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MAX").
			Short('b').String()

	//----------------------------
	// run-packet: nested command
	//----------------------------

	cmdRunPacket = app.Command("run-packet", "Starts a CoreOS instance on Packet.net")

	flPktApiKey = cmdRunPacket.Flag("api-key", "Packet API key.").
			Required().PlaceHolder("PKT_APIKEY").
			OverrideDefaultFromEnvar("PKT_APIKEY").
			Short('k').String()

	flPktHostName = cmdRunPacket.Flag("hostname", "For the Packet.net dashboard.").
			Required().PlaceHolder("PKT_HOSTNAME").
			OverrideDefaultFromEnvar("PKT_HOSTNAME").
			Short('h').String()

	flPktProjId = cmdRunPacket.Flag("project-id", "Format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee").
			Required().PlaceHolder("PKT_PROJID").
			OverrideDefaultFromEnvar("PKT_PROJID").
			Short('i').String()

	flPktPlan = cmdRunPacket.Flag("plan", "One of [ baremetal_0 | baremetal_1 | baremetal_2 | baremetal_3 ]").
			Required().PlaceHolder("PKT_PLAN").
			OverrideDefaultFromEnvar("PKT_PLAN").
			Short('p').String()

	flPktOsys = cmdRunPacket.Flag("os", "One of [ coreos_stable | coreos_beta | coreos_alpha ]").
			Required().PlaceHolder("PKT_OS").
			OverrideDefaultFromEnvar("PKT_OS").
			Short('o').String()

	flPktFacility = cmdRunPacket.Flag("facility", "One of [ ewr1 | ams1 ]").
			Required().PlaceHolder("PKT_FACILITY").
			OverrideDefaultFromEnvar("PKT_FACILITY").
			Short('f').String()

	flPktBilling = cmdRunPacket.Flag("billing", "One of [ hourly | monthly ]").
			Required().PlaceHolder("PKT_BILLING").
			OverrideDefaultFromEnvar("PKT_BILLING").
			Short('b').String()

	//-------------------------
	// run-ec2: nested command
	//-------------------------

	cmdRunEc2 = app.Command("run-ec2", "Starts a CoreOS instance on Amazon EC2")

	flEc2HostName = cmdRunEc2.Flag("hostname", "For the EC2 dashboard.").
			PlaceHolder("EC2_HOSTNAME").
			OverrideDefaultFromEnvar("EC2_HOSTNAME").
			Short('h').String()

	flEc2Region = cmdRunEc2.Flag("region", "EC2 region.").
			Required().PlaceHolder("EC2_REGION").
			OverrideDefaultFromEnvar("EC2_REGION").
			Short('r').String()

	flEc2ImageId = cmdRunEc2.Flag("image-id", "EC2 image id.").
			Required().PlaceHolder("EC2_IMAGE_ID").
			OverrideDefaultFromEnvar("EC2_IMAGE_ID").
			Short('i').String()

	flEc2InsType = cmdRunEc2.Flag("instance-type", "EC2 instance type.").
			Required().PlaceHolder("EC2_INSTANCE_TYPE").
			OverrideDefaultFromEnvar("EC2_INSTANCE_TYPE").
			Short('t').String()

	flEc2KeyPair = cmdRunEc2.Flag("key-pair", "EC2 key pair.").
			Required().PlaceHolder("EC2_KEY_PAIR").
			OverrideDefaultFromEnvar("EC2_KEY_PAIR").
			Short('k').String()

	flEc2VpcId = cmdRunEc2.Flag("vpc-id", "EC2 VPC id.").
			Required().PlaceHolder("EC2_VPC_ID").
			OverrideDefaultFromEnvar("EC2_VPC_ID").
			Short('v').String()

	flEc2SubnetId = cmdRunEc2.Flag("subnet-id", "EC2 subnet id.").
			Required().PlaceHolder("EC2_SUBNET_ID").
			OverrideDefaultFromEnvar("EC2_SUBNET_ID").
			Short('s').String()

	flEc2SecGrpIds = cmdRunEc2.Flag("sec-group-ids", "EC2 security group ids.").
			Required().PlaceHolder("EC2_SEC_GROUP_IDS").
			OverrideDefaultFromEnvar("EC2_SEC_GROUP_IDS").
			Short('g').String()
)

//----------------------------------------------------------------------------
// Entry point:
//----------------------------------------------------------------------------

func main() {

	// Sub-command selector:
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {

	// katoctl udata ...
	case cmdUdata.FullCommand():
		cmd_udata()

	// katoctl run-packet ...
	case cmdRunPacket.FullCommand():
		cmd_run_packet()

	// katoctl run-ec2 ...
	case cmdRunEc2.FullCommand():
		cmd_run_ec2()
	}
}

//--------------------------------------------------------------------------
// func: cmd_udata
//--------------------------------------------------------------------------

func cmd_udata() {

	// Template udata structure:
	udata := Udata{
		HostName:         *flHostName,
		HostId:           string((*flHostName)[strings.LastIndex(*flHostName, "-")+1:]),
		Domain:           *flDomain,
		Role:             *flRole,
		Ns1ApiKey:        *flNs1Apikey,
		FleetTags:        *flFleetTags,
		EtcdToken:        *flEtcdToken,
		FlannelNetwork:   *flFlannelNetwork,
		FlannelSubnetLen: *flFlannelSubnetLen,
		FlannelSubnetMin: *flFlannelSubnetMin,
		FlannelSubnetMax: *flFlannelSubnetMax,
		FlannelBackend:   *flFlannelBackend,
	}

	// Read the CA certificate:
	if *flCAcert != "" {
		dat, err := ioutil.ReadFile(*flCAcert)
		checkError(err)
		udata.CaCert = strings.TrimSpace(strings.Replace(string(dat), "\n", "\n    ", -1))
	}

	// Render the template for the selected role:
	switch *flRole {
	case "master":
		t := template.New("master_udata")
		t, err := t.Parse(templ_master)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	case "node":
		t := template.New("node_udata")
		t, err := t.Parse(templ_node)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	case "edge":
		t := template.New("edge_udata")
		t, err := t.Parse(templ_edge)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	}
}

//--------------------------------------------------------------------------
// func: cmd_run_packet
//--------------------------------------------------------------------------

func cmd_run_packet() {

	// Read user-data from stdin:
	udata, err := ioutil.ReadAll(os.Stdin)
	checkError(err)

	// Connect and authenticate to the API endpoint:
	client := packngo.NewClient("", *flPktApiKey, nil)

	// Forge the request:
	createRequest := &packngo.DeviceCreateRequest{
		HostName:     *flPktHostName,
		Plan:         *flPktPlan,
		Facility:     *flPktFacility,
		OS:           *flPktOsys,
		BillingCycle: *flPktBilling,
		ProjectID:    *flPktProjId,
		UserData:     string(udata),
	}

	// Send the request:
	newDevice, _, err := client.Devices.Create(createRequest)
	checkError(err)

	// Pretty-print the response data:
	fmt.Println(newDevice)
}

//--------------------------------------------------------------------------
// func: cmd_run_ec2
//--------------------------------------------------------------------------

func cmd_run_ec2() {

	// Read user-data from stdin:
	udata, err := ioutil.ReadAll(os.Stdin)
	checkError(err)

	// Connect and authenticate to the API endpoint:
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(*flEc2Region)}))

	// Forge the SecurityGroupIds:
	var secGrps []*string
	for _, gid := range strings.Split(*flEc2SecGrpIds, ",") {
		secGrps = append(secGrps, aws.String(gid))
	}

	// Send the request:
	runResult, err := svc.RunInstances(&ec2.RunInstancesInput{
		ImageId:          aws.String(*flEc2ImageId),
		InstanceType:     aws.String(*flEc2InsType),
		MinCount:         aws.Int64(1),
		MaxCount:         aws.Int64(1),
		KeyName:          aws.String(*flEc2KeyPair),
		SubnetId:         aws.String(*flEc2SubnetId),
		SecurityGroupIds: secGrps,
		UserData:         aws.String(base64.StdEncoding.EncodeToString([]byte(udata))),
	})

	checkError(err)

	// Pretty-print the response data:
	fmt.Println("Created instance", *runResult.Instances[0].InstanceId)

	// Add tags to the created instance:
	_, err = svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{runResult.Instances[0].InstanceId},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String("Name"),
				Value: aws.String(*flEc2HostName),
			},
		},
	})

	checkError(err)
}

//---------------------------------------------------------------------------
// func: checkError
//---------------------------------------------------------------------------

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(1)
	}
}
<commit_msg>List all flannel backends<commit_after>//-----------------------------------------------------------------------------
// Package membership:
//-----------------------------------------------------------------------------

package main

//-----------------------------------------------------------------------------
// Package factored import statement:
//-----------------------------------------------------------------------------

import (

	// Standard library:
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"text/template"

	// Community:
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/packethost/packngo"
	"gopkg.in/alecthomas/kingpin.v2"
)

//----------------------------------------------------------------------------
// Typedefs:
//----------------------------------------------------------------------------

type Udata struct {
	HostName         string
	HostId           string
	Domain           string
	Role             string
	Ns1ApiKey        string
	FleetTags        string
	CaCert           string
	EtcdToken        string
	FlannelNetwork   string
	FlannelSubnetLen string
	FlannelSubnetMin string
	FlannelSubnetMax string
	FlannelBackend   string
}

//-----------------------------------------------------------------------------
// Package variable declarations factored into a block:
//-----------------------------------------------------------------------------

var (

	//----------------------------
	// katoctl: top level command
	//----------------------------

	app = kingpin.New("katoctl", "Katoctl defines and deploys CoreOS clusters.")

	//-----------------------
	// udata: nested command
	//-----------------------

	cmdUdata = app.Command("udata", "Generate CoreOS cloud-config user-data.")

	flHostName = cmdUdata.Flag("hostname", "Short host name as in (hostname -s)").
			Required().PlaceHolder("CS_HOSTNAME").
			OverrideDefaultFromEnvar("CS_HOSTNAME").
			Short('h').String()

	flDomain = cmdUdata.Flag("domain", "Domain name as in (hostname -d)").
			Required().PlaceHolder("CS_DOMAIN").
			OverrideDefaultFromEnvar("CS_DOMAIN").
			Short('d').String()

	flRole = cmdUdata.Flag("role", "Choose one of [ master | node | edge ]").
			Required().PlaceHolder("CS_ROLE").
			OverrideDefaultFromEnvar("CS_ROLE").
			Short('r').String()

	flNs1Apikey = cmdUdata.Flag("ns1-api-key", "NS1 private API key.").
			Required().PlaceHolder("CS_NS1_API_KEY").
			OverrideDefaultFromEnvar("CS_NS1_API_KEY").
			Short('k').String()

	flFleetTags = cmdUdata.Flag("fleet-tags", "Comma separated list of fleet tags.").
			PlaceHolder("CS_FLEET_TAGS").
			OverrideDefaultFromEnvar("CS_FLEET_TAGS").
			Short('t').String()

	flCAcert = cmdUdata.Flag("ca-cert", "Path to CA certificate.").
			PlaceHolder("CS_CA_CERT").
			OverrideDefaultFromEnvar("CS_CA_CERT").
			Short('c').String()

	flEtcdToken = cmdUdata.Flag("etcd-token", "Provide an etcd discovery token.").
			PlaceHolder("CS_ETCD_TOKEN").
			OverrideDefaultFromEnvar("CS_ETCD_TOKEN").
			Short('e').String()

	flFlannelNetwork = cmdUdata.Flag("flannel-network", "Flannel entire overlay network.").
			PlaceHolder("CS_FLANNEL_NETWORK").
			OverrideDefaultFromEnvar("CS_FLANNEL_NETWORK").
			Short('n').String()

	flFlannelSubnetLen = cmdUdata.Flag("flannel-subnet-len", "Subnet len to llocate to each host.").
			PlaceHolder("CS_FLANNEL_SUBNET_LEN").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_LEN").
			Short('s').String()

	flFlannelSubnetMin = cmdUdata.Flag("flannel-subnet-min", "Minimum subnet IP addresses.").
			PlaceHolder("CS_FLANNEL_SUBNET_MIN").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MIN").
			Short('m').String()

	flFlannelSubnetMax = cmdUdata.Flag("flannel-subnet-max", "Maximum subnet IP addresses.").
			PlaceHolder("CS_FLANNEL_SUBNET_MAX").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MAX").
			Short('x').String()

	flFlannelBackend = cmdUdata.Flag("flannel-backend", "Flannel backend type: [ udp | vxlan | host-gw | gce | aws-vpc | alloc ]").
			PlaceHolder("CS_FLANNEL_SUBNET_MAX").
			OverrideDefaultFromEnvar("CS_FLANNEL_SUBNET_MAX").
			Short('b').String()

	//----------------------------
	// run-packet: nested command
	//----------------------------

	cmdRunPacket = app.Command("run-packet", "Starts a CoreOS instance on Packet.net")

	flPktApiKey = cmdRunPacket.Flag("api-key", "Packet API key.").
			Required().PlaceHolder("PKT_APIKEY").
			OverrideDefaultFromEnvar("PKT_APIKEY").
			Short('k').String()

	flPktHostName = cmdRunPacket.Flag("hostname", "For the Packet.net dashboard.").
			Required().PlaceHolder("PKT_HOSTNAME").
			OverrideDefaultFromEnvar("PKT_HOSTNAME").
			Short('h').String()

	flPktProjId = cmdRunPacket.Flag("project-id", "Format: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee").
			Required().PlaceHolder("PKT_PROJID").
			OverrideDefaultFromEnvar("PKT_PROJID").
			Short('i').String()

	flPktPlan = cmdRunPacket.Flag("plan", "One of [ baremetal_0 | baremetal_1 | baremetal_2 | baremetal_3 ]").
			Required().PlaceHolder("PKT_PLAN").
			OverrideDefaultFromEnvar("PKT_PLAN").
			Short('p').String()

	flPktOsys = cmdRunPacket.Flag("os", "One of [ coreos_stable | coreos_beta | coreos_alpha ]").
			Required().PlaceHolder("PKT_OS").
			OverrideDefaultFromEnvar("PKT_OS").
			Short('o').String()

	flPktFacility = cmdRunPacket.Flag("facility", "One of [ ewr1 | ams1 ]").
			Required().PlaceHolder("PKT_FACILITY").
			OverrideDefaultFromEnvar("PKT_FACILITY").
			Short('f').String()

	flPktBilling = cmdRunPacket.Flag("billing", "One of [ hourly | monthly ]").
			Required().PlaceHolder("PKT_BILLING").
			OverrideDefaultFromEnvar("PKT_BILLING").
			Short('b').String()

	//-------------------------
	// run-ec2: nested command
	//-------------------------

	cmdRunEc2 = app.Command("run-ec2", "Starts a CoreOS instance on Amazon EC2")

	flEc2HostName = cmdRunEc2.Flag("hostname", "For the EC2 dashboard.").
			PlaceHolder("EC2_HOSTNAME").
			OverrideDefaultFromEnvar("EC2_HOSTNAME").
			Short('h').String()

	flEc2Region = cmdRunEc2.Flag("region", "EC2 region.").
			Required().PlaceHolder("EC2_REGION").
			OverrideDefaultFromEnvar("EC2_REGION").
			Short('r').String()

	flEc2ImageId = cmdRunEc2.Flag("image-id", "EC2 image id.").
			Required().PlaceHolder("EC2_IMAGE_ID").
			OverrideDefaultFromEnvar("EC2_IMAGE_ID").
			Short('i').String()

	flEc2InsType = cmdRunEc2.Flag("instance-type", "EC2 instance type.").
			Required().PlaceHolder("EC2_INSTANCE_TYPE").
			OverrideDefaultFromEnvar("EC2_INSTANCE_TYPE").
			Short('t').String()

	flEc2KeyPair = cmdRunEc2.Flag("key-pair", "EC2 key pair.").
			Required().PlaceHolder("EC2_KEY_PAIR").
			OverrideDefaultFromEnvar("EC2_KEY_PAIR").
			Short('k').String()

	flEc2VpcId = cmdRunEc2.Flag("vpc-id", "EC2 VPC id.").
			Required().PlaceHolder("EC2_VPC_ID").
			OverrideDefaultFromEnvar("EC2_VPC_ID").
			Short('v').String()

	flEc2SubnetId = cmdRunEc2.Flag("subnet-id", "EC2 subnet id.").
			Required().PlaceHolder("EC2_SUBNET_ID").
			OverrideDefaultFromEnvar("EC2_SUBNET_ID").
			Short('s').String()

	flEc2SecGrpIds = cmdRunEc2.Flag("sec-group-ids", "EC2 security group ids.").
			Required().PlaceHolder("EC2_SEC_GROUP_IDS").
			OverrideDefaultFromEnvar("EC2_SEC_GROUP_IDS").
			Short('g').String()
)

//----------------------------------------------------------------------------
// Entry point:
//----------------------------------------------------------------------------

func main() {

	// Sub-command selector:
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {

	// katoctl udata ...
	case cmdUdata.FullCommand():
		cmd_udata()

	// katoctl run-packet ...
	case cmdRunPacket.FullCommand():
		cmd_run_packet()

	// katoctl run-ec2 ...
	case cmdRunEc2.FullCommand():
		cmd_run_ec2()
	}
}

//--------------------------------------------------------------------------
// func: cmd_udata
//--------------------------------------------------------------------------

func cmd_udata() {

	// Template udata structure:
	udata := Udata{
		HostName:         *flHostName,
		HostId:           string((*flHostName)[strings.LastIndex(*flHostName, "-")+1:]),
		Domain:           *flDomain,
		Role:             *flRole,
		Ns1ApiKey:        *flNs1Apikey,
		FleetTags:        *flFleetTags,
		EtcdToken:        *flEtcdToken,
		FlannelNetwork:   *flFlannelNetwork,
		FlannelSubnetLen: *flFlannelSubnetLen,
		FlannelSubnetMin: *flFlannelSubnetMin,
		FlannelSubnetMax: *flFlannelSubnetMax,
		FlannelBackend:   *flFlannelBackend,
	}

	// Read the CA certificate:
	if *flCAcert != "" {
		dat, err := ioutil.ReadFile(*flCAcert)
		checkError(err)
		udata.CaCert = strings.TrimSpace(strings.Replace(string(dat), "\n", "\n    ", -1))
	}

	// Render the template for the selected role:
	switch *flRole {
	case "master":
		t := template.New("master_udata")
		t, err := t.Parse(templ_master)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	case "node":
		t := template.New("node_udata")
		t, err := t.Parse(templ_node)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	case "edge":
		t := template.New("edge_udata")
		t, err := t.Parse(templ_edge)
		err = t.Execute(os.Stdout, udata)
		checkError(err)
	}
}

//--------------------------------------------------------------------------
// func: cmd_run_packet
//--------------------------------------------------------------------------

func cmd_run_packet() {

	// Read user-data from stdin:
	udata, err := ioutil.ReadAll(os.Stdin)
	checkError(err)

	// Connect and authenticate to the API endpoint:
	client := packngo.NewClient("", *flPktApiKey, nil)

	// Forge the request:
	createRequest := &packngo.DeviceCreateRequest{
		HostName:     *flPktHostName,
		Plan:         *flPktPlan,
		Facility:     *flPktFacility,
		OS:           *flPktOsys,
		BillingCycle: *flPktBilling,
		ProjectID:    *flPktProjId,
		UserData:     string(udata),
	}

	// Send the request:
	newDevice, _, err := client.Devices.Create(createRequest)
	checkError(err)

	// Pretty-print the response data:
	fmt.Println(newDevice)
}

//--------------------------------------------------------------------------
// func: cmd_run_ec2
//--------------------------------------------------------------------------

func cmd_run_ec2() {

	// Read user-data from stdin:
	udata, err := ioutil.ReadAll(os.Stdin)
	checkError(err)

	// Connect and authenticate to the API endpoint:
	svc := ec2.New(session.New(&aws.Config{Region: aws.String(*flEc2Region)}))

	// Forge the SecurityGroupIds:
	var secGrps []*string
	for _, gid := range strings.Split(*flEc2SecGrpIds, ",") {
		secGrps = append(secGrps, aws.String(gid))
	}

	// Send the request:
	runResult, err := svc.RunInstances(&ec2.RunInstancesInput{
		ImageId:          aws.String(*flEc2ImageId),
		InstanceType:     aws.String(*flEc2InsType),
		MinCount:         aws.Int64(1),
		MaxCount:         aws.Int64(1),
		KeyName:          aws.String(*flEc2KeyPair),
		SubnetId:         aws.String(*flEc2SubnetId),
		SecurityGroupIds: secGrps,
		UserData:         aws.String(base64.StdEncoding.EncodeToString([]byte(udata))),
	})

	checkError(err)

	// Pretty-print the response data:
	fmt.Println("Created instance", *runResult.Instances[0].InstanceId)

	// Add tags to the created instance:
	_, err = svc.CreateTags(&ec2.CreateTagsInput{
		Resources: []*string{runResult.Instances[0].InstanceId},
		Tags: []*ec2.Tag{
			{
				Key:   aws.String("Name"),
				Value: aws.String(*flEc2HostName),
			},
		},
	})

	checkError(err)
}

//---------------------------------------------------------------------------
// func: checkError
//---------------------------------------------------------------------------

func checkError(err error) {
	if err != nil {
		fmt.Println("Fatal error ", err.Error())
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/grantmd/go-s2client/sc2proto"
	"log"
	"time"
)

var addr = flag.String("addr", "localhost:5000", "sc2api server address")
var listMaps = flag.Bool("listMaps", false, "list available maps")
var mapName = flag.String("map", "", "name of map to play")

func main() {
	flag.Parse()
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	var c Conn
	log.Printf("Connecting to %s…", *addr)

	err := c.Dial(addr)
	if err != nil {
		log.Fatal("dial:", err)
	}
	log.Println("Successfully connected!")

	protocol := &Protocol{
		conn: &c,
	}
	defer protocol.Disconnect()

	var req *SC2APIProtocol.Request
	var resp *SC2APIProtocol.Response

	if *listMaps == true {
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_AvailableMaps{
				AvailableMaps: &SC2APIProtocol.RequestAvailableMaps{},
			},
		}
		log.Println("Listing available maps…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send available maps request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive available maps response:", err)
		}

		availableMaps := resp.GetAvailableMaps()
		fmt.Println("Local maps:")
		for _, localMap := range availableMaps.LocalMapPaths {
			fmt.Println(localMap)
		}

		fmt.Println("\nBattlenet maps:")
		for _, bnetMap := range availableMaps.BattlenetMapNames {
			fmt.Println(bnetMap)
		}
	}

	if *mapName != "" {
		// Create a new game
		ourPlayer := &SC2APIProtocol.PlayerSetup{
			Type: SC2APIProtocol.PlayerType_Participant.Enum(),
			Race: SC2APIProtocol.Race_Terran.Enum(),
		}
		opponentPlayer := &SC2APIProtocol.PlayerSetup{
			Type:       SC2APIProtocol.PlayerType_Computer.Enum(),
			Race:       SC2APIProtocol.Race_Terran.Enum(),
			Difficulty: SC2APIProtocol.Difficulty_VeryHard.Enum(),
		}

		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_CreateGame{
				CreateGame: &SC2APIProtocol.RequestCreateGame{
					Map: &SC2APIProtocol.RequestCreateGame_BattlenetMapName{
						BattlenetMapName: *mapName,
					},
					PlayerSetup: []*SC2APIProtocol.PlayerSetup{ourPlayer, opponentPlayer},
					DisableFog:  proto.Bool(false),
					Realtime:    proto.Bool(true),
				},
			},
		}
		log.Println("Starting game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send game start request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive game start response:", err)
		}
		log.Println("Game started:", resp)

		// Join the game
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_JoinGame{
				JoinGame: &SC2APIProtocol.RequestJoinGame{
					Participation: &SC2APIProtocol.RequestJoinGame_Race{
						Race: SC2APIProtocol.Race_Terran,
					},
					Options: &SC2APIProtocol.InterfaceOptions{
						Raw: proto.Bool(true),
					},
				},
			},
		}
		log.Println("Joining game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send join game request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive join game response:", err)
		}
		log.Println("Game joined:", resp)

		// Game loop
		for {
			// Request observation
			req = &SC2APIProtocol.Request{
				Request: &SC2APIProtocol.Request_Observation{
					Observation: &SC2APIProtocol.RequestObservation{},
				},
			}
			err = protocol.SendRequest(req)
			if err != nil {
				log.Fatal("Could not send request:", err)
			}

			// Read the game state result
			resp, err = protocol.ReadResponse()
			if err != nil {
				log.Fatal("Could not receive response:", err)
			}

			respObs := resp.GetObservation()
			// respObs.Actions - list of actions performed
			// respObs.ActionErrors - list of actions which did not complete
			// respObs.Observation - whole mess of observation data. see struct
			// respObs.PlayerResult - result of game, only if ended that step
			// respObs.Chat - chat messages received. could be fun

			obs := respObs.GetObservation()
			// obs.PlayerCommon - looks like player state. minerals, vespene, units, etc. very useful
			// obs.Alerts - critical end game actions like nuclear launch detected
			// obs.Abilities - list of available abilities? unclear. definitiion of AvailableAbility is in common.pb.go
			// obs.Score - I think how well you're doing, if you request score mode at game start
			// obs.RawData - Raw game data. Where the meat is of what we can see and do. Look at raw.pb.go for all the info
			// obs.FeatureLayerData - Probably not available unless you pick that game mode. Image based?
			// obs.RenderData - Full fidelity rendered image of the game. Not available yet
			// obs.UiData - Also not available yet

			log.Printf("step: %s", obs.PlayerCommon)

			// Are we done?
			if resp.GetStatus() == SC2APIProtocol.Status_ended {
				log.Println("Game over, man")
				log.Println(respObs.PlayerResult)
				break
			}

			// Examine game state
			for _, unit := range obs.RawData.Units {
				if *unit.UnitType == 18 { // Command center

				}
			}

			// Send action

			// Keep this reasonably paced
			time.Sleep(100 * time.Millisecond)
		}

		// Leave game
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_LeaveGame{
				LeaveGame: &SC2APIProtocol.RequestLeaveGame{},
			},
		}
		log.Println("Leaving game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send leave request:", err)
		}

		_, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive leave response:", err)
		}
		log.Println("Game left:", resp)
	}

	// Disconnect
	log.Println("Disconnecting…")
	err = protocol.Disconnect()
	if err != nil {
		log.Fatal("Error disconnecting:", err)
	}

	log.Println("gg")

	// Extra requests I've tested
	/*req = &SC2APIProtocol.Request{
		Request: &SC2APIProtocol.Request_Ping{
			Ping: &SC2APIProtocol.RequestPing{},
		},
	}*/
	/*req = &SC2APIProtocol.Request{
		Request: &SC2APIProtocol.Request_Debug{
			Debug: &SC2APIProtocol.RequestDebug{},
		},
	}*/
}
<commit_msg>Allow switching between local and battlenet maps<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/grantmd/go-s2client/sc2proto"
	"log"
	"time"
)

var addr = flag.String("addr", "localhost:5000", "sc2api server address")
var listMaps = flag.Bool("listMaps", false, "list available maps")
var mapName = flag.String("mapName", "", "name of battlenet map to play")
var mapPath = flag.String("mapPath", "", "path of local map to play")

func main() {
	flag.Parse()
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	var c Conn
	log.Printf("Connecting to %s…", *addr)

	err := c.Dial(addr)
	if err != nil {
		log.Fatal("dial:", err)
	}
	log.Println("Successfully connected!")

	protocol := &Protocol{
		conn: &c,
	}
	defer protocol.Disconnect()

	var req *SC2APIProtocol.Request
	var resp *SC2APIProtocol.Response

	if *listMaps == true {
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_AvailableMaps{
				AvailableMaps: &SC2APIProtocol.RequestAvailableMaps{},
			},
		}
		log.Println("Listing available maps…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send available maps request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive available maps response:", err)
		}

		availableMaps := resp.GetAvailableMaps()
		fmt.Println("Local maps:")
		for _, localMap := range availableMaps.LocalMapPaths {
			fmt.Println(localMap)
		}

		fmt.Println("\nBattlenet maps:")
		for _, bnetMap := range availableMaps.BattlenetMapNames {
			fmt.Println(bnetMap)
		}
	}

	if *mapName != "" || *mapPath != "" {
		// Create a new game
		ourPlayer := &SC2APIProtocol.PlayerSetup{
			Type: SC2APIProtocol.PlayerType_Participant.Enum(),
			Race: SC2APIProtocol.Race_Terran.Enum(),
		}
		opponentPlayer := &SC2APIProtocol.PlayerSetup{
			Type:       SC2APIProtocol.PlayerType_Computer.Enum(),
			Race:       SC2APIProtocol.Race_Terran.Enum(),
			Difficulty: SC2APIProtocol.Difficulty_VeryHard.Enum(),
		}

		// Set either a battlenet map or a local map from args
		if *mapName != "" {
			req = &SC2APIProtocol.Request{
				Request: &SC2APIProtocol.Request_CreateGame{
					CreateGame: &SC2APIProtocol.RequestCreateGame{
						Map: &SC2APIProtocol.RequestCreateGame_BattlenetMapName{
							BattlenetMapName: *mapName,
						},
						PlayerSetup: []*SC2APIProtocol.PlayerSetup{ourPlayer, opponentPlayer},
						DisableFog:  proto.Bool(false),
						Realtime:    proto.Bool(true),
					},
				},
			}
		}
		if *mapPath != "" {
			req = &SC2APIProtocol.Request{
				Request: &SC2APIProtocol.Request_CreateGame{
					CreateGame: &SC2APIProtocol.RequestCreateGame{
						Map: &SC2APIProtocol.RequestCreateGame_LocalMap{
							LocalMap: &SC2APIProtocol.LocalMap{
								MapPath: mapPath,
							},
						},
						PlayerSetup: []*SC2APIProtocol.PlayerSetup{ourPlayer, opponentPlayer},
						DisableFog:  proto.Bool(false),
						Realtime:    proto.Bool(true),
					},
				},
			}
		}

		log.Println("Starting game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send game start request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive game start response:", err)
		}
		log.Println("Game started:", resp)

		// Join the game
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_JoinGame{
				JoinGame: &SC2APIProtocol.RequestJoinGame{
					Participation: &SC2APIProtocol.RequestJoinGame_Race{
						Race: SC2APIProtocol.Race_Terran,
					},
					Options: &SC2APIProtocol.InterfaceOptions{
						Raw: proto.Bool(true),
					},
				},
			},
		}
		log.Println("Joining game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send join game request:", err)
		}

		resp, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive join game response:", err)
		}
		log.Println("Game joined:", resp)

		// Game loop
		for {
			// Request observation
			req = &SC2APIProtocol.Request{
				Request: &SC2APIProtocol.Request_Observation{
					Observation: &SC2APIProtocol.RequestObservation{},
				},
			}
			err = protocol.SendRequest(req)
			if err != nil {
				log.Fatal("Could not send request:", err)
			}

			// Read the game state result
			resp, err = protocol.ReadResponse()
			if err != nil {
				log.Fatal("Could not receive response:", err)
			}

			respObs := resp.GetObservation()
			// respObs.Actions - list of actions performed
			// respObs.ActionErrors - list of actions which did not complete
			// respObs.Observation - whole mess of observation data. see struct
			// respObs.PlayerResult - result of game, only if ended that step
			// respObs.Chat - chat messages received. could be fun

			obs := respObs.GetObservation()
			// obs.PlayerCommon - looks like player state. minerals, vespene, units, etc. very useful
			// obs.Alerts - critical end game actions like nuclear launch detected
			// obs.Abilities - list of available abilities? unclear. definitiion of AvailableAbility is in common.pb.go
			// obs.Score - I think how well you're doing, if you request score mode at game start
			// obs.RawData - Raw game data. Where the meat is of what we can see and do. Look at raw.pb.go for all the info
			// obs.FeatureLayerData - Probably not available unless you pick that game mode. Image based?
			// obs.RenderData - Full fidelity rendered image of the game. Not available yet
			// obs.UiData - Also not available yet

			log.Printf("step: %s", obs.PlayerCommon)

			// Are we done?
			if resp.GetStatus() == SC2APIProtocol.Status_ended {
				log.Println("Game over, man")
				log.Println(respObs.PlayerResult)
				break
			}

			// Examine game state
			for _, unit := range obs.RawData.Units {
				if *unit.UnitType == 18 { // Command center

				}
			}

			// Send action

			// Keep this reasonably paced
			time.Sleep(100 * time.Millisecond)
		}

		// Leave game
		req = &SC2APIProtocol.Request{
			Request: &SC2APIProtocol.Request_LeaveGame{
				LeaveGame: &SC2APIProtocol.RequestLeaveGame{},
			},
		}
		log.Println("Leaving game…")
		err = protocol.SendRequest(req)
		if err != nil {
			log.Fatal("Could not send leave request:", err)
		}

		_, err = protocol.ReadResponse()
		if err != nil {
			log.Fatal("Could not receive leave response:", err)
		}
		log.Println("Game left:", resp)
	}

	// Disconnect
	log.Println("Disconnecting…")
	err = protocol.Disconnect()
	if err != nil {
		log.Fatal("Error disconnecting:", err)
	}

	log.Println("gg")

	// Extra requests I've tested
	/*req = &SC2APIProtocol.Request{
		Request: &SC2APIProtocol.Request_Ping{
			Ping: &SC2APIProtocol.RequestPing{},
		},
	}*/
	/*req = &SC2APIProtocol.Request{
		Request: &SC2APIProtocol.Request_Debug{
			Debug: &SC2APIProtocol.RequestDebug{},
		},
	}*/
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"regexp"
	"syscall"
	"time"

	"github.com/codegangsta/cli"
)

const (
	// VERSION of crononag
	VERSION = "0.0.3"
)

func run(c *cli.Context) {
	args := c.Args()
	if len(c.Args()) == 0 {
		cli.ShowAppHelp(c)
		os.Exit(1)
	}

	suppressRegexpSlice := make([]*regexp.Regexp, len(c.StringSlice(`suppress-regexp`)))
	for i, s := range c.StringSlice(`suppress-regexp`) {
		suppressRegexpSlice[i] = regexp.MustCompile(s)
	}

	forceRegexpSlice := make([]*regexp.Regexp, len(c.StringSlice(`force-regexp`)))
	for i, s := range c.StringSlice(`force-regexp`) {
		forceRegexpSlice[i] = regexp.MustCompile(s)
	}

	var cmd *exec.Cmd
	if len(args) > 1 {
		cmd = exec.Command(args[0], args[1:len(args)]...)
	} else {
		cmd = exec.Command(args[0])
	}

	splay := c.Duration(`splay`)
	if splay > 0 {
		rand.Seed(time.Now().UnixNano())
		rsplayf := splay.Seconds() * rand.Float64()
		rsplay, err := time.ParseDuration(fmt.Sprintf("%fs", rsplayf))
		if err == nil {
			time.Sleep(rsplay)
		}
	}

	var (
		out bytes.Buffer
		err error
	)

	cmd.Stderr = &out
	if !c.Bool(`omit-stdout`) {
		cmd.Stdout = &out
	}

	if err = cmd.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "Could not start process: %v", err)
		os.Exit(1)
	}

	err = cmd.Wait()
	if regexpSliceMatches(out.Bytes(), forceRegexpSlice) {
		exit(out.String(), 1)
	} else if exitError, ok := err.(*exec.ExitError); ok {
		// Exited non-zero
		if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
			exitCode := status.ExitStatus()
			if !intInSlice(exitCode, c.IntSlice(`suppress-exit-code`)) && !regexpSliceMatches(out.Bytes(), suppressRegexpSlice) {
				exit(out.String(), exitCode)
			}
		} else {
			exit(fmt.Sprintf("Unhandled error, sending output: %s\n%v", err, out), 1)
		}
	}
}

func exit(out string, code int) {
	if len(out) > 0 {
		fmt.Fprintf(os.Stderr, "%s", out)
	}
	os.Exit(code)
}

func regexpSliceMatches(b []byte, regexpSlice []*regexp.Regexp) bool {
	for _, r := range regexpSlice {
		if r.Match(b) {
			return true
		}
	}

	return false
}

func intInSlice(i int, list []int) bool {
	for _, r := range list {
		if r == i {
			return true
		}
	}

	return false
}

func main() {
	app := cli.NewApp()
	app.Name = `crononag`
	app.Usage = `wrap commands running from cron to limit nagging emails`
	app.Version = VERSION
	app.HideHelp = true
	app.Flags = []cli.Flag{
		cli.IntSliceFlag{
			Name:  `E, suppress-exit-code`,
			Value: &cli.IntSlice{0},
			Usage: `suppress output for specified exit code(s), may specify multiple times, defaults to 0`,
		},
		cli.StringSliceFlag{
			Name:  `R, suppress-regexp`,
			Usage: `suppress output on matching regexp, may specify multiple times`,
		},
		cli.BoolFlag{
			Name:  `O, omit-stdout`,
			Usage: `omit stdout, even on error, defaults to false`,
		},
		cli.StringSliceFlag{
			Name:  `f, force-regexp`,
			Usage: `force output on matching regexp, may specify multiple times, overrides suppression`,
		},
		cli.DurationFlag{
			Name:  `s, splay`,
			Usage: `sleep for a random duration, up to the specified maximum, format is <decimal><unit>, eg: "5s", "2h45m", "12h", defaults to 0`,
		},
	}
	app.Action = run
	if err := app.Run(os.Args); err != nil {
		panic(err)
	}
}
<commit_msg>Refactor<commit_after>package main

import (
	"bytes"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"regexp"
	"syscall"
	"time"

	"github.com/codegangsta/cli"
)

const (
	// VERSION of crononag
	VERSION = "0.0.3"
)

type regexpSlice []*regexp.Regexp

func run(c *cli.Context) {
	args := c.Args()
	if len(c.Args()) == 0 {
		cli.ShowAppHelp(c)
		os.Exit(1)
	}

	doSplay(c)

	suppressRegexpSlice := make(regexpSlice, len(c.StringSlice(`suppress-regexp`)))
	for i, s := range c.StringSlice(`suppress-regexp`) {
		suppressRegexpSlice[i] = regexp.MustCompile(s)
	}

	forceRegexpSlice := make(regexpSlice, len(c.StringSlice(`force-regexp`)))
	for i, s := range c.StringSlice(`force-regexp`) {
		forceRegexpSlice[i] = regexp.MustCompile(s)
	}

	var cmd *exec.Cmd
	if len(args) > 1 {
		cmd = exec.Command(args[0], args[1:len(args)]...)
	} else {
		cmd = exec.Command(args[0])
	}

	doCmd(c, cmd, forceRegexpSlice, suppressRegexpSlice)
}

func exit(out string, code int) {
	if len(out) > 0 {
		fmt.Fprintf(os.Stderr, "%s", out)
	}
	os.Exit(code)
}

func doCmd(c *cli.Context, cmd *exec.Cmd, forceRegexpSlice, suppressRegexpSlice regexpSlice) {
	var (
		out bytes.Buffer
		err error
	)

	cmd.Stderr = &out
	if !c.Bool(`omit-stdout`) {
		cmd.Stdout = &out
	}

	if err = cmd.Start(); err != nil {
		fmt.Fprintf(os.Stderr, "Could not start process: %v", err)
		os.Exit(1)
	}

	err = cmd.Wait()
	if regexpSliceMatches(out.Bytes(), forceRegexpSlice) {
		exit(out.String(), 1)
	} else if exitError, ok := err.(*exec.ExitError); ok {
		// Exited non-zero
		if status, ok := exitError.Sys().(syscall.WaitStatus); ok {
			exitCode := status.ExitStatus()
			if !intInSlice(exitCode, c.IntSlice(`suppress-exit-code`)) && !regexpSliceMatches(out.Bytes(), suppressRegexpSlice) {
				exit(out.String(), exitCode)
			}
		} else {
			exit(fmt.Sprintf("Unhandled error, sending output: %s\n%v", err, out), 1)
		}
	}
}

func doSplay(c *cli.Context) {
	splay := c.Duration(`splay`)
	if splay > 0 {
		rand.Seed(time.Now().UnixNano())
		rsplayf := splay.Seconds() * rand.Float64()
		rsplay, err := time.ParseDuration(fmt.Sprintf("%fs", rsplayf))
		if err == nil {
			time.Sleep(rsplay)
		}
	}
}

func regexpSliceMatches(b []byte, regexpSlice []*regexp.Regexp) bool {
	for _, r := range regexpSlice {
		if r.Match(b) {
			return true
		}
	}

	return false
}

func intInSlice(i int, list []int) bool {
	for _, r := range list {
		if r == i {
			return true
		}
	}

	return false
}

func main() {
	app := cli.NewApp()
	app.Name = `crononag`
	app.Usage = `wrap commands running from cron to limit nagging emails`
	app.Version = VERSION
	app.HideHelp = true
	app.Flags = []cli.Flag{
		cli.IntSliceFlag{
			Name:  `E, suppress-exit-code`,
			Value: &cli.IntSlice{0},
			Usage: `suppress output for specified exit code(s), may specify multiple times, defaults to 0`,
		},
		cli.StringSliceFlag{
			Name:  `R, suppress-regexp`,
			Usage: `suppress output on matching regexp, may specify multiple times`,
		},
		cli.BoolFlag{
			Name:  `O, omit-stdout`,
			Usage: `omit stdout, even on error, defaults to false`,
		},
		cli.StringSliceFlag{
			Name:  `f, force-regexp`,
			Usage: `force output on matching regexp, may specify multiple times, overrides suppression`,
		},
		cli.DurationFlag{
			Name:  `s, splay`,
			Usage: `sleep for a random duration, up to the specified maximum, format is <decimal><unit>, eg: "5s", "2h45m", "12h", defaults to 0`,
		},
	}
	app.Action = run
	if err := app.Run(os.Args); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"log"
	"os"
)

var red (func(...interface{}) string) = color.New(color.FgRed).SprintFunc()
var yellow (func(...interface{}) string) = color.New(color.FgYellow).SprintFunc()
var green (func(...interface{}) string) = color.New(color.FgGreen).SprintFunc()
var blue (func(...interface{}) string) = color.New(color.FgCyan).SprintFunc()

const MISSING_FLAG_ERROR string = `The plugin-path argument is required.
Usage:
go-epidemic --plugin-path=$HOME/.config/nvim/bundle
  or
go-epidemic --plugin-path=$HOME/.vim/bundle
`

func main() {
	// Remove timestamp prefix
	log.SetFlags(0)

	// Parse command line arguments
	var pluginPath string
	flag.StringVar(&pluginPath, "plugin-path", "", "REQUIRED: the path to your pathogen plugins")
	flag.Parse()

	// Handle args
	if pluginPath == "" {
		log.Fatalln(red(MISSING_FLAG_ERROR))
	}

	// Find plugins
	pluginDir, err := getDirectory(pluginPath)
	if err != nil {
		log.Fatalln(red(err))
	}
	fmt.Println(blue(pluginDir.Name()) + " targeted")
}

// getDirectory returns the directory at the given path if it can be opened
// and confirmed to be a directory.
func getDirectory(directoryPath string) (*os.File, error) {
	directory, err := os.Open(directoryPath)
	if err != nil {
		return nil, errors.Wrapf(err, "Unable to open %s:", directoryPath)
	}
	if fileInfo, err := directory.Stat(); err != nil {
		return nil, errors.Wrapf(err, "Unable to access metadata for %s:", directory.Name())
	} else if !fileInfo.IsDir() {
		return nil, fmt.Errorf("%s is not a directory", directory.Name())
	}
	return directory, nil
}
<commit_msg>Improve usage text<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/fatih/color"
	"github.com/pkg/errors"
	"os"
)

var red (func(...interface{}) string) = color.New(color.FgRed).SprintFunc()
var yellow (func(...interface{}) string) = color.New(color.FgYellow).SprintFunc()
var green (func(...interface{}) string) = color.New(color.FgGreen).SprintFunc()
var blue (func(...interface{}) string) = color.New(color.FgCyan).SprintFunc()

const USAGE_MESSAGE string = `
%[1]s path

path -- the path to where your pathogen vim plugins are stored.
	This is generally the bundle directory within your vim
	configuration.
	Ex: (neovim) $HOME/.config/nvim/bundle
	    (vim)    $HOME/.vim/bundle

Ex: (neovim) %[1]s $HOME/.config/nvim/bundle
    (vim)    %[1]s $HOME/.vim/bundle
`

func main() {
	// Override usage text
	flag.Usage = printUsage

	// Parse command line arguments
	pluginPath := flag.Arg(0)
	if pluginPath == "" {
		printUsage()
	}

	// Find plugins
	pluginDir, err := getDirectory(pluginPath)
	if err != nil {
		fmt.Println(os.Stderr, red(err))
		os.Exit(1)
	}
	fmt.Println(blue(pluginDir.Name()) + " targeted")
}

// printUsage prints usage information to stderr and exits with an error status.
func printUsage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n%s", os.Args[0], fmt.Sprintf(USAGE_MESSAGE, os.Args[0]))
	os.Exit(2)
}

// getDirectory returns the directory at the given path if it can be opened
// and confirmed to be a directory.
func getDirectory(directoryPath string) (*os.File, error) {
	directory, err := os.Open(directoryPath)
	if err != nil {
		return nil, errors.Wrapf(err, "Unable to open %s:", directoryPath)
	}
	if fileInfo, err := directory.Stat(); err != nil {
		return nil, errors.Wrapf(err, "Unable to access metadata for %s:", directory.Name())
	} else if !fileInfo.IsDir() {
		return nil, fmt.Errorf("%s is not a directory", directory.Name())
	}
	return directory, nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"io"
	"log"
	"net/http"
	"strconv"
	"time"

	"cloud.google.com/go/storage"
	"github.com/gorilla/mux"
)

var (
	bind    = flag.String("b", "127.0.0.1:8080", "")
	verbose = flag.Bool("v", false, "")
)

var (
	client *storage.Client
	ctx    = context.Background()
)

func handleError(w http.ResponseWriter, err error) {
	if err != nil {
		if err == storage.ErrObjectNotExist {
			http.Error(w, err.Error(), http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
}

func header(r *http.Request, key string) (string, bool) {
	if r.Header == nil {
		return "", false
	}
	if candidate := r.Header[key]; len(candidate) > 0 {
		return candidate[0], true
	}
	return "", false
}

func setStrHeader(w http.ResponseWriter, key string, value string) {
	if value != "" {
		w.Header().Add(key, value)
	}
}

func setIntHeader(w http.ResponseWriter, key string, value int64) {
	if value > 0 {
		w.Header().Add(key, strconv.FormatInt(value, 10))
	}
}

func setTimeHeader(w http.ResponseWriter, key string, value time.Time) {
	w.Header().Add(key, value.UTC().Format(http.TimeFormat))
}

type wrapResponseWriter struct {
	http.ResponseWriter
	status int
}

func (w *wrapResponseWriter) WriteHeader(status int) {
	w.ResponseWriter.WriteHeader(status)
	w.status = status
}

func wrapper(fn func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		proc := time.Now()
		writer := &wrapResponseWriter{
			ResponseWriter: w,
			status:         http.StatusOK,
		}
		fn(writer, r)
		addr := r.RemoteAddr
		if ip, found := header(r, "X-Forwarded-For"); found {
			addr = ip
		}
		if *verbose {
			log.Printf("[%s] %.3f %d %s %s",
				addr,
				time.Now().Sub(proc).Seconds(),
				writer.status,
				r.Method,
				r.URL,
			)
		}
	}
}

func proxy(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	obj := client.Bucket(params["bucket"]).Object(params["object"])
	attr, err := obj.Attrs(ctx)
	if err != nil {
		handleError(w, err)
		return
	}
	setStrHeader(w, "Content-Type", attr.ContentType)
	setStrHeader(w, "Content-Language", attr.ContentLanguage)
	setStrHeader(w, "Cache-Control", attr.CacheControl)
	setStrHeader(w, "Content-Encoding", attr.ContentEncoding)
	setStrHeader(w, "Content-Disposition", attr.ContentDisposition)
	setIntHeader(w, "Content-Length", attr.Size)
	// setTimeHeader(w, "Last-Modified", attr.Updated)
	// setStrHeader(w, "Expires", attr.Expires)
	objr, err := obj.NewReader(ctx)
	if err != nil {
		handleError(w, err)
		return
	}
	io.Copy(w, objr)
}

func main() {
	flag.Parse()

	var err error
	client, err = storage.NewClient(ctx)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	r := mux.NewRouter()
	r.HandleFunc("/{bucket:[0-9a-zA-Z-_]+}/{object:.*}", wrapper(proxy)).Methods("GET", "HEAD")

	log.Printf("[service] listening on %s", *bind)
	if err := http.ListenAndServe(*bind, r); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>fix cli flag.<commit_after>package main

import (
	"context"
	"flag"
	"io"
	"log"
	"net/http"
	"strconv"
	"time"

	"cloud.google.com/go/storage"
	"github.com/gorilla/mux"
)

var (
	bind    = flag.String("b", "127.0.0.1:8080", "bind address")
	verbose = flag.Bool("v", false, "show access log")
)

var (
	client *storage.Client
	ctx    = context.Background()
)

func handleError(w http.ResponseWriter, err error) {
	if err != nil {
		if err == storage.ErrObjectNotExist {
			http.Error(w, err.Error(), http.StatusNotFound)
		} else {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		return
	}
}

func header(r *http.Request, key string) (string, bool) {
	if r.Header == nil {
		return "", false
	}
	if candidate := r.Header[key]; len(candidate) > 0 {
		return candidate[0], true
	}
	return "", false
}

func setStrHeader(w http.ResponseWriter, key string, value string) {
	if value != "" {
		w.Header().Add(key, value)
	}
}

func setIntHeader(w http.ResponseWriter, key string, value int64) {
	if value > 0 {
		w.Header().Add(key, strconv.FormatInt(value, 10))
	}
}

func setTimeHeader(w http.ResponseWriter, key string, value time.Time) {
	w.Header().Add(key, value.UTC().Format(http.TimeFormat))
}

type wrapResponseWriter struct {
	http.ResponseWriter
	status int
}

func (w *wrapResponseWriter) WriteHeader(status int) {
	w.ResponseWriter.WriteHeader(status)
	w.status = status
}

func wrapper(fn func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		proc := time.Now()
		writer := &wrapResponseWriter{
			ResponseWriter: w,
			status:         http.StatusOK,
		}
		fn(writer, r)
		addr := r.RemoteAddr
		if ip, found := header(r, "X-Forwarded-For"); found {
			addr = ip
		}
		if *verbose {
			log.Printf("[%s] %.3f %d %s %s",
				addr,
				time.Now().Sub(proc).Seconds(),
				writer.status,
				r.Method,
				r.URL,
			)
		}
	}
}

func proxy(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	obj := client.Bucket(params["bucket"]).Object(params["object"])
	attr, err := obj.Attrs(ctx)
	if err != nil {
		handleError(w, err)
		return
	}
	setStrHeader(w, "Content-Type", attr.ContentType)
	setStrHeader(w, "Content-Language", attr.ContentLanguage)
	setStrHeader(w, "Cache-Control", attr.CacheControl)
	setStrHeader(w, "Content-Encoding", attr.ContentEncoding)
	setStrHeader(w, "Content-Disposition", attr.ContentDisposition)
	setIntHeader(w, "Content-Length", attr.Size)
	// setTimeHeader(w, "Last-Modified", attr.Updated)
	// setStrHeader(w, "Expires", attr.Expires)
	objr, err := obj.NewReader(ctx)
	if err != nil {
		handleError(w, err)
		return
	}
	io.Copy(w, objr)
}

func main() {
	flag.Parse()

	var err error
	client, err = storage.NewClient(ctx)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	r := mux.NewRouter()
	r.HandleFunc("/{bucket:[0-9a-zA-Z-_]+}/{object:.*}", wrapper(proxy)).Methods("GET", "HEAD")

	log.Printf("[service] listening on %s", *bind)
	if err := http.ListenAndServe(*bind, r); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/martinlindhe/imgcat/lib"

	"gopkg.in/alecthomas/kingpin.v2"
)

type fileList []string

// 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 (i *fileList) Set(value string) error {

	if !exists(value) {
		return fmt.Errorf("'%s' does not exist", value)
	}
	*i = append(*i, value)
	return nil
}

func (i *fileList) String() string {
	return ""
}

func (i *fileList) IsCumulative() bool {
	return true
}

func ImageList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*fileList)(target))
	return
}

var (
	files   = ImageList(kingpin.Arg("files", "Image files to show."))
	verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
)

func main() {
	// support -h for --help
	kingpin.CommandLine.HelpFlag.Short('h')
	kingpin.Parse()

	heading := false
	if len(*files) > 1 && *verbose {
		heading = true
	}

	for _, file := range *files {
		if heading {
			fmt.Printf("%s:\n", file)
		}
		imgcat.CatImage(file)
	}
}
<commit_msg>ImageList -> imageList<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/martinlindhe/imgcat/lib"

	"gopkg.in/alecthomas/kingpin.v2"
)

type fileList []string

// 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 (i *fileList) Set(value string) error {

	if !exists(value) {
		return fmt.Errorf("'%s' does not exist", value)
	}
	*i = append(*i, value)
	return nil
}

func (i *fileList) String() string {
	return ""
}

func (i *fileList) IsCumulative() bool {
	return true
}

func imageList(s kingpin.Settings) (target *[]string) {
	target = new([]string)
	s.SetValue((*fileList)(target))
	return
}

var (
	files   = imageList(kingpin.Arg("files", "Image files to show."))
	verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
)

func main() {
	// support -h for --help
	kingpin.CommandLine.HelpFlag.Short('h')
	kingpin.Parse()

	heading := false
	if len(*files) > 1 && *verbose {
		heading = true
	}

	for _, file := range *files {
		if heading {
			fmt.Printf("%s:\n", file)
		}
		imgcat.CatImage(file)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
	"github.com/motemen/go-cli"
)

// allow options like -role=... -role=...
type roleFullnamesFlag []string

var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`)

func (r *roleFullnamesFlag) String() string {
	return fmt.Sprint(*r)
}

func (r *roleFullnamesFlag) Set(input string) error {
	inputRoles := strings.Split(input, ",")
	*r = append(*r, inputRoles...)
	return nil
}

var logger = logging.GetLogger("main")

const (
	exitStatusOK = iota
	exitStatusError
)

func main() {
	cli.Run(os.Args[1:])
}

func printRetireUsage() {
	usage := fmt.Sprintf(`Usage of mackerel-agent retire:
  -conf string
        Config file path (Configs in this file are over-written by command line options)
        (default "%s")
  -force
        force retirement without prompting
  -apibase string
        API base (default "%s")
  -apikey string
        (DEPRECATED) API key from mackerel.io web site`,
		config.DefaultConfig.Conffile,
		config.DefaultConfig.Apibase)

	fmt.Fprintln(os.Stderr, usage)
	os.Exit(2)
}

func resolveConfigForRetire(fs *flag.FlagSet, argv []string) (*config.Config, bool, error) {
	var force = fs.Bool("force", false, "force retirement without prompting")
	fs.Usage = printRetireUsage
	conf, err := resolveConfig(fs, argv)
	return conf, *force, err
}

// resolveConfig parses command line arguments and loads config file to
// return config.Config information.
func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) {
	conf := &config.Config{}

	var (
		conffile      = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)")
		apibase       = fs.String("apibase", config.DefaultConfig.Apibase, "API base")
		pidfile       = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID")
		root          = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information")
		apikey        = fs.String("apikey", "", "(DEPRECATED) API key from mackerel.io web site")
		diagnostic    = fs.Bool("diagnostic", false, "Enables diagnostic features")
		verbose       bool
		roleFullnames roleFullnamesFlag
	)
	fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity")
	fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)")

	// The value of "role" option is internally "roll fullname",
	// but we call it "role" here for ease.
	fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)")

	fs.Parse(argv)

	conf, confErr := config.LoadConfig(*conffile)
	conf.Conffile = *conffile
	if confErr != nil {
		return nil, fmt.Errorf("Failed to load the config file: %s", confErr)
	}

	// overwrite config from file by config from args
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "apibase":
			conf.Apibase = *apibase
		case "apikey":
			conf.Apikey = *apikey
		case "pidfile":
			conf.Pidfile = *pidfile
		case "root":
			conf.Root = *root
		case "diagnostic":
			conf.Diagnostic = *diagnostic
		case "verbose", "v":
			conf.Verbose = verbose
		case "role":
			conf.Roles = roleFullnames
		}
	})

	r := []string{}
	for _, roleFullName := range conf.Roles {
		if !roleFullnamePattern.MatchString(roleFullName) {
			logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName)
		} else {
			r = append(r, roleFullName)
		}
	}
	conf.Roles = r

	if conf.Apikey == "" {
		return nil, fmt.Errorf("Apikey must be specified in the config file (or by the DEPRECATED command-line flag)")
	}
	return conf, nil
}

func createPidFile(pidfile string) error {
	if pidString, err := ioutil.ReadFile(pidfile); err == nil {
		if pid, err := strconv.Atoi(string(pidString)); err == nil {
			if existsPid(pid) {
				return fmt.Errorf("Pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
			}
			// Note mackerel-agent in windows can't remove pidfile during stoping the service
			logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
		} else {
			logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
		}
	}

	err := os.MkdirAll(filepath.Dir(pidfile), 0755)
	if err != nil {
		return err
	}
	file, err := os.Create(pidfile)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = fmt.Fprintf(file, "%d", os.Getpid())
	return err
}

func removePidFile(pidfile string) {
	if err := os.Remove(pidfile); err != nil {
		logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
	}
}

func start(conf *config.Config, termCh chan struct{}) error {
	if conf.Verbose {
		logging.SetLogLevel(logging.DEBUG)
	}
	logger.Infof("Starting mackerel-agent version:%s, rev:%s, apibase:%s", version.VERSION, version.GITCOMMIT, conf.Apibase)

	if err := createPidFile(conf.Pidfile); err != nil {
		return fmt.Errorf("createPidFile(%q) failed: %s", conf.Pidfile, err)
	}
	defer removePidFile(conf.Pidfile)

	ctx, err := command.Prepare(conf)
	if err != nil {
		return fmt.Errorf("command.Prepare failed: %s", err)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	return command.Run(ctx, termCh)
}

var maxTerminatingInterval = 30 * time.Second

func signalHandler(c chan os.Signal, ctx *command.Context, termCh chan struct{}) {
	received := false
	for sig := range c {
		if sig == syscall.SIGHUP {
			logger.Debugf("Received signal '%v'", sig)
			// TODO reload configuration file

			ctx.UpdateHostSpecs()
		} else {
			if !received {
				received = true
				logger.Infof(
					"Received signal '%v', try graceful shutdown up to %f seconds. If you want force shutdown immediately, send a signal again.",
					sig,
					maxTerminatingInterval.Seconds())
			} else {
				logger.Infof("Received signal '%v' again, force shutdown.", sig)
			}
			termCh <- struct{}{}
			go func() {
				time.Sleep(maxTerminatingInterval)
				logger.Infof("Timed out. force shutdown.")
				termCh <- struct{}{}
			}()
		}
	}
}
<commit_msg>exitStatusOK and exitStatusError are no longer used<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
	"github.com/motemen/go-cli"
)

// allow options like -role=... -role=...
type roleFullnamesFlag []string

var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`)

func (r *roleFullnamesFlag) String() string {
	return fmt.Sprint(*r)
}

func (r *roleFullnamesFlag) Set(input string) error {
	inputRoles := strings.Split(input, ",")
	*r = append(*r, inputRoles...)
	return nil
}

var logger = logging.GetLogger("main")

func main() {
	cli.Run(os.Args[1:])
}

func printRetireUsage() {
	usage := fmt.Sprintf(`Usage of mackerel-agent retire:
  -conf string
        Config file path (Configs in this file are over-written by command line options)
        (default "%s")
  -force
        force retirement without prompting
  -apibase string
        API base (default "%s")
  -apikey string
        (DEPRECATED) API key from mackerel.io web site`,
		config.DefaultConfig.Conffile,
		config.DefaultConfig.Apibase)

	fmt.Fprintln(os.Stderr, usage)
	os.Exit(2)
}

func resolveConfigForRetire(fs *flag.FlagSet, argv []string) (*config.Config, bool, error) {
	var force = fs.Bool("force", false, "force retirement without prompting")
	fs.Usage = printRetireUsage
	conf, err := resolveConfig(fs, argv)
	return conf, *force, err
}

// resolveConfig parses command line arguments and loads config file to
// return config.Config information.
func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) {
	conf := &config.Config{}

	var (
		conffile      = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)")
		apibase       = fs.String("apibase", config.DefaultConfig.Apibase, "API base")
		pidfile       = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID")
		root          = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information")
		apikey        = fs.String("apikey", "", "(DEPRECATED) API key from mackerel.io web site")
		diagnostic    = fs.Bool("diagnostic", false, "Enables diagnostic features")
		verbose       bool
		roleFullnames roleFullnamesFlag
	)
	fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity")
	fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)")

	// The value of "role" option is internally "roll fullname",
	// but we call it "role" here for ease.
	fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)")

	fs.Parse(argv)

	conf, confErr := config.LoadConfig(*conffile)
	conf.Conffile = *conffile
	if confErr != nil {
		return nil, fmt.Errorf("Failed to load the config file: %s", confErr)
	}

	// overwrite config from file by config from args
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "apibase":
			conf.Apibase = *apibase
		case "apikey":
			conf.Apikey = *apikey
		case "pidfile":
			conf.Pidfile = *pidfile
		case "root":
			conf.Root = *root
		case "diagnostic":
			conf.Diagnostic = *diagnostic
		case "verbose", "v":
			conf.Verbose = verbose
		case "role":
			conf.Roles = roleFullnames
		}
	})

	r := []string{}
	for _, roleFullName := range conf.Roles {
		if !roleFullnamePattern.MatchString(roleFullName) {
			logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName)
		} else {
			r = append(r, roleFullName)
		}
	}
	conf.Roles = r

	if conf.Apikey == "" {
		return nil, fmt.Errorf("Apikey must be specified in the config file (or by the DEPRECATED command-line flag)")
	}
	return conf, nil
}

func createPidFile(pidfile string) error {
	if pidString, err := ioutil.ReadFile(pidfile); err == nil {
		if pid, err := strconv.Atoi(string(pidString)); err == nil {
			if existsPid(pid) {
				return fmt.Errorf("Pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
			}
			// Note mackerel-agent in windows can't remove pidfile during stoping the service
			logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
		} else {
			logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
		}
	}

	err := os.MkdirAll(filepath.Dir(pidfile), 0755)
	if err != nil {
		return err
	}
	file, err := os.Create(pidfile)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = fmt.Fprintf(file, "%d", os.Getpid())
	return err
}

func removePidFile(pidfile string) {
	if err := os.Remove(pidfile); err != nil {
		logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
	}
}

func start(conf *config.Config, termCh chan struct{}) error {
	if conf.Verbose {
		logging.SetLogLevel(logging.DEBUG)
	}
	logger.Infof("Starting mackerel-agent version:%s, rev:%s, apibase:%s", version.VERSION, version.GITCOMMIT, conf.Apibase)

	if err := createPidFile(conf.Pidfile); err != nil {
		return fmt.Errorf("createPidFile(%q) failed: %s", conf.Pidfile, err)
	}
	defer removePidFile(conf.Pidfile)

	ctx, err := command.Prepare(conf)
	if err != nil {
		return fmt.Errorf("command.Prepare failed: %s", err)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	return command.Run(ctx, termCh)
}

var maxTerminatingInterval = 30 * time.Second

func signalHandler(c chan os.Signal, ctx *command.Context, termCh chan struct{}) {
	received := false
	for sig := range c {
		if sig == syscall.SIGHUP {
			logger.Debugf("Received signal '%v'", sig)
			// TODO reload configuration file

			ctx.UpdateHostSpecs()
		} else {
			if !received {
				received = true
				logger.Infof(
					"Received signal '%v', try graceful shutdown up to %f seconds. If you want force shutdown immediately, send a signal again.",
					sig,
					maxTerminatingInterval.Seconds())
			} else {
				logger.Infof("Received signal '%v' again, force shutdown.", sig)
			}
			termCh <- struct{}{}
			go func() {
				time.Sleep(maxTerminatingInterval)
				logger.Infof("Timed out. force shutdown.")
				termCh <- struct{}{}
			}()
		}
	}
}
<|endoftext|>


<commit_before>//go:generate go run pkg/codegen/cleanup/main.go
//go:generate /bin/rm -rf pkg/generated
//go:generate go run pkg/codegen/main.go
//go:generate go fmt pkg/deploy/zz_generated_bindata.go
//go:generate go fmt pkg/static/zz_generated_bindata.go

package main

import (
	"os"

	"github.com/rancher/k3s/pkg/cli/agent"
	"github.com/rancher/k3s/pkg/cli/cmds"
	"github.com/rancher/k3s/pkg/cli/crictl"
	"github.com/rancher/k3s/pkg/cli/kubectl"
	"github.com/rancher/k3s/pkg/cli/server"
	"github.com/rancher/spur/cli"
	"github.com/sirupsen/logrus"
)

func main() {
	app := cmds.NewApp()
	app.Commands = []cli.Command{
		cmds.NewServerCommand(server.Run),
		cmds.NewAgentCommand(agent.Run),
		cmds.NewKubectlCommand(kubectl.Run),
		cmds.NewCRICTL(crictl.Run),
	}

	if err := app.Run(os.Args); err != nil {
		logrus.Fatal(err)
	}
}
<commit_msg>Fix cli in main.go (#2043)<commit_after>//go:generate go run pkg/codegen/cleanup/main.go
//go:generate /bin/rm -rf pkg/generated
//go:generate go run pkg/codegen/main.go
//go:generate go fmt pkg/deploy/zz_generated_bindata.go
//go:generate go fmt pkg/static/zz_generated_bindata.go

package main

import (
	"os"

	"github.com/rancher/k3s/pkg/cli/agent"
	"github.com/rancher/k3s/pkg/cli/cmds"
	"github.com/rancher/k3s/pkg/cli/crictl"
	"github.com/rancher/k3s/pkg/cli/kubectl"
	"github.com/rancher/k3s/pkg/cli/server"
	"github.com/rancher/spur/cli"
	"github.com/sirupsen/logrus"
)

func main() {
	app := cmds.NewApp()
	app.Commands = []*cli.Command{
		cmds.NewServerCommand(server.Run),
		cmds.NewAgentCommand(agent.Run),
		cmds.NewKubectlCommand(kubectl.Run),
		cmds.NewCRICTL(crictl.Run),
	}

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