<commit_before>package main

import (
	"bytes"
	"errors"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"os"

	"github.com/develed/develed/imconv"
	srv "github.com/develed/develed/services"
	"golang.org/x/crypto/ssh/terminal"
	"golang.org/x/net/context"

	tm "github.com/buger/goterm"
)

// TermSink redirects any image written to it to the terminal's stdout.
// It requires a Truecolor-capable terminal in order to render images correctly.
type TermSink struct{}

// NewTermSink creates a new TermSink. It returns an error if the sdout of the
// calling process is not a terminal.
func NewTermSink() (*TermSink, error) {
	if !terminal.IsTerminal(int(os.Stdout.Fd())) {
		return nil, errors.New("TermSink requires stdout to be a terminal")
	}
	return &TermSink{}, nil
}

func (ts *TermSink) Draw(ctx context.Context, req *srv.DrawRequest) (*srv.DrawResponse, error) {
	img, _, err := image.Decode(bytes.NewReader(req.Data))
	if err != nil {
		return nil, err
	}

	sz := img.Bounds().Size()
	tm.Clear()
	tm.MoveCursor(0, 0)
	for y := 0; y < sz.Y; y++ {
		for x := 0; x < sz.X; x++ {
			col := imconv.NormalizeColor(img.At(x, y))
			tm.Printf("\033[48;2;%d;%d;%dm ", col.R, col.G, col.B)
		}
		tm.Print("\033[0m\n")
	}
	tm.Flush()
	return &srv.DrawResponse{Code: 0, Status: "OK"}, nil
}
<commit_msg>Revert "dspd: Use goterm to redraw terminal frame in same position."<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	_ "image/jpeg"
	_ "image/png"
	"os"

	"github.com/develed/develed/imconv"
	srv "github.com/develed/develed/services"
	"golang.org/x/crypto/ssh/terminal"
	"golang.org/x/net/context"
)

// TermSink redirects any image written to it to the terminal's stdout.
// It requires a Truecolor-capable terminal in order to render images correctly.
type TermSink struct{}

// NewTermSink creates a new TermSink. It returns an error if the sdout of the
// calling process is not a terminal.
func NewTermSink() (*TermSink, error) {
	if !terminal.IsTerminal(int(os.Stdout.Fd())) {
		return nil, errors.New("TermSink requires stdout to be a terminal")
	}
	return &TermSink{}, nil
}

func (ts *TermSink) Draw(ctx context.Context, req *srv.DrawRequest) (*srv.DrawResponse, error) {
	img, _, err := image.Decode(bytes.NewReader(req.Data))
	if err != nil {
		return nil, err
	}

	sz := img.Bounds().Size()
	for y := 0; y < sz.Y; y++ {
		for x := 0; x < sz.X; x++ {
			col := imconv.NormalizeColor(img.At(x, y))
			if _, err := fmt.Printf("\033[48;2;%d;%d;%dm ", col.R, col.G, col.B); err != nil {
				return nil, err
			}
		}
		if _, err := fmt.Print("\033[0m\n"); err != nil {
			return nil, err
		}
	}
	return &srv.DrawResponse{Code: 0, Status: "OK"}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/robdimsdale/garagepi"
)

var (
	port = flag.String("port", "9999", "Port for server to bind to.")

	webcamHost = flag.String("webcamHost", "localhost", "Host of webcam image.")
	webcamPort = flag.String("webcamPort", "8080", "Port of webcam image.")
)

func main() {
	flag.Parse()

	loggingOn := true
	l := garagepi.NewLoggerImpl(loggingOn)

	// The location of the 'assets' directory
	// is relative to where the compilation takes place
	// This assumes compliation happens from the root directory
	osHelper := garagepi.NewOsHelperImpl(l, "assets")
	httpHelper := garagepi.NewHttpHelperImpl()

	rtr := mux.NewRouter()

	e := garagepi.NewExecutor(
		l,
		httpHelper,
		osHelper,
		*webcamHost,
		*webcamPort)

	staticFileSystem, err := osHelper.GetStaticFileSystem()
	if err != nil {
		panic(err)
	}
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(staticFileSystem)))

	rtr.HandleFunc("/", e.HomepageHandler).Methods("GET")
	rtr.HandleFunc("/webcam", e.WebcamHandler).Methods("GET")
	rtr.HandleFunc("/toggle", e.ToggleDoorHandler).Methods("POST")

	http.Handle("/", rtr)
	l.Log("Listening on port " + *port + "...")
	http.ListenAndServe(":"+*port, nil)
}
<commit_msg>Add loggingOn flag, true by default.<commit_after>package main

import (
	"flag"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/robdimsdale/garagepi"
)

var (
	port = flag.String("port", "9999", "Port for server to bind to.")

	webcamHost = flag.String("webcamHost", "localhost", "Host of webcam image.")
	webcamPort = flag.String("webcamPort", "8080", "Port of webcam image.")

	loggingOn = flag.Bool("loggingOn", true, "Whether logging is enabled.")
)

func main() {
	flag.Parse()

	logger := garagepi.NewLoggerImpl(*loggingOn)

	// The location of the 'assets' directory
	// is relative to where the compilation takes place
	// This assumes compliation happens from the root directory
	osHelper := garagepi.NewOsHelperImpl(logger, "assets")
	httpHelper := garagepi.NewHttpHelperImpl()

	rtr := mux.NewRouter()

	e := garagepi.NewExecutor(
		logger,
		httpHelper,
		osHelper,
		*webcamHost,
		*webcamPort)

	staticFileSystem, err := osHelper.GetStaticFileSystem()
	if err != nil {
		panic(err)
	}
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(staticFileSystem)))

	rtr.HandleFunc("/", e.HomepageHandler).Methods("GET")
	rtr.HandleFunc("/webcam", e.WebcamHandler).Methods("GET")
	rtr.HandleFunc("/toggle", e.ToggleDoorHandler).Methods("POST")

	http.Handle("/", rtr)
	logger.Log("Listening on port " + *port + "...")
	http.ListenAndServe(":"+*port, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/mercari/gaurun/buford/token"
	"github.com/mercari/gaurun/gaurun"
)

const (
	DefaultPidPermission = 0644
)

func main() {
	versionPrinted := flag.Bool("v", false, "gaurun version")
	confPath := flag.String("c", "", "configuration file path for gaurun")
	listenPort := flag.String("p", "", "port number or unix socket path")
	workerNum := flag.Int64("w", 0, "number of workers for push notification")
	queueNum := flag.Int64("q", 0, "size of internal queue for push notification")
	flag.Parse()

	if *versionPrinted {
		gaurun.PrintVersion()
		return
	}

	// set default parameters
	gaurun.ConfGaurun = gaurun.BuildDefaultConf()

	// load configuration
	conf, err := gaurun.LoadConf(gaurun.ConfGaurun, *confPath)
	if err != nil {
		gaurun.LogSetupFatal(err)
	}
	gaurun.ConfGaurun = conf

	// overwrite if port is specified by flags
	if *listenPort != "" {
		gaurun.ConfGaurun.Core.Port = *listenPort
	}

	// overwrite if workerNum is specified by flags
	if *workerNum > 0 {
		gaurun.ConfGaurun.Core.WorkerNum = *workerNum
	}

	// overwrite if queueNum is specified by flags
	if *queueNum > 0 {
		gaurun.ConfGaurun.Core.QueueNum = *queueNum
	}

	// set logger
	accessLogger, accessLogReopener, err := gaurun.InitLog(gaurun.ConfGaurun.Log.AccessLog, "info")
	if err != nil {
		gaurun.LogSetupFatal(err)
	}
	errorLogger, errorLogReopener, err := gaurun.InitLog(gaurun.ConfGaurun.Log.ErrorLog, gaurun.ConfGaurun.Log.Level)
	if err != nil {
		gaurun.LogSetupFatal(err)
	}

	gaurun.LogAccess = accessLogger
	gaurun.LogError = errorLogger

	if !gaurun.ConfGaurun.Ios.Enabled && !gaurun.ConfGaurun.Android.Enabled {
		gaurun.LogSetupFatal(fmt.Errorf("no platform has been enabled"))
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		if gaurun.ConfGaurun.Ios.PemCertPath != "" && gaurun.ConfGaurun.Ios.PemKeyPath != "" {
			gaurun.CertificatePemIos.Cert, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemCertPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the certification file for iOS was not found"))
			}

			gaurun.CertificatePemIos.Key, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemKeyPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the key file for iOS was not found"))
			}
		} else if gaurun.ConfGaurun.Ios.AuthKeyPath != "" && conf.Ios.KeyID != "" && conf.Ios.TeamID != "" {
			gaurun.AuthKey, err = token.AuthKeyFromFile(gaurun.ConfGaurun.Ios.AuthKeyPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the auth key file for iOS was not loading: %v", err))
			}
		} else {
			gaurun.LogSetupFatal(fmt.Errorf("the key file or APNsAuthKey file for iOS was not found"))
		}

	}

	if gaurun.ConfGaurun.Android.Enabled {
		if gaurun.ConfGaurun.Android.ApiKey == "" {
			gaurun.LogSetupFatal(fmt.Errorf("the APIKey for Android cannot be empty"))
		}
	}

	sigHUPChan := make(chan os.Signal, 1)
	signal.Notify(sigHUPChan, syscall.SIGHUP)

	sighupHandler := func() {
		if err := accessLogReopener.Reopen(); err != nil {
			gaurun.LogError.Warn(fmt.Sprintf("failed to reopen access log: %v", err))
		}
		if err := errorLogReopener.Reopen(); err != nil {
			gaurun.LogError.Warn(fmt.Sprintf("failed to reopen error log: %v", err))
		}
	}

	go signalHandler(sigHUPChan, sighupHandler)

	if len(conf.Core.Pid) > 0 {
		if _, err := os.Stat(filepath.Dir(conf.Core.Pid)); os.IsNotExist(err) {
			gaurun.LogSetupFatal(fmt.Errorf("directory for pid file is not exist: %v", err))
		} else if err := ioutil.WriteFile(conf.Core.Pid, []byte(strconv.Itoa(os.Getpid())), DefaultPidPermission); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to create a pid file: %v", err))
		}
	}

	if gaurun.ConfGaurun.Android.Enabled {
		if err := gaurun.InitGCMClient(); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to init gcm/fcm client: %v", err))
		}
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		if err := gaurun.InitAPNSClient(); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to init http client for APNs: %v", err))
		}
	}
	gaurun.InitStat()
	gaurun.StartPushWorkers(gaurun.ConfGaurun.Core.WorkerNum, gaurun.ConfGaurun.Core.QueueNum)

	mux := http.NewServeMux()
	gaurun.RegisterHandlers(mux)

	server := &http.Server{
		Handler: mux,
	}
	go func() {
		gaurun.LogError.Info("start server")
		if err := gaurun.RunServer(server, &gaurun.ConfGaurun); err != nil {
			gaurun.LogError.Info(fmt.Sprintf("failed to serve: %s", err))
		}
	}()

	// Graceful shutdown (kicked by SIGTERM).
	//
	// First, it shutdowns server and stops accepting new requests.
	// Then wait until all remaining queues in buffer are flushed.
	sigTERMChan := make(chan os.Signal, 1)
	signal.Notify(sigTERMChan, syscall.SIGTERM)

	<-sigTERMChan
	gaurun.LogError.Info("shutdown server")
	timeout := time.Duration(conf.Core.ShutdownTimeout) * time.Second
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		gaurun.LogError.Error(fmt.Sprintf("failed to shutdown server: %v", err))
	}

	// Start a goroutine to log number of job queue.
	go func() {
		for {
			queue := len(gaurun.QueueNotification)
			if queue == 0 {
				break
			}

			gaurun.LogError.Info(fmt.Sprintf("wait until queue is empty. Current queue len: %d", queue))
			time.Sleep(1 * time.Second)
		}
	}()

	// Block until all pusher worker job is done.
	gaurun.PusherWg.Wait()

	gaurun.LogError.Info("successfully shutdown")
}

func signalHandler(ch <-chan os.Signal, sighupFn func()) {
	for sig := range ch {
		switch sig {
		case syscall.SIGHUP:
			sighupFn()
		}
	}
}
<commit_msg>use gaurun.ConfGaurun<commit_after>package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"github.com/mercari/gaurun/buford/token"
	"github.com/mercari/gaurun/gaurun"
)

const (
	DefaultPidPermission = 0644
)

func main() {
	versionPrinted := flag.Bool("v", false, "gaurun version")
	confPath := flag.String("c", "", "configuration file path for gaurun")
	listenPort := flag.String("p", "", "port number or unix socket path")
	workerNum := flag.Int64("w", 0, "number of workers for push notification")
	queueNum := flag.Int64("q", 0, "size of internal queue for push notification")
	flag.Parse()

	if *versionPrinted {
		gaurun.PrintVersion()
		return
	}

	// set default parameters
	gaurun.ConfGaurun = gaurun.BuildDefaultConf()

	// load configuration
	conf, err := gaurun.LoadConf(gaurun.ConfGaurun, *confPath)
	if err != nil {
		gaurun.LogSetupFatal(err)
	}
	gaurun.ConfGaurun = conf

	// overwrite if port is specified by flags
	if *listenPort != "" {
		gaurun.ConfGaurun.Core.Port = *listenPort
	}

	// overwrite if workerNum is specified by flags
	if *workerNum > 0 {
		gaurun.ConfGaurun.Core.WorkerNum = *workerNum
	}

	// overwrite if queueNum is specified by flags
	if *queueNum > 0 {
		gaurun.ConfGaurun.Core.QueueNum = *queueNum
	}

	// set logger
	accessLogger, accessLogReopener, err := gaurun.InitLog(gaurun.ConfGaurun.Log.AccessLog, "info")
	if err != nil {
		gaurun.LogSetupFatal(err)
	}
	errorLogger, errorLogReopener, err := gaurun.InitLog(gaurun.ConfGaurun.Log.ErrorLog, gaurun.ConfGaurun.Log.Level)
	if err != nil {
		gaurun.LogSetupFatal(err)
	}

	gaurun.LogAccess = accessLogger
	gaurun.LogError = errorLogger

	if !gaurun.ConfGaurun.Ios.Enabled && !gaurun.ConfGaurun.Android.Enabled {
		gaurun.LogSetupFatal(fmt.Errorf("no platform has been enabled"))
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		if gaurun.ConfGaurun.Ios.PemCertPath != "" && gaurun.ConfGaurun.Ios.PemKeyPath != "" {
			gaurun.CertificatePemIos.Cert, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemCertPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the certification file for iOS was not found"))
			}

			gaurun.CertificatePemIos.Key, err = ioutil.ReadFile(gaurun.ConfGaurun.Ios.PemKeyPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the key file for iOS was not found"))
			}
		} else if gaurun.ConfGaurun.Ios.AuthKeyPath != "" && gaurun.ConfGaurun.Ios.KeyID != "" && gaurun.ConfGaurun.Ios.TeamID != "" {
			gaurun.AuthKey, err = token.AuthKeyFromFile(gaurun.ConfGaurun.Ios.AuthKeyPath)
			if err != nil {
				gaurun.LogSetupFatal(fmt.Errorf("the auth key file for iOS was not loading: %v", err))
			}
		} else {
			gaurun.LogSetupFatal(fmt.Errorf("the key file or APNsAuthKey file for iOS was not found"))
		}

	}

	if gaurun.ConfGaurun.Android.Enabled {
		if gaurun.ConfGaurun.Android.ApiKey == "" {
			gaurun.LogSetupFatal(fmt.Errorf("the APIKey for Android cannot be empty"))
		}
	}

	sigHUPChan := make(chan os.Signal, 1)
	signal.Notify(sigHUPChan, syscall.SIGHUP)

	sighupHandler := func() {
		if err := accessLogReopener.Reopen(); err != nil {
			gaurun.LogError.Warn(fmt.Sprintf("failed to reopen access log: %v", err))
		}
		if err := errorLogReopener.Reopen(); err != nil {
			gaurun.LogError.Warn(fmt.Sprintf("failed to reopen error log: %v", err))
		}
	}

	go signalHandler(sigHUPChan, sighupHandler)

	if len(conf.Core.Pid) > 0 {
		if _, err := os.Stat(filepath.Dir(conf.Core.Pid)); os.IsNotExist(err) {
			gaurun.LogSetupFatal(fmt.Errorf("directory for pid file is not exist: %v", err))
		} else if err := ioutil.WriteFile(conf.Core.Pid, []byte(strconv.Itoa(os.Getpid())), DefaultPidPermission); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to create a pid file: %v", err))
		}
	}

	if gaurun.ConfGaurun.Android.Enabled {
		if err := gaurun.InitGCMClient(); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to init gcm/fcm client: %v", err))
		}
	}

	if gaurun.ConfGaurun.Ios.Enabled {
		if err := gaurun.InitAPNSClient(); err != nil {
			gaurun.LogSetupFatal(fmt.Errorf("failed to init http client for APNs: %v", err))
		}
	}
	gaurun.InitStat()
	gaurun.StartPushWorkers(gaurun.ConfGaurun.Core.WorkerNum, gaurun.ConfGaurun.Core.QueueNum)

	mux := http.NewServeMux()
	gaurun.RegisterHandlers(mux)

	server := &http.Server{
		Handler: mux,
	}
	go func() {
		gaurun.LogError.Info("start server")
		if err := gaurun.RunServer(server, &gaurun.ConfGaurun); err != nil {
			gaurun.LogError.Info(fmt.Sprintf("failed to serve: %s", err))
		}
	}()

	// Graceful shutdown (kicked by SIGTERM).
	//
	// First, it shutdowns server and stops accepting new requests.
	// Then wait until all remaining queues in buffer are flushed.
	sigTERMChan := make(chan os.Signal, 1)
	signal.Notify(sigTERMChan, syscall.SIGTERM)

	<-sigTERMChan
	gaurun.LogError.Info("shutdown server")
	timeout := time.Duration(conf.Core.ShutdownTimeout) * time.Second
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		gaurun.LogError.Error(fmt.Sprintf("failed to shutdown server: %v", err))
	}

	// Start a goroutine to log number of job queue.
	go func() {
		for {
			queue := len(gaurun.QueueNotification)
			if queue == 0 {
				break
			}

			gaurun.LogError.Info(fmt.Sprintf("wait until queue is empty. Current queue len: %d", queue))
			time.Sleep(1 * time.Second)
		}
	}()

	// Block until all pusher worker job is done.
	gaurun.PusherWg.Wait()

	gaurun.LogError.Info("successfully shutdown")
}

func signalHandler(ch <-chan os.Signal, sighupFn func()) {
	for sig := range ch {
		switch sig {
		case syscall.SIGHUP:
			sighupFn()
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gin-gonic/gin"
)

func BindRoutes(router *gin.Engine) {

	//front end
	router.GET("/", Index)
	router.GET("/about/", About)
	router.GET("/contact/", ContactRender)
	router.POST("/contact/", ContactSend)

	//sign up
	router.GET("/signup/", SignupRender)
	router.POST("/signup/", Signup)

	//social sign up
	router.POST("/signup/social/", Index)
	router.GET("/signup/twitter/", Index)
	router.GET("/signup/twitter/callback/", Index)
	router.GET("/signup/github/", Index)
	router.GET("/signup/github/callback/", Index)
	router.GET("/signup/facebook/", Index)
	router.GET("/signup/facebook/callback/", Index)
	router.GET("/signup/google/", Index)
	router.GET("/signup/google/callback/", Index)
	router.GET("/signup/tumblr/", Index)
	router.GET("/signup/tumblr/callback/", Index)

	//login/out
	router.GET("/login/", LoginRender)
	router.POST("/login/", Login)
	router.GET("/login/forgot/", ForgotRender)
	router.POST("/login/forgot/", Index)
	router.GET("/login/reset/", Index)
	router.GET("/login/reset/:email/:token/", Index)
	router.PUT("/login/reset/:email/:token/", Index)
	router.GET("/logout/", Logout)// todo doesn't work

	//social login
	router.GET("/login/twitter/", Index)
	router.GET("/login/twitter/callback/", Index)
	router.GET("/login/github/", Index)
	router.GET("/login/github/callback/", Index)
	router.GET("/login/facebook/", Index)
	router.GET("/login/facebook/callback/", Index)
	router.GET("/login/google/", Index)
	router.GET("/login/google/callback/", Index)
	router.GET("/login/tumblr/", Index)
	router.GET("/login/tumblr/callback/", Index)

	//admin
	//app.all('/admin*', ensureAuthenticated); TODO necessary midleware
	//app.all('/admin*', ensureAdmin);
	router.GET("/admin/", Index)

	//admin > users
	router.GET("/admin/users/", Index)
	router.POST("/admin/users/", Index)
	router.GET("/admin/users/:id/", Index)
	router.PUT("/admin/users/:id/", Index)
	router.PUT("/admin/users/:id/password/", Index)
	router.PUT("/admin/users/:id/role-admin/", Index)
	router.DELETE("/admin/users/:id/role-admin/", Index)
	router.PUT("/admin/users/:id/role-account/", Index)
	router.DELETE("/admin/users/:id/role-account/", Index)
	router.DELETE("/admin/users/:id/", Index)

	//admin > administrators
	router.GET("/admin/administrators/", Index)
	router.POST("/admin/administrators/", Index)
	router.GET("/admin/administrators/:id/", Index)
	router.PUT("/admin/administrators/:id/", Index)
	router.PUT("/admin/administrators/:id/permissions/", Index)
	router.PUT("/admin/administrators/:id/groups/", Index)
	router.PUT("/admin/administrators/:id/user/", Index)
	router.DELETE("/admin/administrators/:id/user/", Index)
	router.DELETE("/admin/administrators/:id/", Index)

	//admin > admin groups
	router.GET("/admin/admin-groups/", Index)
	router.POST("/admin/admin-groups/", Index)
	router.GET("/admin/admin-groups/:id/", Index)
	router.PUT("/admin/admin-groups/:id/", Index)
	router.PUT("/admin/admin-groups/:id/permissions/", Index)
	router.DELETE("/admin/admin-groups/:id/", Index)

	//admin > accounts
	router.GET("/admin/accounts/", Index)
	router.POST("/admin/accounts/", Index)
	router.GET("/admin/accounts/:id/", Index)
	router.PUT("/admin/accounts/:id/", Index)
	router.PUT("/admin/accounts/:id/user/", Index)
	router.DELETE("/admin/accounts/:id/user/", Index)
	router.POST("/admin/accounts/:id/notes/", Index)
	router.POST("/admin/accounts/:id/status/", Index)
	router.DELETE("/admin/accounts/:id/", Index)

	//admin > statuses
	router.GET("/admin/statuses/", Index)
	router.POST("/admin/statuses/", Index)
	router.GET("/admin/statuses/:id/", Index)
	router.PUT("/admin/statuses/:id/", Index)
	router.DELETE("/admin/statuses/:id/", Index)

	//admin > categories
	router.GET("/admin/categories/", Index)
	router.POST("/admin/categories/", Index)
	router.GET("/admin/categories/:id/", Index)
	router.PUT("/admin/categories/:id/", Index)
	router.DELETE("/admin/categories/:id/", Index)

	//admin > search
	router.GET("/admin/search/", Index)

	//account
	//app.all('/account*', ensureAuthenticated); //TODO necessary midleware
	//app.all('/account*', ensureAccount);
	router.GET("/account/", AccountRender)

	//account > verification
	router.GET("/account/verification/", AccountVerification)
	router.POST("/account/verification/", Index)
	router.GET("/account/verification/:token/", Index)

	//account > settings
	router.GET("/account/settings/", AccountSettingsRender)
	router.PUT("/account/settings/", Index)
	router.PUT("/account/settings/identity/", Index)
	router.PUT("/account/settings/password/", Index)

	//account > settings > social
	router.GET("/account/settings/twitter/", Index)
	router.GET("/account/settings/twitter/callback/", Index)
	router.GET("/account/settings/twitter/disconnect/", Index)
	router.GET("/account/settings/github/", Index)
	router.GET("/account/settings/github/callback/", Index)
	router.GET("/account/settings/github/disconnect/", Index)
	router.GET("/account/settings/facebook/", Index)
	router.GET("/account/settings/facebook/callback/", Index)
	router.GET("/account/settings/facebook/disconnect/", Index)
	router.GET("/account/settings/google/", Index)
	router.GET("/account/settings/google/callback/", Index)
	router.GET("/account/settings/google/disconnect/", Index)
	router.GET("/account/settings/tumblr/", Index)
	router.GET("/account/settings/tumblr/callback/", Index)
	router.GET("/account/settings/tumblr/disconnect/", Index)

	//route not found
	router.NoRoute(Status404Render)
}<commit_msg>grouped routers<commit_after>package main

import (
	"github.com/gin-gonic/gin"
)

func BindRoutes(router *gin.Engine) {

	//front end
	router.GET("/", Index)
	router.GET("/about/", About)
	router.GET("/contact/", ContactRender)
	router.POST("/contact/", ContactSend)

	//sign up
	router.GET("/signup/", SignupRender)
	router.POST("/signup/", Signup)

	//social sign up
	router.POST("/signup/social/", Index)
	router.GET("/signup/twitter/", Index)
	router.GET("/signup/twitter/callback/", Index)
	router.GET("/signup/github/", Index)
	router.GET("/signup/github/callback/", Index)
	router.GET("/signup/facebook/", Index)
	router.GET("/signup/facebook/callback/", Index)
	router.GET("/signup/google/", Index)
	router.GET("/signup/google/callback/", Index)
	router.GET("/signup/tumblr/", Index)
	router.GET("/signup/tumblr/callback/", Index)

	//login/out
	router.GET("/login/", LoginRender)
	router.POST("/login/", Login)
	router.GET("/login/forgot/", ForgotRender)
	router.POST("/login/forgot/", Index)
	router.GET("/login/reset/", Index)
	router.GET("/login/reset/:email/:token/", Index)
	router.PUT("/login/reset/:email/:token/", Index)
	router.GET("/logout/", Logout)// todo doesn't work

	//social login
	router.GET("/login/twitter/", Index)
	router.GET("/login/twitter/callback/", Index)
	router.GET("/login/github/", Index)
	router.GET("/login/github/callback/", Index)
	router.GET("/login/facebook/", Index)
	router.GET("/login/facebook/callback/", Index)
	router.GET("/login/google/", Index)
	router.GET("/login/google/callback/", Index)
	router.GET("/login/tumblr/", Index)
	router.GET("/login/tumblr/callback/", Index)

	//admin
	//app.all('/admin*', ensureAuthenticated); TODO necessary midleware
	//app.all('/admin*', ensureAdmin);
	router.GET("/admin/", Index)

	//admin > users
	router.GET("/admin/users/", Index)
	router.POST("/admin/users/", Index)
	router.GET("/admin/users/:id/", Index)
	router.PUT("/admin/users/:id/", Index)
	router.PUT("/admin/users/:id/password/", Index)
	router.PUT("/admin/users/:id/role-admin/", Index)
	router.DELETE("/admin/users/:id/role-admin/", Index)
	router.PUT("/admin/users/:id/role-account/", Index)
	router.DELETE("/admin/users/:id/role-account/", Index)
	router.DELETE("/admin/users/:id/", Index)

	//admin > administrators
	router.GET("/admin/administrators/", Index)
	router.POST("/admin/administrators/", Index)
	router.GET("/admin/administrators/:id/", Index)
	router.PUT("/admin/administrators/:id/", Index)
	router.PUT("/admin/administrators/:id/permissions/", Index)
	router.PUT("/admin/administrators/:id/groups/", Index)
	router.PUT("/admin/administrators/:id/user/", Index)
	router.DELETE("/admin/administrators/:id/user/", Index)
	router.DELETE("/admin/administrators/:id/", Index)

	//admin > admin groups
	router.GET("/admin/admin-groups/", Index)
	router.POST("/admin/admin-groups/", Index)
	router.GET("/admin/admin-groups/:id/", Index)
	router.PUT("/admin/admin-groups/:id/", Index)
	router.PUT("/admin/admin-groups/:id/permissions/", Index)
	router.DELETE("/admin/admin-groups/:id/", Index)

	//admin > accounts
	router.GET("/admin/accounts/", Index)
	router.POST("/admin/accounts/", Index)
	router.GET("/admin/accounts/:id/", Index)
	router.PUT("/admin/accounts/:id/", Index)
	router.PUT("/admin/accounts/:id/user/", Index)
	router.DELETE("/admin/accounts/:id/user/", Index)
	router.POST("/admin/accounts/:id/notes/", Index)
	router.POST("/admin/accounts/:id/status/", Index)
	router.DELETE("/admin/accounts/:id/", Index)

	//admin > statuses
	router.GET("/admin/statuses/", Index)
	router.POST("/admin/statuses/", Index)
	router.GET("/admin/statuses/:id/", Index)
	router.PUT("/admin/statuses/:id/", Index)
	router.DELETE("/admin/statuses/:id/", Index)

	//admin > categories
	router.GET("/admin/categories/", Index)
	router.POST("/admin/categories/", Index)
	router.GET("/admin/categories/:id/", Index)
	router.PUT("/admin/categories/:id/", Index)
	router.DELETE("/admin/categories/:id/", Index)

	//admin > search
	router.GET("/admin/search/", Index)

	//account
	account := router.Group("/account")
	//account.Use(ensureAuthenticated)
	//account.Use(ensureAccount)
	{
		account.GET("/", AccountRender)

		//account > verification
		account.GET("/verification/", AccountVerification)
		account.POST("/verification/", Index)
		account.GET("/verification/:token/", Index)

		//account > settings
		account.GET("/settings/", AccountSettingsRender)
		account.PUT("/settings/", Index)
		account.PUT("/settings/identity/", Index)
		account.PUT("/settings/password/", Index)

		//account > settings > social
		account.GET("/settings/twitter/", Index)
		account.GET("/settings/twitter/callback/", Index)
		account.GET("/settings/twitter/disconnect/", Index)
		account.GET("/settings/github/", Index)
		account.GET("/settings/github/callback/", Index)
		account.GET("/settings/github/disconnect/", Index)
		account.GET("/settings/facebook/", Index)
		account.GET("/settings/facebook/callback/", Index)
		account.GET("/settings/facebook/disconnect/", Index)
		account.GET("/settings/google/", Index)
		account.GET("/settings/google/callback/", Index)
		account.GET("/settings/google/disconnect/", Index)
		account.GET("/settings/tumblr/", Index)
		account.GET("/settings/tumblr/callback/", Index)
		account.GET("/settings/tumblr/disconnect/", Index)
	}

	//route not found
	router.NoRoute(Status404Render)
}<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/gsdocker/gserrors"
	"github.com/gsdocker/gslogger"
	"github.com/gsdocker/gsmake"
	"github.com/gsdocker/gsos"
	"github.com/gsdocker/gsos/uuid"
)

var helpmsg = `
gsmake is a build automation software for golang and others
Usage:
    go [flags] task
Use "gsmake list" list all task
`

var verbflag = flag.Bool("v", false, "print more debug information")
var rootflag = flag.String("root", "", "the gsmake's root path")

func main() {

	log := gslogger.Get("gsmake")

	flag.Parse()

	if !*verbflag {
		gslogger.NewFlags(gslogger.ASSERT | gslogger.ERROR | gslogger.WARN | gslogger.INFO)
	}

	defer func() {
		if e := recover(); e != nil {
			log.E("recover :%s", e)
			gslogger.Join()
			os.Exit(1)
		} else {
			gslogger.Join()
		}
	}()

	homepath := os.Getenv(gsmake.EnvHome)

	if homepath == "" {
		homepath = *rootflag
	}

	if homepath == "" {
		gserrors.Panicf(nil, "expect -root flag or set %s env variable", gsmake.EnvHome)
	}

	var packagedir string

	if gsos.IsExist(".gsmake.json") {
		fullpath, err := filepath.Abs("./")

		if err != nil {
			log.E("get package full path error\n%s", err)
			gserrors.Panicf(err, "get package full path error")
		}

		packagedir = fullpath
	} else {
		dir := uuid.NewV1().String()

		packagedir = filepath.Join(os.TempDir(), dir)

		if err := os.MkdirAll(packagedir, 0755); err != nil {
			gserrors.Panicf(err, "create %s error", packagedir)
		}

		pkg := &gsmake.Package{
			Name: "github.com/gsdocker/gsmake.tmp",
			Import: []gsmake.Import{
				{Name: "github.com/gsdocker/gsmake"},
			},
		}

		content, err := json.Marshal(pkg)

		if err != nil {
			gserrors.Panicf(err, "create .gsmake.json error")
		}

		jsonfile := filepath.Join(packagedir, ".gsmake.json")

		err = ioutil.WriteFile(jsonfile, content, 0644)

		if err != nil {
			gserrors.Panicf(err, "create %s error", jsonfile)
		}
	}

	log.D("package path :%s", packagedir)
	log.D("gsmake root path :%s", homepath)

	compiler, err := gsmake.Compile(homepath, packagedir)

	if err != nil {
		panic(err)
	}

	if *verbflag {

		log.I("verb .... ")

		args := append([]string{"-v"}, flag.Args()...)
		compiler.Run(args...)
	} else {
		compiler.Run(flag.Args()...)
	}

	log.D("exist gsmake")
}
<commit_msg>update<commit_after>package main

import (
	"encoding/json"
	"flag"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/gsdocker/gserrors"
	"github.com/gsdocker/gslogger"
	"github.com/gsdocker/gsmake"
	"github.com/gsdocker/gsos"
	"github.com/gsdocker/gsos/uuid"
)

var helpmsg = `
gsmake is a build automation software for golang and others
Usage:
    go [flags] task
Use "gsmake list" list all task
`

var verbflag = flag.Bool("v", false, "print more debug information")
var rootflag = flag.String("root", "", "the gsmake's root path")

func main() {

	log := gslogger.Get("gsmake")

	flag.Parse()

	if !*verbflag {
		gslogger.NewFlags(gslogger.ASSERT | gslogger.ERROR | gslogger.WARN | gslogger.INFO)
	}

	defer func() {
		if e := recover(); e != nil {
			log.E("recover :%s", e)
			gslogger.Join()
			os.Exit(1)
		} else {
			gslogger.Join()
		}
	}()

	homepath := os.Getenv(gsmake.EnvHome)

	if homepath == "" {
		homepath = *rootflag
	}

	if homepath == "" {
		gserrors.Panicf(nil, "expect -root flag or set %s env variable", gsmake.EnvHome)
	}

	var packagedir string

	if gsos.IsExist(".gsmake.json") {
		fullpath, err := filepath.Abs("./")

		if err != nil {
			log.E("get package full path error\n%s", err)
			gserrors.Panicf(err, "get package full path error")
		}

		packagedir = fullpath
	} else {
		dir := uuid.NewV1().String()

		packagedir = filepath.Join(os.TempDir(), dir)

		if err := os.MkdirAll(packagedir, 0755); err != nil {
			gserrors.Panicf(err, "create %s error", packagedir)
		}

		pkg := &gsmake.Package{
			Name: "github.com/gsdocker/gsmake.tmp",
			Import: []gsmake.Import{
				{Name: "github.com/gsdocker/gsmake"},
			},
		}

		content, err := json.Marshal(pkg)

		if err != nil {
			gserrors.Panicf(err, "create .gsmake.json error")
		}

		jsonfile := filepath.Join(packagedir, ".gsmake.json")

		err = ioutil.WriteFile(jsonfile, content, 0644)

		if err != nil {
			gserrors.Panicf(err, "create %s error", jsonfile)
		}
	}

	log.D("package path :%s", packagedir)
	log.D("gsmake root path :%s", homepath)

	compiler, err := gsmake.Compile(homepath, packagedir)

	if err != nil {
		panic(err)
	}

	if *verbflag {
		args := append([]string{"-v"}, flag.Args()...)
		compiler.Run(args...)
	} else {
		compiler.Run(flag.Args()...)
	}

	log.D("exist gsmake")
}
<|endoftext|>


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

// hoverfly is an HTTP/s proxy configurable via flags/environment variables/admin HTTP API
//
// this proxy can be dynamically configured through HTTP calls when it's running, to change modes,
// export and import requests.

package main

import (
	log "github.com/Sirupsen/logrus"
	hv "github.com/SpectoLabs/hoverfly"
	"github.com/SpectoLabs/hoverfly/authentication/backends"
	"github.com/SpectoLabs/hoverfly/backends/boltdb"

	"flag"
	"fmt"
	"os"
	"strings"
)

type arrayFlags []string

func (i *arrayFlags) String() string {
	return "my string representation"
}

func (i *arrayFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

var importFlags arrayFlags
var destinationFlags arrayFlags

func main() {
	log.SetFormatter(&log.JSONFormatter{})

	// getting proxy configuration
	verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
	// modes
	capture := flag.Bool("capture", false, "start Hoverfly in capture mode - transparently intercepts and saves requests/response")
	synthesize := flag.Bool("synthesize", false, "start Hoverfly in synthesize mode (middleware is required)")
	modify := flag.Bool("modify", false, "start Hoverfly in modify mode - applies middleware (required) to both outgoing and incomming HTTP traffic")

	middleware := flag.String("middleware", "", "should proxy use middleware")

	// proxy port
	proxyPort := flag.String("pp", "", "proxy port - run proxy on another port (i.e. '-pp 9999' to run proxy on port 9999)")
	// admin port
	adminPort := flag.String("ap", "", "admin port - run admin interface on another port (i.e. '-ap 1234' to run admin UI on port 1234)")

	// database location
	database := flag.String("db", "", "database location - supply it if you want to provide specific to database (will be created there if it doesn't exist)")

	// delete current database on startup
	wipeDb := flag.Bool("wipedb", false, "supply -wipedb flag to delete all records from given database on startup")

	// metrics
	metrics := flag.Bool("metrics", false, "supply -metrics flag to enable metrics logging to stdout")

	// development
	dev := flag.Bool("dev", false, "supply -dev flag to serve directly from ./static/dist instead from statik binary")

	// import flag
	flag.Var(&importFlags, "import", "import from file or from URL (i.e. '-import my_service.json' or '-import http://mypage.com/service_x.json'")

	// destination configuration
	destination := flag.String("destination", ".", "destination URI to catch")
	flag.Var(&destinationFlags, "dest", "specify which hosts to process (i.e. '-dest fooservice.org -dest barservice.org -dest catservice.org') - other hosts will be ignored will passthrough'")

	// adding new user
	addNew := flag.Bool("add", false, "add new user '-add -username hfadmin -password hfpass'")
	addUser := flag.String("username", "", "username for new user")
	addPassword := flag.String("password", "", "password for new user")
	isAdmin := flag.Bool("admin", true, "supply '-admin false' to make this non admin user (defaults to 'true') ")

	// TODO: this should be enabled by default when UI and documentation is ready
	authEnabled := flag.Bool("auth", false, "enable authentication, currently it is disabled by default")

	flag.Parse()

	// getting settings
	cfg := hv.InitSettings()

	if *verbose {
		// Only log the warning severity or above.
		log.SetLevel(log.DebugLevel)
	}
	cfg.Verbose = *verbose

	if *dev {
		// making text pretty
		log.SetFormatter(&log.TextFormatter{})
	}

	// overriding environment variables (proxy and admin ports)
	if *proxyPort != "" {
		cfg.ProxyPort = *proxyPort
	}
	if *adminPort != "" {
		cfg.AdminPort = *adminPort
	}

	// development settings
	cfg.Development = *dev

	// overriding database location
	if *database != "" {
		cfg.DatabaseName = *database
	}

	if *wipeDb {
		os.Remove(cfg.DatabaseName)
	}

	// overriding default middleware setting
	cfg.Middleware = *middleware

	// setting default mode
	mode := hv.VirtualizeMode

	if *capture {
		mode = hv.CaptureMode
		// checking whether user supplied other modes
		if *synthesize == true || *modify == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	} else if *synthesize {
		mode = hv.SynthesizeMode

		if cfg.Middleware == "" {
			log.Fatal("Synthesize mode chosen although middleware not supplied")
		}

		if *capture == true || *modify == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	} else if *modify {
		mode = hv.ModifyMode

		if cfg.Middleware == "" {
			log.Fatal("Modify mode chosen although middleware not supplied")
		}

		if *capture == true || *synthesize == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	}

	// setting mode
	cfg.SetMode(mode)

	// enabling authentication if flag or env variable is set to 'true'
	if cfg.AuthEnabled || *authEnabled {
		cfg.AuthEnabled = true
	}

	if len(destinationFlags) > 0 {
		cfg.Destination = strings.Join(destinationFlags[:], "|")

	} else {
		//  setting destination regexp
		cfg.Destination = *destination
	}

	// getting boltDB
	db := boltdb.GetDB(cfg.DatabaseName)

	cache := boltdb.NewBoltDBCache(db, []byte(boltdb.RequestsBucketName))
	defer cache.CloseDB()

	dbClient := hv.GetNewHoverfly(cfg, cache)

	ab := backends.NewBoltDBAuthBackend(db, []byte(backends.TokenBucketName), []byte(backends.UserBucketName))

	// assigning auth backend
	dbClient.AB = ab

	// metadata backend
	md := hv.NewBoltDBMetadata(db, []byte(hv.MetadataBucketName))

	dbClient.MD = md

	// if add new user supplied - adding it to database
	if *addNew {
		err := ab.AddUser([]byte(*addUser), []byte(*addPassword), *isAdmin)
		if err != nil {
			log.WithFields(log.Fields{
				"error":    err.Error(),
				"username": *addUser,
			}).Fatal("failed to add new user")
		} else {
			log.WithFields(log.Fields{
				"username": *addUser,
			}).Info("user added successfuly")
		}
		return
	}

	// importing stuff
	if len(importFlags) > 0 {
		for i, v := range importFlags {
			if v != "" {
				log.WithFields(log.Fields{
					"import": v,
				}).Debug("Importing given resource")
				err := dbClient.Import(v)
				if err != nil {
					log.WithFields(log.Fields{
						"error":  err.Error(),
						"import": v,
					}).Fatal("Failed to import given resource")
				} else {
					err = dbClient.MD.Set(fmt.Sprintf("import_%d", i+1), v)
				}

			}
		}
	}

	// start metrics registry flush
	if *metrics {
		dbClient.Counter.Init()
	}

	err := dbClient.StartProxy()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Fatal("failed to start proxy...")
	}

	// starting admin interface, this is blocking
	dbClient.StartAdminInterface()
}
<commit_msg>providing cache interface to metadata<commit_after>// Copyright 2015 SpectoLabs. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// hoverfly is an HTTP/s proxy configurable via flags/environment variables/admin HTTP API
//
// this proxy can be dynamically configured through HTTP calls when it's running, to change modes,
// export and import requests.

package main

import (
	log "github.com/Sirupsen/logrus"
	hv "github.com/SpectoLabs/hoverfly"
	"github.com/SpectoLabs/hoverfly/authentication/backends"
	"github.com/SpectoLabs/hoverfly/backends/boltdb"

	"flag"
	"fmt"
	"os"
	"strings"
)

type arrayFlags []string

func (i *arrayFlags) String() string {
	return "my string representation"
}

func (i *arrayFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

var importFlags arrayFlags
var destinationFlags arrayFlags

func main() {
	log.SetFormatter(&log.JSONFormatter{})

	// getting proxy configuration
	verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
	// modes
	capture := flag.Bool("capture", false, "start Hoverfly in capture mode - transparently intercepts and saves requests/response")
	synthesize := flag.Bool("synthesize", false, "start Hoverfly in synthesize mode (middleware is required)")
	modify := flag.Bool("modify", false, "start Hoverfly in modify mode - applies middleware (required) to both outgoing and incomming HTTP traffic")

	middleware := flag.String("middleware", "", "should proxy use middleware")

	// proxy port
	proxyPort := flag.String("pp", "", "proxy port - run proxy on another port (i.e. '-pp 9999' to run proxy on port 9999)")
	// admin port
	adminPort := flag.String("ap", "", "admin port - run admin interface on another port (i.e. '-ap 1234' to run admin UI on port 1234)")

	// database location
	database := flag.String("db", "", "database location - supply it if you want to provide specific to database (will be created there if it doesn't exist)")

	// delete current database on startup
	wipeDb := flag.Bool("wipedb", false, "supply -wipedb flag to delete all records from given database on startup")

	// metrics
	metrics := flag.Bool("metrics", false, "supply -metrics flag to enable metrics logging to stdout")

	// development
	dev := flag.Bool("dev", false, "supply -dev flag to serve directly from ./static/dist instead from statik binary")

	// import flag
	flag.Var(&importFlags, "import", "import from file or from URL (i.e. '-import my_service.json' or '-import http://mypage.com/service_x.json'")

	// destination configuration
	destination := flag.String("destination", ".", "destination URI to catch")
	flag.Var(&destinationFlags, "dest", "specify which hosts to process (i.e. '-dest fooservice.org -dest barservice.org -dest catservice.org') - other hosts will be ignored will passthrough'")

	// adding new user
	addNew := flag.Bool("add", false, "add new user '-add -username hfadmin -password hfpass'")
	addUser := flag.String("username", "", "username for new user")
	addPassword := flag.String("password", "", "password for new user")
	isAdmin := flag.Bool("admin", true, "supply '-admin false' to make this non admin user (defaults to 'true') ")

	// TODO: this should be enabled by default when UI and documentation is ready
	authEnabled := flag.Bool("auth", false, "enable authentication, currently it is disabled by default")

	flag.Parse()

	// getting settings
	cfg := hv.InitSettings()

	if *verbose {
		// Only log the warning severity or above.
		log.SetLevel(log.DebugLevel)
	}
	cfg.Verbose = *verbose

	if *dev {
		// making text pretty
		log.SetFormatter(&log.TextFormatter{})
	}

	// overriding environment variables (proxy and admin ports)
	if *proxyPort != "" {
		cfg.ProxyPort = *proxyPort
	}
	if *adminPort != "" {
		cfg.AdminPort = *adminPort
	}

	// development settings
	cfg.Development = *dev

	// overriding database location
	if *database != "" {
		cfg.DatabaseName = *database
	}

	if *wipeDb {
		os.Remove(cfg.DatabaseName)
	}

	// overriding default middleware setting
	cfg.Middleware = *middleware

	// setting default mode
	mode := hv.VirtualizeMode

	if *capture {
		mode = hv.CaptureMode
		// checking whether user supplied other modes
		if *synthesize == true || *modify == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	} else if *synthesize {
		mode = hv.SynthesizeMode

		if cfg.Middleware == "" {
			log.Fatal("Synthesize mode chosen although middleware not supplied")
		}

		if *capture == true || *modify == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	} else if *modify {
		mode = hv.ModifyMode

		if cfg.Middleware == "" {
			log.Fatal("Modify mode chosen although middleware not supplied")
		}

		if *capture == true || *synthesize == true {
			log.Fatal("Two or more modes supplied, check your flags")
		}
	}

	// setting mode
	cfg.SetMode(mode)

	// enabling authentication if flag or env variable is set to 'true'
	if cfg.AuthEnabled || *authEnabled {
		cfg.AuthEnabled = true
	}

	if len(destinationFlags) > 0 {
		cfg.Destination = strings.Join(destinationFlags[:], "|")

	} else {
		//  setting destination regexp
		cfg.Destination = *destination
	}

	// getting boltDB
	db := boltdb.GetDB(cfg.DatabaseName)
	defer db.Close()

	cache := boltdb.NewBoltDBCache(db, []byte("requestsBucket"))

	dbClient := hv.GetNewHoverfly(cfg, cache)

	ab := backends.NewBoltDBAuthBackend(db, []byte(backends.TokenBucketName), []byte(backends.UserBucketName))

	// assigning auth backend
	dbClient.AB = ab

	// metadata backend
	metaCache := boltdb.NewBoltDBCache(db, []byte("metadataBucket"))
	md := hv.NewBoltDBMetadata(metaCache)

	dbClient.MD = md

	// if add new user supplied - adding it to database
	if *addNew {
		err := ab.AddUser([]byte(*addUser), []byte(*addPassword), *isAdmin)
		if err != nil {
			log.WithFields(log.Fields{
				"error":    err.Error(),
				"username": *addUser,
			}).Fatal("failed to add new user")
		} else {
			log.WithFields(log.Fields{
				"username": *addUser,
			}).Info("user added successfuly")
		}
		return
	}

	// importing stuff
	if len(importFlags) > 0 {
		for i, v := range importFlags {
			if v != "" {
				log.WithFields(log.Fields{
					"import": v,
				}).Debug("Importing given resource")
				err := dbClient.Import(v)
				if err != nil {
					log.WithFields(log.Fields{
						"error":  err.Error(),
						"import": v,
					}).Fatal("Failed to import given resource")
				} else {
					err = dbClient.MD.Set(fmt.Sprintf("import_%d", i+1), v)
				}

			}
		}
	}

	// start metrics registry flush
	if *metrics {
		dbClient.Counter.Init()
	}

	err := dbClient.StartProxy()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Fatal("failed to start proxy...")
	}

	// starting admin interface, this is blocking
	dbClient.StartAdminInterface()
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"net"
)

func setupHttpsListener(listenAddr string, certFile, keyFile string) (net.Listener, error) {
	listener, err := net.Listen("tcp", listenAddr)
	if err != nil {
		return nil, err
	}

	config := &tls.Config{
		NextProtos:   []string{"http/1.1"},
		Certificates: make([]tls.Certificate, 1),
	}
	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return nil, err
	}

	tlsListener := tls.NewListener(listener, config)
	return tlsListener, nil
}
<commit_msg>a small refactor<commit_after>package main

import (
	"crypto/tls"
	"net"
)

func setupHttpsListener(listenAddr string, certFile, keyFile string) (net.Listener, error) {
	listener, err := net.Listen("tcp", listenAddr)
	if err != nil {
		return nil, err
	}

	cer, err := tls.LoadX509KeyPair("server.pem", "server.key")
	if err != nil {
		return nil, err
	}

	config := &tls.Config{
		NextProtos:   []string{"http/1.1"},
		Certificates: []tls.Certificate{cer},
	}

	tlsListener := tls.NewListener(listener, config)
	return tlsListener, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

func pr(f string, v ...interface{}) {
	fmt.Printf(f+"\n", v...)
}

func exists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

// createdir is used when the existence of a directory is absolutely required.
func createdir(dir string) string {
	if !exists(dir) {
		err := os.MkdirAll(dir, 0700)
		if err != nil {
			pr("Fatal: Couldn't create directory %s", dir)
			os.Exit(2)
		}
	}
	return dir
}
<commit_msg>Add prn() for no-newline printouts.<commit_after>package main

import (
	"fmt"
	"os"
)

func pr(f string, v ...interface{}) {
	fmt.Printf(f+"\n", v...)
}

func prn(f string, v ...interface{}) {
	fmt.Printf(f, v...)
}

func exists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

// createdir is used when the existence of a directory is absolutely required.
func createdir(dir string) string {
	if !exists(dir) {
		err := os.MkdirAll(dir, 0700)
		if err != nil {
			pr("Fatal: Couldn't create directory %s", dir)
			os.Exit(2)
		}
	}
	return dir
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"net/http"

	"time"

	"github.com/jhernandezb/go-multasgt/entities/emetra"
)

func main() {
	client := &http.Client{
		Timeout: time.Duration(15 * time.Second),
	}
	var pType = flag.String("type", "P", "Plate Type")
	var pNumber = flag.String("number", "123ABC", "Plate Number")
	flag.Parse()
	plates, _ := emetra.Check(*pType, *pNumber, client)
	fmt.Printf("%+v", plates)
	// ts, _ := multasgt.GetAllTickets(*pType, *pNumber, client)
	// for _, t := range ts {
	// 	fmt.Printf("%#v \n", t)
	// }

}
<commit_msg>update main<commit_after>package main

import (
	"flag"
	"fmt"

	"net/http"

	"time"

	"github.com/jhernandezb/go-multasgt"
)

func main() {
	client := &http.Client{
		Timeout: time.Duration(15 * time.Second),
	}
	var pType = flag.String("type", "P", "Plate Type")
	var pNumber = flag.String("number", "123ABC", "Plate Number")
	flag.Parse()
	ts, _ := multasgt.GetAllTickets(*pType, *pNumber, client)
	for _, t := range ts {
		fmt.Printf("%#v \n", t)
	}
}
<|endoftext|>


<commit_before>package replay

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/danielfireman/esperf/esmetrics"
	"github.com/danielfireman/esperf/loadspec"
	"github.com/danielfireman/esperf/metrics"
	"github.com/danielfireman/esperf/reporter"
	"github.com/spf13/cobra"
)

var (
	host        string
	resultsPath string
	expID       string
	cint        time.Duration
	timeout     time.Duration
	debug       bool
	numClients  int
	isPaused    int32
)

func init() {
	RootCmd.Flags().StringVar(&host, "mon_host", "", "")
	RootCmd.Flags().DurationVar(&cint, "mon_interval", 5*time.Second, "Interval between metrics collection.")
	RootCmd.Flags().StringVar(&resultsPath, "results_path", "", "")
	RootCmd.Flags().StringVar(&expID, "exp_id", "1", "")
	RootCmd.Flags().DurationVar(&timeout, "timeout", 30*time.Second, "Timeout to be used in connections to ES.")
	RootCmd.Flags().BoolVar(&debug, "debug", false, "Dump requests and responses.")
	RootCmd.Flags().IntVarP(&numClients, "num_clients", "c", 10, "Number of active clients making requests.")
}

var (
	// DefaultLocalAddr is the default local IP address an Attacker uses.
	defaultLocalAddr = net.IPAddr{IP: net.IPv4zero}
	// DefaultConnections is the default amount of max open idle connections per
	// target host.
	defaultConnections = 10000
	r                  runner
)

var RootCmd = &cobra.Command{
	Use:   "replay",
	Short: "Runs a performance testing and collects metrics.",
	Long:  "Multiplatform command line tool to load test and collect metrics from your ElasticSearch deployment.",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if numClients < 1 {
			return fmt.Errorf("number of clients must be positive.")
		}

		var err error
		r = runner{}
		if resultsPath == "" {
			return fmt.Errorf("results path can not be empty. Please set --results_path flag.")
		}

		r.requestsSent = metrics.NewCounter()
		r.errors = metrics.NewCounter()
		r.responseTimes = metrics.NewHistogram()
		r.pauseTimes = metrics.NewHistogram()
		r.clients = make(chan *http.Client, numClients)
		for i := 0; i < numClients; i++ {
			r.clients <- &http.Client{
				Transport: &http.Transport{
					Dial: (&net.Dialer{
						LocalAddr: &net.TCPAddr{IP: defaultLocalAddr.IP, Zone: defaultLocalAddr.Zone},
						KeepAlive: 3 * timeout,
						Timeout:   timeout,
					}).Dial,
					ResponseHeaderTimeout: timeout,
					MaxIdleConnsPerHost:   defaultConnections,
				},
			}
		}

		// TODO(danielfireman): Review metrics collection design.
		collector, err := esmetrics.NewCollector(host, timeout, debug)
		if err != nil {
			return err
		}
		r.report, err = reporter.New(
			cint,
			timeout,
			reporter.MetricToCSV(r.responseTimes, csvFilePath("response.time", expID, resultsPath)),
			reporter.MetricToCSV(r.pauseTimes, csvFilePath("pause.time", expID, resultsPath)),
			reporter.MetricToCSV(r.requestsSent, csvFilePath("requests.sent", expID, resultsPath)),
			reporter.MetricToCSV(r.errors, csvFilePath("errors", expID, resultsPath)),
			reporter.AddCollector(collector),
			reporter.MetricToCSV(collector.Mem.YoungPoolUsedBytes, csvFilePath("young.pool.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.YoungPoolMaxBytes, csvFilePath("young.pool.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.TenuredPoolUsedBytes, csvFilePath("tenured.pool.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.TenuredPoolMaxBytes, csvFilePath("tenured.pool.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.SurvivorPoolUsedBytes, csvFilePath("survivor.pool.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.SurvivorPoolMaxBytes, csvFilePath("survivor.pool.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.CPU.Percent, csvFilePath("cpu.percent", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.YoungCount, csvFilePath("gc.young.count", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.YoungTimeMillis, csvFilePath("gc.young.time.ms", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.FullCount, csvFilePath("gc.full.count", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.FullTimeMillis, csvFilePath("gc.full.time.ms", expID, resultsPath)),
		)
		if err != nil {
			return err
		}
		return nil
	},
	RunE: func(cmd *cobra.Command, args []string) error {
		if err := r.Run(); err != nil {
			return err
		}
		return nil
	},
}

type runner struct {
	clients chan *http.Client
	report  *reporter.Reporter

	requestsSent  *metrics.Counter
	responseTimes *metrics.Histogram
	errors        *metrics.Counter
	pauseTimes    *metrics.Histogram
}

func csvFilePath(name, expID, resultsPath string) string {
	return filepath.Join(resultsPath, name+"_"+expID+".csv")
}

func (r *runner) Run() error {
	r.report.Start()
	defer r.report.Finish()

	var wg sync.WaitGroup
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)

	pauseTime := int64(0)
	pauseChan := make(chan time.Duration)
	scanner := bufio.NewScanner(os.Stdin)
	for count := 0; scanner.Scan(); count++ {
		// Note: Having a single worker or a single load generator is a way to guarantee the load will obey to a
		// certain  distribution. For instance, 10 workers generating load following a Poisson distribution is
		// different  from having Poisson ruling the overall load impressed on the service.
		entry := loadspec.Entry{}
		if err := json.NewDecoder(strings.NewReader(scanner.Text())).Decode(&entry); err != nil {
			return err
		}
		// Dropping requests made during pauses.
		if pauseTime > 0 {
			pauseTime -= entry.DelaySinceLastNanos
			continue
		} else {
			pauseTime = 0
		}
		time.Sleep(time.Duration(entry.DelaySinceLastNanos))

		req, err := http.NewRequest("GET", entry.URL, strings.NewReader(entry.Source))
		if err != nil {
			return err
		}

		wg.Add(1)
		go func() {
			defer wg.Done()

			// Pretty simple thread-safe pool implementation.
			client := <-r.clients
			defer func() {
				r.clients <- client
			}()

			dReq, _ := httputil.DumpRequest(req, true)
			if debug {
				fmt.Println(string(dReq))
			}

			r.requestsSent.Inc()
			ctx, cancel := context.WithTimeout(context.Background(), timeout)
			defer cancel()
			req.WithContext(ctx)

			resp, err := client.Do(req)
			if err != nil {
				r.errors.Inc()
				fmt.Printf("Error sending request: %q\n", err)
				return
			}

			dResp, _ := httputil.DumpResponse(resp, true)
			if debug {
				fmt.Println(string(dResp))
			}

			defer resp.Body.Close()
			code := resp.StatusCode
			switch {
			default:
				r.errors.Inc()
			case code == http.StatusOK:
				searchResp := struct {
					TookInMillis int64 `json:"took"`
				}{}
				if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
					fmt.Printf("error parsing response: %q\n", err)
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					os.Exit(-1)
					return
				}
				r.responseTimes.Record(searchResp.TookInMillis)
			case code == http.StatusBadRequest:
				searchResp := struct {
					Error struct {
						Type   string `json:"type"`
						Reason string `json:"reason"`
					} `json:"error"`
				}{}
				if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
					fmt.Printf("error parsing bad request response: %q\n", err)
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					os.Exit(-1)
					return
				}
				fmt.Printf("error querying server: %+v\n", searchResp.Error)
				// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
				os.Exit(-1)
				return
			case code == http.StatusServiceUnavailable || code == http.StatusTooManyRequests:
				if atomic.LoadInt32(&isPaused) == 1 {
					return
				}
				ra := resp.Header.Get("Retry-After")
				if ra == "" {
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					fmt.Println("Could not extract retry-after information")
					os.Exit(-1)
				}
				pt, err := strconv.ParseFloat(ra, 64)
				if err != nil {
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					fmt.Println("Could not extract retry-after information")
					os.Exit(-1)
				}
				pauseMillis := int64(pt * 1e3)
				r.pauseTimes.Record(pauseMillis)
				// If the loadtest is paused, ignore this signal.
				if atomic.LoadInt32(&isPaused) == 1 {
					return
				}
				// Only enqueue if the pause queue is empty.
				if len(pauseChan) == 0 {
					atomic.StoreInt32(&isPaused, 1)
					pauseChan <- time.Duration(pauseMillis) * time.Millisecond
				}
			}
		}()
		// Non-blocking check of pauses.
		select {
		case pt := <-pauseChan:
			pauseTime = pt.Nanoseconds()
			time.Sleep(pt)
			atomic.StoreInt32(&isPaused, 0)
		case <-sig:
			fmt.Println("Interrupting load test.")
			return nil
		default:
		}
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	go func() {
		wg.Wait()
		close(pauseChan)
	}()
	// Avoiding any goroutine to be blocked on adding to the pause channel
	for range pauseChan {
	}
	return nil
}
<commit_msg>Renaming memory pool file names to be more consistent<commit_after>package replay

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/danielfireman/esperf/esmetrics"
	"github.com/danielfireman/esperf/loadspec"
	"github.com/danielfireman/esperf/metrics"
	"github.com/danielfireman/esperf/reporter"
	"github.com/spf13/cobra"
)

var (
	host        string
	resultsPath string
	expID       string
	cint        time.Duration
	timeout     time.Duration
	debug       bool
	numClients  int
	isPaused    int32
)

func init() {
	RootCmd.Flags().StringVar(&host, "mon_host", "", "")
	RootCmd.Flags().DurationVar(&cint, "mon_interval", 5*time.Second, "Interval between metrics collection.")
	RootCmd.Flags().StringVar(&resultsPath, "results_path", "", "")
	RootCmd.Flags().StringVar(&expID, "exp_id", "1", "")
	RootCmd.Flags().DurationVar(&timeout, "timeout", 30*time.Second, "Timeout to be used in connections to ES.")
	RootCmd.Flags().BoolVar(&debug, "debug", false, "Dump requests and responses.")
	RootCmd.Flags().IntVarP(&numClients, "num_clients", "c", 10, "Number of active clients making requests.")
}

var (
	// DefaultLocalAddr is the default local IP address an Attacker uses.
	defaultLocalAddr = net.IPAddr{IP: net.IPv4zero}
	// DefaultConnections is the default amount of max open idle connections per
	// target host.
	defaultConnections = 10000
	r                  runner
)

var RootCmd = &cobra.Command{
	Use:   "replay",
	Short: "Runs a performance testing and collects metrics.",
	Long:  "Multiplatform command line tool to load test and collect metrics from your ElasticSearch deployment.",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if numClients < 1 {
			return fmt.Errorf("number of clients must be positive.")
		}

		var err error
		r = runner{}
		if resultsPath == "" {
			return fmt.Errorf("results path can not be empty. Please set --results_path flag.")
		}

		r.requestsSent = metrics.NewCounter()
		r.errors = metrics.NewCounter()
		r.responseTimes = metrics.NewHistogram()
		r.pauseTimes = metrics.NewHistogram()
		r.clients = make(chan *http.Client, numClients)
		for i := 0; i < numClients; i++ {
			r.clients <- &http.Client{
				Transport: &http.Transport{
					Dial: (&net.Dialer{
						LocalAddr: &net.TCPAddr{IP: defaultLocalAddr.IP, Zone: defaultLocalAddr.Zone},
						KeepAlive: 3 * timeout,
						Timeout:   timeout,
					}).Dial,
					ResponseHeaderTimeout: timeout,
					MaxIdleConnsPerHost:   defaultConnections,
				},
			}
		}

		// TODO(danielfireman): Review metrics collection design.
		collector, err := esmetrics.NewCollector(host, timeout, debug)
		if err != nil {
			return err
		}
		r.report, err = reporter.New(
			cint,
			timeout,
			reporter.MetricToCSV(r.responseTimes, csvFilePath("response.time", expID, resultsPath)),
			reporter.MetricToCSV(r.pauseTimes, csvFilePath("pause.time", expID, resultsPath)),
			reporter.MetricToCSV(r.requestsSent, csvFilePath("requests.sent", expID, resultsPath)),
			reporter.MetricToCSV(r.errors, csvFilePath("errors", expID, resultsPath)),
			reporter.AddCollector(collector),
			reporter.MetricToCSV(collector.Mem.YoungPoolUsedBytes, csvFilePath("mem.young.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.YoungPoolMaxBytes, csvFilePath("mem.young.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.TenuredPoolUsedBytes, csvFilePath("mem.tenured.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.TenuredPoolMaxBytes, csvFilePath("mem.tenured.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.SurvivorPoolUsedBytes, csvFilePath("mem.survivor.used.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.Mem.SurvivorPoolMaxBytes, csvFilePath("mem.survivor.max.bytes", expID, resultsPath)),
			reporter.MetricToCSV(collector.CPU.Percent, csvFilePath("cpu.percent", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.YoungCount, csvFilePath("gc.young.count", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.YoungTimeMillis, csvFilePath("gc.young.time.ms", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.FullCount, csvFilePath("gc.full.count", expID, resultsPath)),
			reporter.MetricToCSV(collector.GC.FullTimeMillis, csvFilePath("gc.full.time.ms", expID, resultsPath)),
		)
		if err != nil {
			return err
		}
		return nil
	},
	RunE: func(cmd *cobra.Command, args []string) error {
		if err := r.Run(); err != nil {
			return err
		}
		return nil
	},
}

type runner struct {
	clients chan *http.Client
	report  *reporter.Reporter

	requestsSent  *metrics.Counter
	responseTimes *metrics.Histogram
	errors        *metrics.Counter
	pauseTimes    *metrics.Histogram
}

func csvFilePath(name, expID, resultsPath string) string {
	return filepath.Join(resultsPath, name+"_"+expID+".csv")
}

func (r *runner) Run() error {
	r.report.Start()
	defer r.report.Finish()

	var wg sync.WaitGroup
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, os.Kill)

	pauseTime := int64(0)
	pauseChan := make(chan time.Duration)
	scanner := bufio.NewScanner(os.Stdin)
	for count := 0; scanner.Scan(); count++ {
		// Note: Having a single worker or a single load generator is a way to guarantee the load will obey to a
		// certain  distribution. For instance, 10 workers generating load following a Poisson distribution is
		// different  from having Poisson ruling the overall load impressed on the service.
		entry := loadspec.Entry{}
		if err := json.NewDecoder(strings.NewReader(scanner.Text())).Decode(&entry); err != nil {
			return err
		}
		// Dropping requests made during pauses.
		if pauseTime > 0 {
			pauseTime -= entry.DelaySinceLastNanos
			continue
		} else {
			pauseTime = 0
		}
		time.Sleep(time.Duration(entry.DelaySinceLastNanos))

		req, err := http.NewRequest("GET", entry.URL, strings.NewReader(entry.Source))
		if err != nil {
			return err
		}

		wg.Add(1)
		go func() {
			defer wg.Done()

			// Pretty simple thread-safe pool implementation.
			client := <-r.clients
			defer func() {
				r.clients <- client
			}()

			dReq, _ := httputil.DumpRequest(req, true)
			if debug {
				fmt.Println(string(dReq))
			}

			r.requestsSent.Inc()
			ctx, cancel := context.WithTimeout(context.Background(), timeout)
			defer cancel()
			req.WithContext(ctx)

			resp, err := client.Do(req)
			if err != nil {
				r.errors.Inc()
				fmt.Printf("Error sending request: %q\n", err)
				return
			}

			dResp, _ := httputil.DumpResponse(resp, true)
			if debug {
				fmt.Println(string(dResp))
			}

			defer resp.Body.Close()
			code := resp.StatusCode
			switch {
			default:
				r.errors.Inc()
			case code == http.StatusOK:
				searchResp := struct {
					TookInMillis int64 `json:"took"`
				}{}
				if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
					fmt.Printf("error parsing response: %q\n", err)
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					os.Exit(-1)
					return
				}
				r.responseTimes.Record(searchResp.TookInMillis)
			case code == http.StatusBadRequest:
				searchResp := struct {
					Error struct {
						Type   string `json:"type"`
						Reason string `json:"reason"`
					} `json:"error"`
				}{}
				if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
					fmt.Printf("error parsing bad request response: %q\n", err)
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					os.Exit(-1)
					return
				}
				fmt.Printf("error querying server: %+v\n", searchResp.Error)
				// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
				os.Exit(-1)
				return
			case code == http.StatusServiceUnavailable || code == http.StatusTooManyRequests:
				if atomic.LoadInt32(&isPaused) == 1 {
					return
				}
				ra := resp.Header.Get("Retry-After")
				if ra == "" {
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					fmt.Println("Could not extract retry-after information")
					os.Exit(-1)
				}
				pt, err := strconv.ParseFloat(ra, 64)
				if err != nil {
					// TODO(danielfireman): Make this more elegant. Leveraging cobra error messages.
					fmt.Println("Could not extract retry-after information")
					os.Exit(-1)
				}
				pauseMillis := int64(pt * 1e3)
				r.pauseTimes.Record(pauseMillis)
				// If the loadtest is paused, ignore this signal.
				if atomic.LoadInt32(&isPaused) == 1 {
					return
				}
				// Only enqueue if the pause queue is empty.
				if len(pauseChan) == 0 {
					atomic.StoreInt32(&isPaused, 1)
					pauseChan <- time.Duration(pauseMillis) * time.Millisecond
				}
			}
		}()
		// Non-blocking check of pauses.
		select {
		case pt := <-pauseChan:
			pauseTime = pt.Nanoseconds()
			time.Sleep(pt)
			atomic.StoreInt32(&isPaused, 0)
		case <-sig:
			fmt.Println("Interrupting load test.")
			return nil
		default:
		}
	}
	if err := scanner.Err(); err != nil {
		return err
	}
	go func() {
		wg.Wait()
		close(pauseChan)
	}()
	// Avoiding any goroutine to be blocked on adding to the pause channel
	for range pauseChan {
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"math/rand"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/cenkalti/backoff"
	"github.com/go-kit/kit/metrics"
	"github.com/relab/raft"
	"github.com/relab/raft/commonpb"
	"github.com/relab/rkv/rkvpb"
	"google.golang.org/grpc"
)

type client struct {
	l             *uint64
	currentLeader uint64
	servers       []rkvpb.RKVClient

	inFlight int64

	id  uint64
	seq uint64

	zipf *z

	s *stats

	payload int
	lat     *raft.Latency

	ensure bool
}

// z wraps rand.Zipf with a mutex.
type z struct {
	sync.Mutex
	*rand.Zipf
}

func (zz *z) Uint64() uint64 {
	zz.Lock()
	i := zz.Zipf.Uint64()
	zz.Unlock()
	return i
}

func newClient(leader *uint64, servers []string, zipf *rand.Zipf, s *stats, payload int, lat *raft.Latency, ensure bool) (*client, error) {
	conns := make([]rkvpb.RKVClient, len(servers))

	for i, server := range servers {
		cc, err := grpc.Dial(server, grpc.WithBlock(), grpc.WithInsecure())

		if err != nil {
			return nil, err
		}

		conns[i] = rkvpb.NewRKVClient(cc)
	}

	c := &client{
		l:       leader,
		servers: conns,
		zipf:    &z{Zipf: zipf},
		s:       s,
		payload: payload,
		lat:     lat,
		ensure:  ensure,
	}

	res, err := c.register()

	if err != nil {
		return nil, err
	}

	c.id = res.ClientID
	c.seq = 1

	return c, nil
}

const (
	requestTimeout = 10 * time.Minute
	maxInFlight    = 50000
)

func newBackOff() *backoff.ExponentialBackOff {
	b := backoff.NewExponentialBackOff()
	b.InitialInterval = 1 * time.Millisecond
	b.RandomizationFactor = 0.5
	b.Multiplier = 1.5
	b.MaxInterval = 1 * time.Second
	b.MaxElapsedTime = 15 * time.Minute
	b.Reset()
	return b
}

func notify(err error, d time.Duration) {
	// TODO For debugging.
}

// ErrMaxInFlightReached indicates that there are too many messages in-flight.
var ErrMaxInFlightReached = errors.New("reached max in-flight")

func (c *client) addServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfAdd)
}

func (c *client) removeServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfRemove)
}

func (c *client) reconf(serverID uint64, reconfType commonpb.ReconfType) (*commonpb.ReconfResponse, error) {
	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *commonpb.ReconfResponse

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		if c.ensure {
			res, err = c.servers[prevLeader].ReconfOnBecome(ctx, &commonpb.ReconfRequest{
				ServerID:   serverID,
				ReconfType: reconfType,
			})
		} else {
			res, err = c.servers[prevLeader].Reconf(ctx, &commonpb.ReconfRequest{
				ServerID:   serverID,
				ReconfType: reconfType,
			})
		}

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(&backoff.ZeroBackOff{}, ctx), notify)

	return res, err
}

func (c *client) register() (*rkvpb.RegisterResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.RegisterResponse

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Register(ctx, &rkvpb.RegisterRequest{})

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		return nil

	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) lookup() (*rkvpb.LookupResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.readReqs.Add(1)
	timer := metrics.NewTimer(c.s.readLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.LookupResponse

	req := &rkvpb.LookupRequest{
		Key: c.randPayload(),
	}

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Lookup(ctx, req)

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.reads.Add(1)
		timer.ObserveDuration()
		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) insert() (*rkvpb.InsertResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)
	start := time.Now()

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.InsertResponse

	req := &rkvpb.InsertRequest{
		ClientID:  c.id,
		ClientSeq: atomic.AddUint64(&c.seq, 1),
		Key:       c.randPayload(),
		Value:     c.randPayload(),
	}

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Insert(ctx, req)

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		c.lat.Record(start)
		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) nextLeader(prevLeader uint64) {
	newLeader := (prevLeader + 1) % uint64(len(c.servers))
	atomic.CompareAndSwapUint64(c.l, prevLeader, newLeader)
}

func (c *client) getLeader() uint64 {
	c.currentLeader = atomic.LoadUint64(c.l)
	return c.currentLeader
}

func (c *client) randPayload() string {
	return strconv.FormatUint(c.zipf.Uint64(), 10) + strings.Repeat("X", c.payload)
}
<commit_msg>rkvctl/client.go: Don't register when ensure flag is set<commit_after>package main

import (
	"context"
	"errors"
	"math/rand"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"github.com/cenkalti/backoff"
	"github.com/go-kit/kit/metrics"
	"github.com/relab/raft"
	"github.com/relab/raft/commonpb"
	"github.com/relab/rkv/rkvpb"
	"google.golang.org/grpc"
)

type client struct {
	l             *uint64
	currentLeader uint64
	servers       []rkvpb.RKVClient

	inFlight int64

	id  uint64
	seq uint64

	zipf *z

	s *stats

	payload int
	lat     *raft.Latency

	ensure bool
}

// z wraps rand.Zipf with a mutex.
type z struct {
	sync.Mutex
	*rand.Zipf
}

func (zz *z) Uint64() uint64 {
	zz.Lock()
	i := zz.Zipf.Uint64()
	zz.Unlock()
	return i
}

func newClient(leader *uint64, servers []string, zipf *rand.Zipf, s *stats, payload int, lat *raft.Latency, ensure bool) (*client, error) {
	conns := make([]rkvpb.RKVClient, len(servers))

	for i, server := range servers {
		cc, err := grpc.Dial(server, grpc.WithBlock(), grpc.WithInsecure())

		if err != nil {
			return nil, err
		}

		conns[i] = rkvpb.NewRKVClient(cc)
	}

	c := &client{
		l:       leader,
		servers: conns,
		zipf:    &z{Zipf: zipf},
		s:       s,
		payload: payload,
		lat:     lat,
		ensure:  ensure,
	}

	if ensure {
		res, err := c.register()

		if err != nil {
			return nil, err
		}

		c.id = res.ClientID
		c.seq = 1
	}

	return c, nil
}

const (
	requestTimeout = 10 * time.Minute
	maxInFlight    = 50000
)

func newBackOff() *backoff.ExponentialBackOff {
	b := backoff.NewExponentialBackOff()
	b.InitialInterval = 1 * time.Millisecond
	b.RandomizationFactor = 0.5
	b.Multiplier = 1.5
	b.MaxInterval = 1 * time.Second
	b.MaxElapsedTime = 15 * time.Minute
	b.Reset()
	return b
}

func notify(err error, d time.Duration) {
	// TODO For debugging.
}

// ErrMaxInFlightReached indicates that there are too many messages in-flight.
var ErrMaxInFlightReached = errors.New("reached max in-flight")

func (c *client) addServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfAdd)
}

func (c *client) removeServer(serverID uint64) (*commonpb.ReconfResponse, error) {
	return c.reconf(serverID, commonpb.ReconfRemove)
}

func (c *client) reconf(serverID uint64, reconfType commonpb.ReconfType) (*commonpb.ReconfResponse, error) {
	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *commonpb.ReconfResponse

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		if c.ensure {
			res, err = c.servers[prevLeader].ReconfOnBecome(ctx, &commonpb.ReconfRequest{
				ServerID:   serverID,
				ReconfType: reconfType,
			})
		} else {
			res, err = c.servers[prevLeader].Reconf(ctx, &commonpb.ReconfRequest{
				ServerID:   serverID,
				ReconfType: reconfType,
			})
		}

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(&backoff.ZeroBackOff{}, ctx), notify)

	return res, err
}

func (c *client) register() (*rkvpb.RegisterResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.RegisterResponse

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Register(ctx, &rkvpb.RegisterRequest{})

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		return nil

	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) lookup() (*rkvpb.LookupResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.readReqs.Add(1)
	timer := metrics.NewTimer(c.s.readLatency)

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.LookupResponse

	req := &rkvpb.LookupRequest{
		Key: c.randPayload(),
	}

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Lookup(ctx, req)

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.reads.Add(1)
		timer.ObserveDuration()
		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) insert() (*rkvpb.InsertResponse, error) {
	if atomic.LoadInt64(&c.inFlight) > maxInFlight {
		return nil, ErrMaxInFlightReached
	}
	atomic.AddInt64(&c.inFlight, 1)
	defer func() {
		atomic.AddInt64(&c.inFlight, -1)
	}()

	c.s.writeReqs.Add(1)
	timer := metrics.NewTimer(c.s.writeLatency)
	start := time.Now()

	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
	defer cancel()

	var res *rkvpb.InsertResponse

	req := &rkvpb.InsertRequest{
		ClientID:  c.id,
		ClientSeq: atomic.AddUint64(&c.seq, 1),
		Key:       c.randPayload(),
		Value:     c.randPayload(),
	}

	op := func() error {
		var err error
		prevLeader := c.getLeader()
		res, err = c.servers[prevLeader].Insert(ctx, req)

		if err != nil {
			c.nextLeader(prevLeader)
			return err
		}

		c.s.writes.Add(1)
		timer.ObserveDuration()
		c.lat.Record(start)
		return nil
	}

	err := backoff.RetryNotify(op, backoff.WithContext(newBackOff(), ctx), notify)

	return res, err
}

func (c *client) nextLeader(prevLeader uint64) {
	newLeader := (prevLeader + 1) % uint64(len(c.servers))
	atomic.CompareAndSwapUint64(c.l, prevLeader, newLeader)
}

func (c *client) getLeader() uint64 {
	c.currentLeader = atomic.LoadUint64(c.l)
	return c.currentLeader
}

func (c *client) randPayload() string {
	return strconv.FormatUint(c.zipf.Uint64(), 10) + strings.Repeat("X", c.payload)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"

	"github.com/hackebrot/turtle"
	"github.com/spf13/cobra"
)

func newSearchCmd(w io.Writer) *cobra.Command {
	return &cobra.Command{
		Use:   "search",
		Short: "Print emojis with a name that contains the search string",
		Long:  "Print emojis with a name that contains the search string",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runSearch(w, args[0])
		},
		Args: func(cmd *cobra.Command, args []string) error {
			if len(args) != 1 {
				return fmt.Errorf("require one search string")
			}
			return nil
		},
	}
}

func runSearch(w io.Writer, s string) error {

	emojis := turtle.Search(s)

	if emojis == nil {
		return fmt.Errorf("cannot find emojis for search %q", s)
	}

	j, err := NewJSONWriter(w, WithIndent(prefix, indent))

	if err != nil {
		return fmt.Errorf("error creating JSONWriter: %v", err)
	}

	return j.WriteEmojis(emojis)
}
<commit_msg>Update Use and Args for search cmd<commit_after>package main

import (
	"fmt"
	"io"

	"github.com/hackebrot/turtle"
	"github.com/spf13/cobra"
)

func newSearchCmd(w io.Writer) *cobra.Command {
	return &cobra.Command{
		Use:   "search [STRING]",
		Short: "Print emojis with a name that contains the search string",
		Long:  "Print emojis with a name that contains the search string",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			return runSearch(w, args[0])
		},
	}
}

func runSearch(w io.Writer, s string) error {

	emojis := turtle.Search(s)

	if emojis == nil {
		return fmt.Errorf("cannot find emojis for search %q", s)
	}

	j, err := NewJSONWriter(w, WithIndent(prefix, indent))

	if err != nil {
		return fmt.Errorf("error creating JSONWriter: %v", err)
	}

	return j.WriteEmojis(emojis)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"syscall"

	"github.com/apex/log"
	"github.com/apex/log/handlers/cli"
	"github.com/apex/log/handlers/json"

	"github.com/alecthomas/kingpin"
	"github.com/versent/unicreds"
)

var (
	app     = kingpin.New("unicreds", "A credential/secret storage command line tool.")
	csv     = app.Flag("csv", "Enable csv output for table data.").Short('c').Bool()
	debug   = app.Flag("debug", "Enable debug mode.").Short('d').Bool()
	logJSON = app.Flag("json", "Output results in JSON").Short('j').Bool()

	region  = app.Flag("region", "Configure the AWS region").Short('r').String()
	profile = app.Flag("profile", "Configure the AWS profile").Short('p').String()
	role    = app.Flag("role", "Specify an AWS role ARN to assume").Short('R').String()

	dynamoTable = app.Flag("table", "DynamoDB table.").Default("credential-store").OverrideDefaultFromEnvar("UNICREDS_TABLE").Short('t').String()
	alias       = app.Flag("alias", "KMS key alias.").Default("alias/credstash").OverrideDefaultFromEnvar("UNICREDS_ALIAS").Short('k').String()
	encContext  = encryptionContext(app.Flag("enc-context", "Add a key value pair to the encryption context.").Short('E'))

	// commands
	cmdSetup      = app.Command("setup", "Setup the dynamodb table used to store credentials.")
	cmdSetupRead  = cmdSetup.Flag("read", "Dynamo read capacity.").Default("4").Int64()
	cmdSetupWrite = cmdSetup.Flag("write", "Dynamo write capacity.").Default("4").Int64()

	cmdGet        = app.Command("get", "Get a credential from the store.")
	cmdGetName    = cmdGet.Arg("credential", "The name of the credential to get.").Required().String()
	cmdGetNoLine  = cmdGet.Flag("noline", "Leave off the newline when emitting secret").Short('n').Bool()
	cmdGetVersion = cmdGet.Arg("version", "The version of the credential to get.").Int()

	cmdGetAll         = app.Command("getall", "Get latest credentials from the store.")
	cmdGetAllVersions = cmdGetAll.Flag("all", "List all versions").Bool()

	cmdList            = app.Command("list", "List latest credentials with names and version.")
	cmdListAllVersions = cmdList.Flag("all", "List all versions").Bool()

	cmdPut        = app.Command("put", "Put a credential into the store.")
	cmdPutName    = cmdPut.Arg("credential", "The name of the credential to store.").Required().String()
	cmdPutSecret  = cmdPut.Arg("value", "The value of the credential to store.").Required().String()
	cmdPutVersion = cmdPut.Arg("version", "Version to store with the credential.").Int()

	cmdPutFile           = app.Command("put-file", "Put a credential from a file into the store.")
	cmdPutFileName       = cmdPutFile.Arg("credential", "The name of the credential to store.").Required().String()
	cmdPutFileSecretPath = cmdPutFile.Arg("value", "Path to file containing the credential to store.").Required().String()
	cmdPutFileVersion    = cmdPutFile.Arg("version", "Version to store with the credential.").Int()

	cmdDelete     = app.Command("delete", "Delete a credential from the store.")
	cmdDeleteName = cmdDelete.Arg("credential", "The name of the credential to delete.").Required().String()

	cmdExecute        = app.Command("exec", "Execute a command with all secrets loaded as environment variables.")
	cmdExecuteCommand = cmdExecute.Arg("command", "The command to execute.").Required().Strings()

	// Version app version
	Version = "1.0.0"
)

func main() {
	app.Version(Version)

	command := kingpin.MustParse(app.Parse(os.Args[1:]))

	if *logJSON {
		log.SetHandler(json.New(os.Stderr))
	} else {
		log.SetHandler(cli.Default)
	}

	if *debug {
		log.SetLevel(log.DebugLevel)
	}

	unicreds.SetAwsConfig(region, profile, role)

	switch command {
	case cmdSetup.FullCommand():
		err := unicreds.Setup(dynamoTable, cmdSetupRead, cmdSetupWrite)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"status": "success"}).Info("Created table")
	case cmdGet.FullCommand():
		var cred *unicreds.DecryptedCredential
		var err error
		if *cmdGetVersion == 0 {
			cred, err = unicreds.GetHighestVersionSecret(dynamoTable, *cmdGetName, encContext)
		} else {
			cred, err = unicreds.GetSecret(dynamoTable, *cmdGetName, unicreds.PaddedInt(*cmdGetVersion), encContext)
		}
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		if *logJSON {
			log.WithFields(log.Fields{"name": *cmdGetName, "secret": cred.Secret, "status": "success"}).Info(cred.Secret)
		} else {
			// Or just print, out of backwards compatibility
			printSecret(cred.Secret, *cmdGetNoLine)
		}

	case cmdPut.FullCommand():
		version, err := unicreds.ResolveVersion(dynamoTable, *cmdPutName, *cmdPutVersion)
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		err = unicreds.PutSecret(dynamoTable, *alias, *cmdPutName, *cmdPutSecret, version, encContext)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"name": *cmdPutName, "version": version}).Info("stored")
	case cmdPutFile.FullCommand():
		version, err := unicreds.ResolveVersion(dynamoTable, *cmdPutFileName, *cmdPutFileVersion)
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		data, err := ioutil.ReadFile(*cmdPutFileSecretPath)
		if err != nil {
			printFatalError(err)
		}

		err = unicreds.PutSecret(dynamoTable, *alias, *cmdPutFileName, string(data), version, encContext)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"name": *cmdPutFileName, "version": version}).Info("stored")
	case cmdList.FullCommand():
		creds, err := unicreds.ListSecrets(dynamoTable, *cmdListAllVersions)
		if err != nil {
			printFatalError(err)
		}

		table := unicreds.NewTable(os.Stdout)
		table.SetHeaders([]string{"Name", "Version", "Created-At"})

		if *csv {
			table.SetFormat(unicreds.TableFormatCSV)
		}

		for _, cred := range creds {
			table.Write([]string{cred.Name, cred.Version, cred.CreatedAtDate()})
		}
		if err = table.Render(); err != nil {
			printFatalError(err)
		}
	case cmdGetAll.FullCommand():
		creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
		if err != nil {
			printFatalError(err)
		}

		table := unicreds.NewTable(os.Stdout)
		table.SetHeaders([]string{"Name", "Secret"})

		if *csv {
			table.SetFormat(unicreds.TableFormatCSV)
		}

		for _, cred := range creds {
			table.Write([]string{cred.Name, cred.Secret})
		}

		if err = table.Render(); err != nil {
			printFatalError(err)
		}
	case cmdDelete.FullCommand():
		err := unicreds.DeleteSecret(dynamoTable, *cmdDeleteName)
		if err != nil {
			printFatalError(err)
		}
	case cmdExecute.FullCommand():
		args := []string(*cmdExecuteCommand)
		commandPath, err := exec.LookPath(args[0])
		if err != nil {
			printFatalError(err)
		}
		creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
		for _, cred := range creds {
			os.Setenv(cred.Name, cred.Secret)
		}
		err = syscall.Exec(commandPath, args, os.Environ())
		if err != nil {
			printFatalError(err)
		}
	}
}

func printFatalError(err error) {
	log.WithError(err).Error("failed")
	os.Exit(1)
}

func printSecret(secret string, noline bool) {
	log.WithField("noline", noline).Debug("print secret")
	if noline {
		fmt.Printf(secret)
	} else {
		fmt.Println(secret)
	}
}

func printEncryptionContext(encContext *unicreds.EncryptionContextValue) {
	if encContext == nil || len(*encContext) == 0 {
		return
	}

	for key, value := range *encContext {
		log.WithFields(log.Fields{"Key": key, "Value": *value}).Debug("Encryption Context")
	}
}

func encryptionContext(s kingpin.Settings) (target *unicreds.EncryptionContextValue) {
	target = unicreds.NewEncryptionContextValue()
	s.SetValue((*unicreds.EncryptionContextValue)(target))
	return
}
<commit_msg>Fix printSecret bug when input contains fmt verb<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"syscall"

	"github.com/apex/log"
	"github.com/apex/log/handlers/cli"
	"github.com/apex/log/handlers/json"

	"github.com/alecthomas/kingpin"
	"github.com/versent/unicreds"
)

var (
	app     = kingpin.New("unicreds", "A credential/secret storage command line tool.")
	csv     = app.Flag("csv", "Enable csv output for table data.").Short('c').Bool()
	debug   = app.Flag("debug", "Enable debug mode.").Short('d').Bool()
	logJSON = app.Flag("json", "Output results in JSON").Short('j').Bool()

	region  = app.Flag("region", "Configure the AWS region").Short('r').String()
	profile = app.Flag("profile", "Configure the AWS profile").Short('p').String()
	role    = app.Flag("role", "Specify an AWS role ARN to assume").Short('R').String()

	dynamoTable = app.Flag("table", "DynamoDB table.").Default("credential-store").OverrideDefaultFromEnvar("UNICREDS_TABLE").Short('t').String()
	alias       = app.Flag("alias", "KMS key alias.").Default("alias/credstash").OverrideDefaultFromEnvar("UNICREDS_ALIAS").Short('k').String()
	encContext  = encryptionContext(app.Flag("enc-context", "Add a key value pair to the encryption context.").Short('E'))

	// commands
	cmdSetup      = app.Command("setup", "Setup the dynamodb table used to store credentials.")
	cmdSetupRead  = cmdSetup.Flag("read", "Dynamo read capacity.").Default("4").Int64()
	cmdSetupWrite = cmdSetup.Flag("write", "Dynamo write capacity.").Default("4").Int64()

	cmdGet        = app.Command("get", "Get a credential from the store.")
	cmdGetName    = cmdGet.Arg("credential", "The name of the credential to get.").Required().String()
	cmdGetNoLine  = cmdGet.Flag("noline", "Leave off the newline when emitting secret").Short('n').Bool()
	cmdGetVersion = cmdGet.Arg("version", "The version of the credential to get.").Int()

	cmdGetAll         = app.Command("getall", "Get latest credentials from the store.")
	cmdGetAllVersions = cmdGetAll.Flag("all", "List all versions").Bool()

	cmdList            = app.Command("list", "List latest credentials with names and version.")
	cmdListAllVersions = cmdList.Flag("all", "List all versions").Bool()

	cmdPut        = app.Command("put", "Put a credential into the store.")
	cmdPutName    = cmdPut.Arg("credential", "The name of the credential to store.").Required().String()
	cmdPutSecret  = cmdPut.Arg("value", "The value of the credential to store.").Required().String()
	cmdPutVersion = cmdPut.Arg("version", "Version to store with the credential.").Int()

	cmdPutFile           = app.Command("put-file", "Put a credential from a file into the store.")
	cmdPutFileName       = cmdPutFile.Arg("credential", "The name of the credential to store.").Required().String()
	cmdPutFileSecretPath = cmdPutFile.Arg("value", "Path to file containing the credential to store.").Required().String()
	cmdPutFileVersion    = cmdPutFile.Arg("version", "Version to store with the credential.").Int()

	cmdDelete     = app.Command("delete", "Delete a credential from the store.")
	cmdDeleteName = cmdDelete.Arg("credential", "The name of the credential to delete.").Required().String()

	cmdExecute        = app.Command("exec", "Execute a command with all secrets loaded as environment variables.")
	cmdExecuteCommand = cmdExecute.Arg("command", "The command to execute.").Required().Strings()

	// Version app version
	Version = "1.0.0"
)

func main() {
	app.Version(Version)

	command := kingpin.MustParse(app.Parse(os.Args[1:]))

	if *logJSON {
		log.SetHandler(json.New(os.Stderr))
	} else {
		log.SetHandler(cli.Default)
	}

	if *debug {
		log.SetLevel(log.DebugLevel)
	}

	unicreds.SetAwsConfig(region, profile, role)

	switch command {
	case cmdSetup.FullCommand():
		err := unicreds.Setup(dynamoTable, cmdSetupRead, cmdSetupWrite)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"status": "success"}).Info("Created table")
	case cmdGet.FullCommand():
		var cred *unicreds.DecryptedCredential
		var err error
		if *cmdGetVersion == 0 {
			cred, err = unicreds.GetHighestVersionSecret(dynamoTable, *cmdGetName, encContext)
		} else {
			cred, err = unicreds.GetSecret(dynamoTable, *cmdGetName, unicreds.PaddedInt(*cmdGetVersion), encContext)
		}
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		if *logJSON {
			log.WithFields(log.Fields{"name": *cmdGetName, "secret": cred.Secret, "status": "success"}).Info(cred.Secret)
		} else {
			// Or just print, out of backwards compatibility
			printSecret(cred.Secret, *cmdGetNoLine)
		}

	case cmdPut.FullCommand():
		version, err := unicreds.ResolveVersion(dynamoTable, *cmdPutName, *cmdPutVersion)
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		err = unicreds.PutSecret(dynamoTable, *alias, *cmdPutName, *cmdPutSecret, version, encContext)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"name": *cmdPutName, "version": version}).Info("stored")
	case cmdPutFile.FullCommand():
		version, err := unicreds.ResolveVersion(dynamoTable, *cmdPutFileName, *cmdPutFileVersion)
		if err != nil {
			printFatalError(err)
		}

		printEncryptionContext(encContext)

		data, err := ioutil.ReadFile(*cmdPutFileSecretPath)
		if err != nil {
			printFatalError(err)
		}

		err = unicreds.PutSecret(dynamoTable, *alias, *cmdPutFileName, string(data), version, encContext)
		if err != nil {
			printFatalError(err)
		}
		log.WithFields(log.Fields{"name": *cmdPutFileName, "version": version}).Info("stored")
	case cmdList.FullCommand():
		creds, err := unicreds.ListSecrets(dynamoTable, *cmdListAllVersions)
		if err != nil {
			printFatalError(err)
		}

		table := unicreds.NewTable(os.Stdout)
		table.SetHeaders([]string{"Name", "Version", "Created-At"})

		if *csv {
			table.SetFormat(unicreds.TableFormatCSV)
		}

		for _, cred := range creds {
			table.Write([]string{cred.Name, cred.Version, cred.CreatedAtDate()})
		}
		if err = table.Render(); err != nil {
			printFatalError(err)
		}
	case cmdGetAll.FullCommand():
		creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
		if err != nil {
			printFatalError(err)
		}

		table := unicreds.NewTable(os.Stdout)
		table.SetHeaders([]string{"Name", "Secret"})

		if *csv {
			table.SetFormat(unicreds.TableFormatCSV)
		}

		for _, cred := range creds {
			table.Write([]string{cred.Name, cred.Secret})
		}

		if err = table.Render(); err != nil {
			printFatalError(err)
		}
	case cmdDelete.FullCommand():
		err := unicreds.DeleteSecret(dynamoTable, *cmdDeleteName)
		if err != nil {
			printFatalError(err)
		}
	case cmdExecute.FullCommand():
		args := []string(*cmdExecuteCommand)
		commandPath, err := exec.LookPath(args[0])
		if err != nil {
			printFatalError(err)
		}
		creds, err := unicreds.GetAllSecrets(dynamoTable, *cmdGetAllVersions, encContext)
		for _, cred := range creds {
			os.Setenv(cred.Name, cred.Secret)
		}
		err = syscall.Exec(commandPath, args, os.Environ())
		if err != nil {
			printFatalError(err)
		}
	}
}

func printFatalError(err error) {
	log.WithError(err).Error("failed")
	os.Exit(1)
}

func printSecret(secret string, noline bool) {
	log.WithField("noline", noline).Debug("print secret")
	if noline {
		fmt.Print(secret)
	} else {
		fmt.Println(secret)
	}
}

func printEncryptionContext(encContext *unicreds.EncryptionContextValue) {
	if encContext == nil || len(*encContext) == 0 {
		return
	}

	for key, value := range *encContext {
		log.WithFields(log.Fields{"Key": key, "Value": *value}).Debug("Encryption Context")
	}
}

func encryptionContext(s kingpin.Settings) (target *unicreds.EncryptionContextValue) {
	target = unicreds.NewEncryptionContextValue()
	s.SetValue((*unicreds.EncryptionContextValue)(target))
	return
}
<|endoftext|>