<commit_before>package lion

import (
	"net/http"
	"os"
	"path"
	"strings"
	"sync"

	"golang.org/x/net/context"
)

// Router is the main component of Lion. It is responsible for registering handlers and middlewares
type Router struct {
	rm RegisterMatcher

	router *Router

	middlewares Middlewares

	handler Handler // TODO: create a handler

	pattern string

	notFoundHandler Handler

	registeredHandlers []registeredHandler // Used for Mount()

	pool sync.Pool

	namedMiddlewares map[string]Middlewares
}

// New creates a new router instance
func New(mws ...Middleware) *Router {
	r := &Router{
		middlewares:      Middlewares{},
		rm:               newRadixMatcher(),
		namedMiddlewares: make(map[string]Middlewares),
	}
	r.pool.New = func() interface{} {
		return NewContext()
	}
	r.router = r
	r.Use(mws...)
	return r
}

// Group creates a subrouter with parent pattern provided.
func (r *Router) Group(pattern string, mws ...Middleware) *Router {
	p := r.pattern + pattern
	if pattern == "/" && r.pattern != "/" {
		p = r.pattern
	}
	validatePattern(p)

	nr := &Router{
		router:           r,
		rm:               r.rm,
		pattern:          p,
		middlewares:      Middlewares{},
		namedMiddlewares: make(map[string]Middlewares),
	}
	nr.Use(mws...)
	return nr
}

// Get registers an http GET method receiver with the provided Handler
func (r *Router) Get(pattern string, handler Handler) {
	r.Handle("GET", pattern, handler)
}

// Head registers an http HEAD method receiver with the provided Handler
func (r *Router) Head(pattern string, handler Handler) {
	r.Handle("HEAD", pattern, handler)
}

// Post registers an http POST method receiver with the provided Handler
func (r *Router) Post(pattern string, handler Handler) {
	r.Handle("POST", pattern, handler)
}

// Put registers an http PUT method receiver with the provided Handler
func (r *Router) Put(pattern string, handler Handler) {
	r.Handle("PUT", pattern, handler)
}

// Delete registers an http DELETE method receiver with the provided Handler
func (r *Router) Delete(pattern string, handler Handler) {
	r.Handle("DELETE", pattern, handler)
}

// Trace registers an http TRACE method receiver with the provided Handler
func (r *Router) Trace(pattern string, handler Handler) {
	r.Handle("TRACE", pattern, handler)
}

// Options registers an http OPTIONS method receiver with the provided Handler
func (r *Router) Options(pattern string, handler Handler) {
	r.Handle("OPTIONS", pattern, handler)
}

// Connect registers an http CONNECT method receiver with the provided Handler
func (r *Router) Connect(pattern string, handler Handler) {
	r.Handle("CONNECT", pattern, handler)
}

// Patch registers an http PATCH method receiver with the provided Handler
func (r *Router) Patch(pattern string, handler Handler) {
	r.Handle("PATCH", pattern, handler)
}

// GetFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) GetFunc(pattern string, fn HandlerFunc) {
	r.Get(pattern, HandlerFunc(fn))
}

// HeadFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) HeadFunc(pattern string, fn HandlerFunc) {
	r.Head(pattern, HandlerFunc(fn))
}

// PostFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PostFunc(pattern string, fn HandlerFunc) {
	r.Post(pattern, HandlerFunc(fn))
}

// PutFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PutFunc(pattern string, fn HandlerFunc) {
	r.Put(pattern, HandlerFunc(fn))
}

// DeleteFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) DeleteFunc(pattern string, fn HandlerFunc) {
	r.Delete(pattern, HandlerFunc(fn))
}

// TraceFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) TraceFunc(pattern string, fn HandlerFunc) {
	r.Trace(pattern, HandlerFunc(fn))
}

// OptionsFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) OptionsFunc(pattern string, fn HandlerFunc) {
	r.Options(pattern, HandlerFunc(fn))
}

// ConnectFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) ConnectFunc(pattern string, fn HandlerFunc) {
	r.Connect(pattern, HandlerFunc(fn))
}

// PatchFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PatchFunc(pattern string, fn HandlerFunc) {
	r.Patch(pattern, HandlerFunc(fn))
}

// Use registers middlewares to be used
func (r *Router) Use(middlewares ...Middleware) {
	r.middlewares = append(r.middlewares, middlewares...)
}

// UseFunc wraps a MiddlewareFunc as a Middleware and registers it middlewares to be used
func (r *Router) UseFunc(middlewareFuncs ...MiddlewareFunc) {
	for _, fn := range middlewareFuncs {
		r.Use(MiddlewareFunc(fn))
	}
}

type negroniHandler interface {
	ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

type negroniHandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func (h negroniHandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	h(rw, r, next)
}

func (r *Router) UseNegroni(n negroniHandler) {
	r.Use(MiddlewareFunc(func(next Handler) Handler {
		return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
			n.ServeHTTP(w, r, HandlerFunc(func(_ context.Context, w http.ResponseWriter, r *http.Request) {
				next.ServeHTTPC(c, w, r)
			}).ServeHTTP)
		})
	}))
}

func (r *Router) UseNegroniFunc(n func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
	r.UseNegroni(negroniHandlerFunc(n))
}

// UseHandler uses
func (r *Router) UseHandler(handler Handler) {
	r.UseFunc(func(next Handler) Handler {
		return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
			handler.ServeHTTPC(c, w, r)
			next.ServeHTTPC(c, w, r)
		})
	})
}

// UseHandlerFunc uses
func (r *Router) UseHandlerFunc(fn HandlerFunc) {
	r.UseHandler(HandlerFunc(fn))
}

// Handle is the underling method responsible for registering a handler for a specific method and pattern.
func (r *Router) Handle(method, pattern string, handler Handler) {
	validatePattern(pattern)

	var p string
	if !r.isRoot() && pattern == "/" {
		p = r.pattern
	} else {
		p = r.pattern + pattern
	}

	built := r.buildMiddlewares(handler)
	r.registeredHandlers = append(r.registeredHandlers, registeredHandler{method, pattern, built})
	r.router.rm.Register(method, p, built)
}

type registeredHandler struct {
	method, pattern string
	handler         Handler
}

// Mount mounts a subrouter at the provided pattern
func (r *Router) Mount(pattern string, router *Router, mws ...Middleware) {
	sub := r.Group(pattern, mws...)
	for _, rh := range router.registeredHandlers {
		sub.Handle(rh.method, rh.pattern, rh.handler)
	}
}

func (r *Router) buildMiddlewares(handler Handler) Handler {
	handler = r.middlewares.BuildHandler(handler)
	if !r.isRoot() {
		handler = r.router.buildMiddlewares(handler)
	}
	return handler
}

func (r *Router) isRoot() bool {
	return r.router == r
}

// HandleFunc wraps a HandlerFunc and pass it to Handle method
func (r *Router) HandleFunc(method, pattern string, fn HandlerFunc) {
	r.Handle(method, pattern, HandlerFunc(fn))
}

// ServeHTTP calls ServeHTTPC with a context.Background()
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	r.ServeHTTPC(context.Background(), w, req)
}

// ServeHTTPC finds the handler associated with the request's path.
// If it is not found it calls the NotFound handler
func (r *Router) ServeHTTPC(c context.Context, w http.ResponseWriter, req *http.Request) {
	ctx := r.pool.Get().(*Context)
	ctx.parent = c

	if ctx, h := r.router.rm.Match(ctx, req); h != nil {
		h.ServeHTTPC(ctx, w, req)
	} else {
		r.notFound(ctx, w, req) // r.middlewares.BuildHandler(HandlerFunc(r.NotFound)).ServeHTTPC
	}

	ctx.reset()
	r.pool.Put(ctx)
}

// NotFound calls NotFoundHandler() if it is set. Otherwise, it calls net/http.NotFound
func (r *Router) notFound(c context.Context, w http.ResponseWriter, req *http.Request) {
	if r.router.notFoundHandler != nil {
		r.router.notFoundHandler.ServeHTTPC(c, w, req)
	} else {
		http.NotFound(w, req)
	}
}

func (r *Router) NotFoundHandler(handler Handler) {
	r.notFoundHandler = handler
}

// ServeFiles serves files located in root http.FileSystem
//
// This can be used as shown below:
// 	r := New()
// 	r.ServeFiles("/static", http.Dir("static")) // This will serve files in the directory static with /static prefix
func (r *Router) ServeFiles(base string, root http.FileSystem) {
	if strings.IndexAny(base, ":*") != -1 {
		panic("Lion: ServeFiles cannot have url parameters")
	}

	pattern := path.Join(base, "/*")
	fileServer := http.StripPrefix(base, http.FileServer(root))

	r.GetH(pattern, fileServer)
}

// GetH wraps a http.Handler
func (r *Router) GetH(pattern string, handler http.Handler) {
	r.Get(pattern, Wrap(handler))
}

// HeadH wraps a http.Handler
func (r *Router) HeadH(pattern string, handler http.Handler) {
	r.Head(pattern, Wrap(handler))
}

// PostH wraps a http.Handler
func (r *Router) PostH(pattern string, handler http.Handler) {
	r.Post(pattern, Wrap(handler))
}

// PutH wraps a http.Handler
func (r *Router) PutH(pattern string, handler http.Handler) {
	r.Put(pattern, Wrap(handler))
}

// DeleteH wraps a http.Handler
func (r *Router) DeleteH(pattern string, handler http.Handler) {
	r.Delete(pattern, Wrap(handler))
}

// TraceH wraps a http.Handler
func (r *Router) TraceH(pattern string, handler http.Handler) {
	r.Trace(pattern, Wrap(handler))
}

// OptionsH wraps a http.Handler
func (r *Router) OptionsH(pattern string, handler http.Handler) {
	r.Options(pattern, Wrap(handler))
}

// ConnectH wraps a http.Handler
func (r *Router) ConnectH(pattern string, handler http.Handler) {
	r.Connect(pattern, Wrap(handler))
}

// PatchH wraps a http.Handler
func (r *Router) PatchH(pattern string, handler http.Handler) {
	r.Patch(pattern, Wrap(handler))
}

// Run calls http.ListenAndServe for the current router.
// If no addresses are specified as arguments, it will use the PORT environnement variable if it is defined. Otherwise, it will listen on port 3000 of the localmachine
//
// 	r := New()
// 	r.Run() // will call
// 	r.Run(":8080")
func (r *Router) Run(addr ...string) {
	var a string

	if len(addr) == 0 {
		if p := os.Getenv("PORT"); p != "" {
			a = p
		} else {
			a = ":3000"
		}
	} else {
		a = addr[0]
	}

	lionLogger.Printf("listening on %s", a)
	lionLogger.Fatal(http.ListenAndServe(a, r))
}

// RunTLS calls http.ListenAndServeTLS for the current router
//
// 	r := New()
// 	r.RunTLS(":3443", "cert.pem", "key.pem")
func (r *Router) RunTLS(addr, certFile, keyFile string) {
	lionLogger.Printf("listening on %s", addr)
	lionLogger.Fatal(http.ListenAndServeTLS(addr, certFile, keyFile, r))
}

// Define registers some middleware using a name for reuse later using UseNamed method.
func (r *Router) Define(name string, mws ...Middleware) {
	r.namedMiddlewares[name] = append(r.namedMiddlewares[name], mws...)
}

// Define is a convenience wrapper for Define() to use MiddlewareFunc instead of a Middleware instance
func (r *Router) DefineFunc(name string, mws ...MiddlewareFunc) {
	for _, mw := range mws {
		r.Define(name, mw)
	}
}

// UseNamed adds a middleware already defined using Define method.
// If it cannot find it in the current router, it will look for it in the parent router.
func (r *Router) UseNamed(name string) {
	if r.hasNamed(name) { // Find if it this is registered in the current router
		r.Use(r.namedMiddlewares[name]...)
	} else if !r.isRoot() { // Otherwise, look for it in parent router.
		r.router.UseNamed(name)
	} else { // not found
		panic("Unknow named middlewares: " + name)
	}
}

func (r *Router) hasNamed(name string) bool {
	_, exist := r.namedMiddlewares[name]
	return exist
}

func validatePattern(pattern string) {
	if len(pattern) > 0 && pattern[0] != '/' {
		panic("path must start with '/' in path '" + pattern + "'")
	}
}
<commit_msg>Use ContainsAny instead of IndexAny<commit_after>package lion

import (
	"net/http"
	"os"
	"path"
	"strings"
	"sync"

	"golang.org/x/net/context"
)

// Router is the main component of Lion. It is responsible for registering handlers and middlewares
type Router struct {
	rm RegisterMatcher

	router *Router

	middlewares Middlewares

	handler Handler // TODO: create a handler

	pattern string

	notFoundHandler Handler

	registeredHandlers []registeredHandler // Used for Mount()

	pool sync.Pool

	namedMiddlewares map[string]Middlewares
}

// New creates a new router instance
func New(mws ...Middleware) *Router {
	r := &Router{
		middlewares:      Middlewares{},
		rm:               newRadixMatcher(),
		namedMiddlewares: make(map[string]Middlewares),
	}
	r.pool.New = func() interface{} {
		return NewContext()
	}
	r.router = r
	r.Use(mws...)
	return r
}

// Group creates a subrouter with parent pattern provided.
func (r *Router) Group(pattern string, mws ...Middleware) *Router {
	p := r.pattern + pattern
	if pattern == "/" && r.pattern != "/" {
		p = r.pattern
	}
	validatePattern(p)

	nr := &Router{
		router:           r,
		rm:               r.rm,
		pattern:          p,
		middlewares:      Middlewares{},
		namedMiddlewares: make(map[string]Middlewares),
	}
	nr.Use(mws...)
	return nr
}

// Get registers an http GET method receiver with the provided Handler
func (r *Router) Get(pattern string, handler Handler) {
	r.Handle("GET", pattern, handler)
}

// Head registers an http HEAD method receiver with the provided Handler
func (r *Router) Head(pattern string, handler Handler) {
	r.Handle("HEAD", pattern, handler)
}

// Post registers an http POST method receiver with the provided Handler
func (r *Router) Post(pattern string, handler Handler) {
	r.Handle("POST", pattern, handler)
}

// Put registers an http PUT method receiver with the provided Handler
func (r *Router) Put(pattern string, handler Handler) {
	r.Handle("PUT", pattern, handler)
}

// Delete registers an http DELETE method receiver with the provided Handler
func (r *Router) Delete(pattern string, handler Handler) {
	r.Handle("DELETE", pattern, handler)
}

// Trace registers an http TRACE method receiver with the provided Handler
func (r *Router) Trace(pattern string, handler Handler) {
	r.Handle("TRACE", pattern, handler)
}

// Options registers an http OPTIONS method receiver with the provided Handler
func (r *Router) Options(pattern string, handler Handler) {
	r.Handle("OPTIONS", pattern, handler)
}

// Connect registers an http CONNECT method receiver with the provided Handler
func (r *Router) Connect(pattern string, handler Handler) {
	r.Handle("CONNECT", pattern, handler)
}

// Patch registers an http PATCH method receiver with the provided Handler
func (r *Router) Patch(pattern string, handler Handler) {
	r.Handle("PATCH", pattern, handler)
}

// GetFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) GetFunc(pattern string, fn HandlerFunc) {
	r.Get(pattern, HandlerFunc(fn))
}

// HeadFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) HeadFunc(pattern string, fn HandlerFunc) {
	r.Head(pattern, HandlerFunc(fn))
}

// PostFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PostFunc(pattern string, fn HandlerFunc) {
	r.Post(pattern, HandlerFunc(fn))
}

// PutFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PutFunc(pattern string, fn HandlerFunc) {
	r.Put(pattern, HandlerFunc(fn))
}

// DeleteFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) DeleteFunc(pattern string, fn HandlerFunc) {
	r.Delete(pattern, HandlerFunc(fn))
}

// TraceFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) TraceFunc(pattern string, fn HandlerFunc) {
	r.Trace(pattern, HandlerFunc(fn))
}

// OptionsFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) OptionsFunc(pattern string, fn HandlerFunc) {
	r.Options(pattern, HandlerFunc(fn))
}

// ConnectFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) ConnectFunc(pattern string, fn HandlerFunc) {
	r.Connect(pattern, HandlerFunc(fn))
}

// PatchFunc wraps a HandlerFunc as a Handler and registers it to the router
func (r *Router) PatchFunc(pattern string, fn HandlerFunc) {
	r.Patch(pattern, HandlerFunc(fn))
}

// Use registers middlewares to be used
func (r *Router) Use(middlewares ...Middleware) {
	r.middlewares = append(r.middlewares, middlewares...)
}

// UseFunc wraps a MiddlewareFunc as a Middleware and registers it middlewares to be used
func (r *Router) UseFunc(middlewareFuncs ...MiddlewareFunc) {
	for _, fn := range middlewareFuncs {
		r.Use(MiddlewareFunc(fn))
	}
}

type negroniHandler interface {
	ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
}

type negroniHandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)

func (h negroniHandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	h(rw, r, next)
}

func (r *Router) UseNegroni(n negroniHandler) {
	r.Use(MiddlewareFunc(func(next Handler) Handler {
		return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
			n.ServeHTTP(w, r, HandlerFunc(func(_ context.Context, w http.ResponseWriter, r *http.Request) {
				next.ServeHTTPC(c, w, r)
			}).ServeHTTP)
		})
	}))
}

func (r *Router) UseNegroniFunc(n func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
	r.UseNegroni(negroniHandlerFunc(n))
}

// UseHandler uses
func (r *Router) UseHandler(handler Handler) {
	r.UseFunc(func(next Handler) Handler {
		return HandlerFunc(func(c context.Context, w http.ResponseWriter, r *http.Request) {
			handler.ServeHTTPC(c, w, r)
			next.ServeHTTPC(c, w, r)
		})
	})
}

// UseHandlerFunc uses
func (r *Router) UseHandlerFunc(fn HandlerFunc) {
	r.UseHandler(HandlerFunc(fn))
}

// Handle is the underling method responsible for registering a handler for a specific method and pattern.
func (r *Router) Handle(method, pattern string, handler Handler) {
	validatePattern(pattern)

	var p string
	if !r.isRoot() && pattern == "/" {
		p = r.pattern
	} else {
		p = r.pattern + pattern
	}

	built := r.buildMiddlewares(handler)
	r.registeredHandlers = append(r.registeredHandlers, registeredHandler{method, pattern, built})
	r.router.rm.Register(method, p, built)
}

type registeredHandler struct {
	method, pattern string
	handler         Handler
}

// Mount mounts a subrouter at the provided pattern
func (r *Router) Mount(pattern string, router *Router, mws ...Middleware) {
	sub := r.Group(pattern, mws...)
	for _, rh := range router.registeredHandlers {
		sub.Handle(rh.method, rh.pattern, rh.handler)
	}
}

func (r *Router) buildMiddlewares(handler Handler) Handler {
	handler = r.middlewares.BuildHandler(handler)
	if !r.isRoot() {
		handler = r.router.buildMiddlewares(handler)
	}
	return handler
}

func (r *Router) isRoot() bool {
	return r.router == r
}

// HandleFunc wraps a HandlerFunc and pass it to Handle method
func (r *Router) HandleFunc(method, pattern string, fn HandlerFunc) {
	r.Handle(method, pattern, HandlerFunc(fn))
}

// ServeHTTP calls ServeHTTPC with a context.Background()
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	r.ServeHTTPC(context.Background(), w, req)
}

// ServeHTTPC finds the handler associated with the request's path.
// If it is not found it calls the NotFound handler
func (r *Router) ServeHTTPC(c context.Context, w http.ResponseWriter, req *http.Request) {
	ctx := r.pool.Get().(*Context)
	ctx.parent = c

	if ctx, h := r.router.rm.Match(ctx, req); h != nil {
		h.ServeHTTPC(ctx, w, req)
	} else {
		r.notFound(ctx, w, req) // r.middlewares.BuildHandler(HandlerFunc(r.NotFound)).ServeHTTPC
	}

	ctx.reset()
	r.pool.Put(ctx)
}

// NotFound calls NotFoundHandler() if it is set. Otherwise, it calls net/http.NotFound
func (r *Router) notFound(c context.Context, w http.ResponseWriter, req *http.Request) {
	if r.router.notFoundHandler != nil {
		r.router.notFoundHandler.ServeHTTPC(c, w, req)
	} else {
		http.NotFound(w, req)
	}
}

func (r *Router) NotFoundHandler(handler Handler) {
	r.notFoundHandler = handler
}

// ServeFiles serves files located in root http.FileSystem
//
// This can be used as shown below:
// 	r := New()
// 	r.ServeFiles("/static", http.Dir("static")) // This will serve files in the directory static with /static prefix
func (r *Router) ServeFiles(base string, root http.FileSystem) {
	if strings.ContainsAny(base, ":*") {
		panic("Lion: ServeFiles cannot have url parameters")
	}

	pattern := path.Join(base, "/*")
	fileServer := http.StripPrefix(base, http.FileServer(root))

	r.GetH(pattern, fileServer)
}

// GetH wraps a http.Handler
func (r *Router) GetH(pattern string, handler http.Handler) {
	r.Get(pattern, Wrap(handler))
}

// HeadH wraps a http.Handler
func (r *Router) HeadH(pattern string, handler http.Handler) {
	r.Head(pattern, Wrap(handler))
}

// PostH wraps a http.Handler
func (r *Router) PostH(pattern string, handler http.Handler) {
	r.Post(pattern, Wrap(handler))
}

// PutH wraps a http.Handler
func (r *Router) PutH(pattern string, handler http.Handler) {
	r.Put(pattern, Wrap(handler))
}

// DeleteH wraps a http.Handler
func (r *Router) DeleteH(pattern string, handler http.Handler) {
	r.Delete(pattern, Wrap(handler))
}

// TraceH wraps a http.Handler
func (r *Router) TraceH(pattern string, handler http.Handler) {
	r.Trace(pattern, Wrap(handler))
}

// OptionsH wraps a http.Handler
func (r *Router) OptionsH(pattern string, handler http.Handler) {
	r.Options(pattern, Wrap(handler))
}

// ConnectH wraps a http.Handler
func (r *Router) ConnectH(pattern string, handler http.Handler) {
	r.Connect(pattern, Wrap(handler))
}

// PatchH wraps a http.Handler
func (r *Router) PatchH(pattern string, handler http.Handler) {
	r.Patch(pattern, Wrap(handler))
}

// Run calls http.ListenAndServe for the current router.
// If no addresses are specified as arguments, it will use the PORT environnement variable if it is defined. Otherwise, it will listen on port 3000 of the localmachine
//
// 	r := New()
// 	r.Run() // will call
// 	r.Run(":8080")
func (r *Router) Run(addr ...string) {
	var a string

	if len(addr) == 0 {
		if p := os.Getenv("PORT"); p != "" {
			a = p
		} else {
			a = ":3000"
		}
	} else {
		a = addr[0]
	}

	lionLogger.Printf("listening on %s", a)
	lionLogger.Fatal(http.ListenAndServe(a, r))
}

// RunTLS calls http.ListenAndServeTLS for the current router
//
// 	r := New()
// 	r.RunTLS(":3443", "cert.pem", "key.pem")
func (r *Router) RunTLS(addr, certFile, keyFile string) {
	lionLogger.Printf("listening on %s", addr)
	lionLogger.Fatal(http.ListenAndServeTLS(addr, certFile, keyFile, r))
}

// Define registers some middleware using a name for reuse later using UseNamed method.
func (r *Router) Define(name string, mws ...Middleware) {
	r.namedMiddlewares[name] = append(r.namedMiddlewares[name], mws...)
}

// Define is a convenience wrapper for Define() to use MiddlewareFunc instead of a Middleware instance
func (r *Router) DefineFunc(name string, mws ...MiddlewareFunc) {
	for _, mw := range mws {
		r.Define(name, mw)
	}
}

// UseNamed adds a middleware already defined using Define method.
// If it cannot find it in the current router, it will look for it in the parent router.
func (r *Router) UseNamed(name string) {
	if r.hasNamed(name) { // Find if it this is registered in the current router
		r.Use(r.namedMiddlewares[name]...)
	} else if !r.isRoot() { // Otherwise, look for it in parent router.
		r.router.UseNamed(name)
	} else { // not found
		panic("Unknow named middlewares: " + name)
	}
}

func (r *Router) hasNamed(name string) bool {
	_, exist := r.namedMiddlewares[name]
	return exist
}

func validatePattern(pattern string) {
	if len(pattern) > 0 && pattern[0] != '/' {
		panic("path must start with '/' in path '" + pattern + "'")
	}
}
<|endoftext|>


<commit_before>package dirscanner_test

import (
	"cred-alert/scanners"
	"cred-alert/scanners/dirscanner"
	"cred-alert/sniff"
	"cred-alert/sniff/snifffakes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("DirScanner", func() {
	var scanner *dirscanner.DirScanner
	var sniffer *snifffakes.FakeSniffer
	var logger *lagertest.TestLogger
	var credentialCount int

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("dirscanner")
		credentialCount = 0
		handler := func(l lager.Logger, violation scanners.Violation) error {
			return nil
		}
		sniffer = &snifffakes.FakeSniffer{}
		sniffer.SniffStub = func(l lager.Logger, s sniff.Scanner, h sniff.ViolationHandlerFunc) error {
			for s.Scan(l) {
				line := s.Line(l)
				if strings.Contains(string(line.Content), "credential") {
					credentialCount++
				}
			}
			return nil
		}

		scanner = dirscanner.New(handler, sniffer)
	})

	Describe("Scan", func() {
		var tmpDir string
		BeforeEach(func() {
			var err error
			tmpDir, err = ioutil.TempDir("", "testdir")
			Expect(err).NotTo(HaveOccurred())
			err = ioutil.WriteFile(filepath.Join(tmpDir, "file1.txt"), []byte("credential"), 0600)
			Expect(err).NotTo(HaveOccurred())
			err = ioutil.WriteFile(filepath.Join(tmpDir, "file2.txt"), []byte("credential"), 0600)
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			_ = os.RemoveAll(tmpDir)
		})

		It("scans a directory", func() {
			err := scanner.Scan(logger, tmpDir)
			Expect(err).NotTo(HaveOccurred())
			Expect(sniffer.SniffCallCount()).To(Equal(2))
			Expect(credentialCount).To(Equal(2))
		})
	})
})
<commit_msg>Add missing dirscanner test assertion<commit_after>package dirscanner_test

import (
	"cred-alert/scanners"
	"cred-alert/scanners/dirscanner"
	"cred-alert/sniff"
	"cred-alert/sniff/snifffakes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"code.cloudfoundry.org/lager"
	"code.cloudfoundry.org/lager/lagertest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("DirScanner", func() {
	var scanner *dirscanner.DirScanner
	var sniffer *snifffakes.FakeSniffer
	var logger *lagertest.TestLogger
	var credentialCount int

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("dirscanner")
		credentialCount = 0
		handler := func(l lager.Logger, violation scanners.Violation) error {
			return nil
		}
		sniffer = &snifffakes.FakeSniffer{}
		sniffer.SniffStub = func(l lager.Logger, s sniff.Scanner, h sniff.ViolationHandlerFunc) error {
			for s.Scan(l) {
				line := s.Line(l)
				if strings.Contains(string(line.Content), "credential") {
					credentialCount++
				}
			}
			return nil
		}

		scanner = dirscanner.New(handler, sniffer)
	})

	Describe("Scan", func() {
		var tmpDir string
		BeforeEach(func() {
			var err error
			tmpDir, err = ioutil.TempDir("", "testdir")
			Expect(err).NotTo(HaveOccurred())
			err = ioutil.WriteFile(filepath.Join(tmpDir, "file1.txt"), []byte("credential"), 0600)
			Expect(err).NotTo(HaveOccurred())
			err = ioutil.WriteFile(filepath.Join(tmpDir, "file2.txt"), []byte("credential"), 0600)
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			_ = os.RemoveAll(tmpDir)
		})

		It("scans a directory", func() {
			err := scanner.Scan(logger, tmpDir)
			Expect(err).NotTo(HaveOccurred())

			Expect(sniffer.SniffCallCount()).To(Equal(2))
			Expect(credentialCount).To(Equal(2))
			Expect(handlerCallCount).To(Equal(2))
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/gorilla/mux"
)

func registerRoute(router *mux.Router, route Route, handler http.Handler) {
	router.
		Methods(route.Method).
		Path(route.Pattern).
		Name(route.Name).
		Handler(handler)
}

func NewRouter() *mux.Router {

	router := mux.NewRouter().StrictSlash(true)
	api := router.PathPrefix("/api/").Subrouter()
	//register public routes, no middleware needed
	for _, route := range publicRoutes {
		var handler http.Handler
		handler = jwtOptionalMiddleware.Handler(route.Handler)
		registerRoute(api, route, handler)
	}
	//register auth routes, only need to be logged in
	for _, route := range authRoutes {
		var handler http.Handler
		handler = jwtRequiredMiddleware.Handler(route.Handler)
		registerRoute(api, route, handler)
	}
	fs := http.Dir(conf.StaticFolder)
	fileHandler := http.FileServer(fs)
	router.PathPrefix("/assets/").Handler(fileHandler)
	router.PathPrefix("/images/").Handler(fileHandler)
	router.Path("/crossdomain.xml").Handler(fileHandler)
	router.Path("/robots.txt").Handler(fileHandler)
	router.NotFoundHandler = http.HandlerFunc(notFound)

	return router
}

func notFound(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, conf.StaticFolder+"index.html")
}
<commit_msg>simplify router by using subdirectory for frontend<commit_after>package main

import (
	"net/http"

	"github.com/gorilla/mux"
)

func registerRoute(router *mux.Router, route Route, handler http.Handler) {
	router.
		Methods(route.Method).
		Path(route.Pattern).
		Name(route.Name).
		Handler(handler)
}

func NewRouter() *mux.Router {

	router := mux.NewRouter().StrictSlash(true)
	api := router.PathPrefix("/api/").Subrouter()
	//register public routes, no middleware needed
	for _, route := range publicRoutes {
		var handler http.Handler
		handler = jwtOptionalMiddleware.Handler(route.Handler)
		registerRoute(api, route, handler)
	}
	//register auth routes, only need to be logged in
	for _, route := range authRoutes {
		var handler http.Handler
		handler = jwtRequiredMiddleware.Handler(route.Handler)
		registerRoute(api, route, handler)
	}
	fs := http.Dir(conf.StaticFolder)
	fileHandler := http.FileServer(fs)
	router.PathPrefix("/app/").Handler(http.HandlerFunc(notFound))
	router.PathPrefix("/").Handler(fileHandler)
	/*
		router.PathPrefix("/assets/").Handler(fileHandler)
		router.PathPrefix("/images/").Handler(fileHandler)
		router.Path("/crossdomain.xml").Handler(fileHandler)
		router.Path("/robots.txt").Handler(fileHandler)
		router.NotFoundHandler = http.HandlerFunc(notFound)
	*/
	return router
}

func notFound(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, conf.StaticFolder+"index.html")
}
<|endoftext|>


<commit_before>package main

import "net/http"

type Route struct {
	Name    string
	Method  string
	Pattern string
	Handler http.Handler
}

type Routes []Route

var adminRoutes = Routes{
	Route{
		"AllUnits",
		"GET",
		"/admin/allunits",
		AllUnits,
	},
	Route{
		"AdminPageById",
		"GET",
		"/admin/pages/{pageId}",
		AdminPageById,
	},
	Route{
		"AdminUpdateUnit",
		"PUT",
		"/admin/units/{unitId}",
		AdminUpdateUnit,
	},
}

var authRoutes = Routes{
	Route{
		"UnitCreate",
		"POST",
		"/units",
		UnitCreate,
	},
	Route{
		"UserUpdateUnit",
		"PUT",
		"/{userId}/units/{unitId}",
		UserUpdateUnit,
	},
	Route{
		"PageCreate",
		"POST",
		"/pages",
		PageCreate,
	},
	Route{
		"PageUpdate",
		"PUT",
		"/pages/{pageId}",
		UserUpdatePage,
	},
	Route{
		"UserUnits",
		"GET",
		"/{userId}/units",
		UserUnits,
	},
	Route{
		"UserPageById",
		"GET",
		"/{userId}/pages/{pageId}",
		UserPageById,
	},
}

var publicRoutes = Routes{
	Route{
		"PublishedUnits",
		"GET",
		"/units",
		PublishedUnits,
	},
	Route{
		"PageById",
		"GET",
		"/pages/{pageId}",
		PageById,
	},
	Route{
		"Login",
		"POST",
		"/login",
		LoginHandler,
	},
	Route{
		"Register",
		"POST",
		"/register",
		RegisterHandler,
	},
}
<commit_msg>change routes for authRoutes<commit_after>package main

import "net/http"

type Route struct {
	Name    string
	Method  string
	Pattern string
	Handler http.Handler
}

type Routes []Route

var adminRoutes = Routes{
	Route{
		"AllUnits",
		"GET",
		"/admin/allunits",
		AllUnits,
	},
	Route{
		"AdminPageById",
		"GET",
		"/admin/pages/{pageId}",
		AdminPageById,
	},
	Route{
		"AdminUpdateUnit",
		"PUT",
		"/admin/units/{unitId}",
		AdminUpdateUnit,
	},
}

var authRoutes = Routes{
	Route{
		"UnitCreate",
		"POST",
		"/users/{userId}/units",
		UnitCreate,
	},
	Route{
		"UserUpdateUnit",
		"PUT",
		"/users/{userId}/units/{unitId}",
		UserUpdateUnit,
	},
	Route{
		"PageCreate",
		"POST",
		"/users/{userId}/units/{unitId}/pages",
		PageCreate,
	},
	Route{
		"PageUpdate",
		"PUT",
		"/users/{userId}/units/{unitId}/pages/{pageId}",
		UserUpdatePage,
	},
	Route{
		"UserUnits",
		"GET",
		"/users/{userId}/units",
		UserUnits,
	},
	Route{
		"UserPageById",
		"GET",
		"/users/{userId}/units/{unitId}/pages/{pageId}",
		UserPageById,
	},
	Route{
		"UploadImage",
		"POST",
		"/users/{userId}/units/{unitId}/images",
		UploadImage,
	},
}

var publicRoutes = Routes{
	Route{
		"PublishedUnits",
		"GET",
		"/units",
		PublishedUnits,
	},
	Route{
		"PageById",
		"GET",
		"/pages/{pageId}",
		PageById,
	},
	Route{
		"Login",
		"POST",
		"/login",
		LoginHandler,
	},
	Route{
		"Register",
		"POST",
		"/register",
		RegisterHandler,
	},
}
<|endoftext|>


<commit_before>package prabbitmq

import (
	"fmt"

	"github.com/enaml-ops/enaml"
	"github.com/enaml-ops/pluginlib/pcli"
	"github.com/enaml-ops/pluginlib/product"
	"github.com/enaml-ops/pluginlib/util"
	"github.com/xchapter7x/lo"
)

// Plugin is an omg product plugin for deploying p-rabbitmq.
type Plugin struct {
	Version string
}

// generatePassword is the default for password flags that should be generated by
// the plugin if not specified by the user
const generatePassword = "[autogenerated]"

// GetFlags returns the CLI flags accepted by the plugin.
func (p *Plugin) GetFlags() []pcli.Flag {
	return []pcli.Flag{
		pcli.CreateStringFlag("deployment-name", "the name bosh will use for the deployment", "p-rabbitmq"),
		pcli.CreateStringFlag("service-admin-password", "the password used by cloud controller for authentication", generatePassword),
		pcli.CreateStringFlag("system-domain", "the system domain"),
		pcli.CreateStringFlag("rabbit-public-ip", "the public IP"),
		pcli.CreateStringFlag("rabbit-admin-password", "the admin password to use", generatePassword),
		pcli.CreateStringFlag("network", "the name of the network to use"),
		pcli.CreateStringFlag("stemcell-ver", "the version number of the stemcell you wish to use", StemcellVersion),
		pcli.CreateStringSliceFlag("rabbit-server-ip", "rabbit-mq server IPs to use"),
		pcli.CreateStringFlag("rabbit-broker-ip", "IP of the rabbitmq broker"),
		pcli.CreateStringFlag("broker-password", "password for the rabbitmq broker", generatePassword),
		pcli.CreateStringFlag("syslog-address", "the address of your syslog drain"),
		pcli.CreateIntFlag("syslog-port", "the port for your syslog connection", "514"),
		pcli.CreateStringSliceFlag("nats-machine-ip", "IP addresses of NATS machines"),
		pcli.CreateIntFlag("nats-port", "NATS port", "4222"),
		pcli.CreateStringFlag("nats-pass", "password for NATS", generatePassword),
		pcli.CreateStringFlag("haproxy-stats-password", "admin password to acces HAproxy stats dashboard", generatePassword),
		pcli.CreateStringFlag("system-services-password", "password for CF system_services account"),
		pcli.CreateBoolFlag("skip-ssl-verify", "skip SSL verification"),
		pcli.CreateStringFlag("doppler-zone", "the name zone for doppler"),
		pcli.CreateStringFlag("doppler-shared-secret", "doppler shared secret"),
		pcli.CreateStringSliceFlag("etcd-machine-ip", "IPs of etcd machines"),

		pcli.CreateStringFlag("vault-domain", "the location of your vault server (ie. http://10.0.0.1:8200)"),
		pcli.CreateStringFlag("vault-token", "the token to make connections to your vault"),
		pcli.CreateStringSliceFlag("vault-hash", "a list of vault hashes to pull values from"),
	}
}

// GetMeta returns metadata about the p-rabbitmq product.
func (p *Plugin) GetMeta() product.Meta {
	return product.Meta{
		Name: "p-rabbitmq",
		Properties: map[string]interface{}{
			"version":                  p.Version,
			"stemcell":                 StemcellVersion,
			"pivotal-rabbit-mq":        fmt.Sprintf("%s / %s", "pivotal-rabbit-mq", ProductVersion), // TODO match pivnet on name
			"cf-rabbitmq-release":      fmt.Sprintf("%s / %s", CFRabbitMQReleaseName, CFRabbitMQReleaseVersion),
			"service-metrics-release":  fmt.Sprintf("%s / %s", ServiceMetricsReleaseName, ServiceMetricsReleaseVersion),
			"loggregator-release":      fmt.Sprintf("%s / %s", LoggregatorReleaseName, LoggregatorReleaseVersion),
			"rabbitmq-metrics-release": fmt.Sprintf("%s / %s", RabbitMQMetricsReleaseName, RabbitMQMetricsReleaseVersion),
		},
	}
}

// GetProduct generates a BOSH deployment manifest for p-rabbitmq.
func (p *Plugin) GetProduct(args []string, cloudConfig []byte) []byte {
	flags := p.GetFlags()
	c := pluginutil.NewContext(args, pluginutil.ToCliFlagArray(flags))

	// populate flags from vault if configured to do so
	domain := c.String("vault-domain")
	tok := c.String("vault-token")
	hashes := c.StringSlice("vault-hash")
	if domain != "" && tok != "" && len(hashes) > 0 {
		lo.G.Debug("connecting to vault at", domain)
		v := pluginutil.NewVaultUnmarshal(domain, tok)
		for _, hash := range hashes {
			v.UnmarshalFlags(hash, flags)
		}
		c = pluginutil.NewContext(args, pluginutil.ToCliFlagArray(flags))
	}

	cfg, err := configFromContext(c)
	if err != nil {
		lo.G.Error(err.Error())
	}

	dm := new(enaml.DeploymentManifest)
	dm.SetName(cfg.DeploymentName)

	dm.AddRelease(enaml.Release{Name: CFRabbitMQReleaseName, Version: CFRabbitMQReleaseVersion})
	dm.AddRelease(enaml.Release{Name: ServiceMetricsReleaseName, Version: ServiceMetricsReleaseVersion})
	dm.AddRelease(enaml.Release{Name: LoggregatorReleaseName, Version: LoggregatorReleaseVersion})
	dm.AddRelease(enaml.Release{Name: RabbitMQMetricsReleaseName, Version: RabbitMQMetricsReleaseVersion})

	dm.AddStemcell(enaml.Stemcell{OS: StemcellName, Version: cfg.StemcellVersion, Alias: StemcellAlias})

	dm.AddInstanceGroup(p.NewRabbitMQServerPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQBrokerPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQHAProxyPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQBrokerRegistrar(cfg))

	dm.Update = enaml.Update{
		Canaries:        1,
		CanaryWatchTime: "30000-300000",
		UpdateWatchTime: "30000-300000",
		MaxInFlight:     1,
		Serial:          true,
	}

	return dm.Bytes()
}
<commit_msg>[#129472045] Add default value for --network flag.<commit_after>package prabbitmq

import (
	"fmt"

	"github.com/enaml-ops/enaml"
	"github.com/enaml-ops/pluginlib/pcli"
	"github.com/enaml-ops/pluginlib/product"
	"github.com/enaml-ops/pluginlib/util"
	"github.com/xchapter7x/lo"
)

// Plugin is an omg product plugin for deploying p-rabbitmq.
type Plugin struct {
	Version string
}

// generatePassword is the default for password flags that should be generated by
// the plugin if not specified by the user
const generatePassword = "[autogenerated]"

// GetFlags returns the CLI flags accepted by the plugin.
func (p *Plugin) GetFlags() []pcli.Flag {
	return []pcli.Flag{
		pcli.CreateStringFlag("deployment-name", "the name bosh will use for the deployment", "p-rabbitmq"),
		pcli.CreateStringFlag("service-admin-password", "the password used by cloud controller for authentication", generatePassword),
		pcli.CreateStringFlag("system-domain", "the system domain"),
		pcli.CreateStringFlag("rabbit-public-ip", "the public IP"),
		pcli.CreateStringFlag("rabbit-admin-password", "the admin password to use", generatePassword),
		pcli.CreateStringFlag("network", "the name of the network to use", "default"),
		pcli.CreateStringFlag("stemcell-ver", "the version number of the stemcell you wish to use", StemcellVersion),
		pcli.CreateStringSliceFlag("rabbit-server-ip", "rabbit-mq server IPs to use"),
		pcli.CreateStringFlag("rabbit-broker-ip", "IP of the rabbitmq broker"),
		pcli.CreateStringFlag("broker-password", "password for the rabbitmq broker", generatePassword),
		pcli.CreateStringFlag("syslog-address", "the address of your syslog drain"),
		pcli.CreateIntFlag("syslog-port", "the port for your syslog connection", "514"),
		pcli.CreateStringSliceFlag("nats-machine-ip", "IP addresses of NATS machines"),
		pcli.CreateIntFlag("nats-port", "NATS port", "4222"),
		pcli.CreateStringFlag("nats-pass", "password for NATS", generatePassword),
		pcli.CreateStringFlag("haproxy-stats-password", "admin password to acces HAproxy stats dashboard", generatePassword),
		pcli.CreateStringFlag("system-services-password", "password for CF system_services account"),
		pcli.CreateBoolFlag("skip-ssl-verify", "skip SSL verification"),
		pcli.CreateStringFlag("doppler-zone", "the name zone for doppler"),
		pcli.CreateStringFlag("doppler-shared-secret", "doppler shared secret"),
		pcli.CreateStringSliceFlag("etcd-machine-ip", "IPs of etcd machines"),

		pcli.CreateStringFlag("vault-domain", "the location of your vault server (ie. http://10.0.0.1:8200)"),
		pcli.CreateStringFlag("vault-token", "the token to make connections to your vault"),
		pcli.CreateStringSliceFlag("vault-hash", "a list of vault hashes to pull values from"),
	}
}

// GetMeta returns metadata about the p-rabbitmq product.
func (p *Plugin) GetMeta() product.Meta {
	return product.Meta{
		Name: "p-rabbitmq",
		Properties: map[string]interface{}{
			"version":                  p.Version,
			"stemcell":                 StemcellVersion,
			"pivotal-rabbit-mq":        fmt.Sprintf("%s / %s", "pivotal-rabbit-mq", ProductVersion), // TODO match pivnet on name
			"cf-rabbitmq-release":      fmt.Sprintf("%s / %s", CFRabbitMQReleaseName, CFRabbitMQReleaseVersion),
			"service-metrics-release":  fmt.Sprintf("%s / %s", ServiceMetricsReleaseName, ServiceMetricsReleaseVersion),
			"loggregator-release":      fmt.Sprintf("%s / %s", LoggregatorReleaseName, LoggregatorReleaseVersion),
			"rabbitmq-metrics-release": fmt.Sprintf("%s / %s", RabbitMQMetricsReleaseName, RabbitMQMetricsReleaseVersion),
		},
	}
}

// GetProduct generates a BOSH deployment manifest for p-rabbitmq.
func (p *Plugin) GetProduct(args []string, cloudConfig []byte) []byte {
	flags := p.GetFlags()
	c := pluginutil.NewContext(args, pluginutil.ToCliFlagArray(flags))

	// populate flags from vault if configured to do so
	domain := c.String("vault-domain")
	tok := c.String("vault-token")
	hashes := c.StringSlice("vault-hash")
	if domain != "" && tok != "" && len(hashes) > 0 {
		lo.G.Debug("connecting to vault at", domain)
		v := pluginutil.NewVaultUnmarshal(domain, tok)
		for _, hash := range hashes {
			v.UnmarshalFlags(hash, flags)
		}
		c = pluginutil.NewContext(args, pluginutil.ToCliFlagArray(flags))
	}

	cfg, err := configFromContext(c)
	if err != nil {
		lo.G.Error(err.Error())
	}

	dm := new(enaml.DeploymentManifest)
	dm.SetName(cfg.DeploymentName)

	dm.AddRelease(enaml.Release{Name: CFRabbitMQReleaseName, Version: CFRabbitMQReleaseVersion})
	dm.AddRelease(enaml.Release{Name: ServiceMetricsReleaseName, Version: ServiceMetricsReleaseVersion})
	dm.AddRelease(enaml.Release{Name: LoggregatorReleaseName, Version: LoggregatorReleaseVersion})
	dm.AddRelease(enaml.Release{Name: RabbitMQMetricsReleaseName, Version: RabbitMQMetricsReleaseVersion})

	dm.AddStemcell(enaml.Stemcell{OS: StemcellName, Version: cfg.StemcellVersion, Alias: StemcellAlias})

	dm.AddInstanceGroup(p.NewRabbitMQServerPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQBrokerPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQHAProxyPartition(cfg))
	dm.AddInstanceGroup(p.NewRabbitMQBrokerRegistrar(cfg))

	dm.Update = enaml.Update{
		Canaries:        1,
		CanaryWatchTime: "30000-300000",
		UpdateWatchTime: "30000-300000",
		MaxInFlight:     1,
		Serial:          true,
	}

	return dm.Bytes()
}
<|endoftext|>


<commit_before>package converters

import (
	"bufio"
	"io/ioutil"
	"log"
	"os/exec"
	"regexp"
	"strings"
)

type PostData struct {
	Meta struct {
		Title    string
		Subtitle string
		Author   string
		Date     string
	}

	Content    string
	ImagePaths []string
}

// Title => Title
func stripAnchorSpans(in string) string {
	re := regexp.MustCompile("]+?>(.*)")
	return re.ReplaceAllString(in, "${1}")
}

// 'foo' => foo
func cleanTitle(in string) string {
	re := regexp.MustCompile("^'?(.*?)'?$")
	return re.ReplaceAllString(in, "${1}")
}

func extractImagePaths(content string) []string {
	re := regexp.MustCompile(`!\[.*?\]\((.*?)\)`)

	matches := []string{}

	for _, match := range re.FindAllStringSubmatch(content, -1) {
		matches = append(matches, match[1])
	}

	return matches
}

// ExtractPostData converts a markdown string into PostData
func ExtractPostData(markdown string) PostData {
	var postData PostData

	lines := strings.Split(markdown, "\n")
	for i := range lines {
		lines[i] = stripAnchorSpans(lines[i])
	}

	// Where does the metadata end and content start?
	idx := 0

	// Grab and parse the metadata block, if it exists
	if lines[0] == "---" {
		for ; idx < len(lines); idx += 1 {
			line := lines[idx]

			// End of block
			if line == "..." {
				break
			}

			kv := strings.SplitN(line, ": ", 2)
			if len(kv) < 2 {
				continue
			} else if kv[1] == "|" {
				kv[1] = ""

				// Roll up multiline values
				for idx += 1; lines[idx] == "" || strings.HasPrefix(lines[idx], " "); idx += 1 {
					kv[1] += strings.TrimSpace(lines[idx])
				}
			}
			log.Printf("LINE: '%s'\n", line)
			switch kv[0] {
			case "title":
				postData.Meta.Title = cleanTitle(kv[1])

			case "subtitle":
				postData.Meta.Subtitle = cleanTitle(kv[1])
			}
		}
	} else {
		// If we don't have a real title, take the first non blank line.
		for _, line := range lines {
			if line != "" {
				postData.Meta.Title = line
			}
		}
	}

	postData.Content = strings.Join(lines[idx:], "\n")
	postData.ImagePaths = extractImagePaths(postData.Content)

	return postData
}

// Suckily, pandoc can't read .docx from streams, so we have to use a file
// interface.
func ConvertDocx(inputFile string, mediaDir string) (string, error) {
	args := []string{
		// from docx
		"-f", "docx",
		// to markdown
		"-t", "markdown",
		// standalone file (including meta)
		"-s",
		"--extract-media", mediaDir,
		"-i", inputFile,
	}

	cmd := exec.Command("pandoc", args...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("failed to open pandoc stdout: %v\n", err)
		return "", err
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Printf("failed to open pandoc stderr: %v\n", err)
		return "", err
	}

	if err := cmd.Start(); err != nil {
		log.Printf("failed to run pandoc: %v\n", err)
		return "", err
	}

	markdown, err := ioutil.ReadAll(stdout)
	if err != nil {
		log.Printf("failed reading from pandoc")
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		log.Printf("pandoc exited with an error: %v\n", err)

		// Make sure we print out the error output
		scanner := bufio.NewScanner(stderr)

		for scanner.Scan() {
			log.Println(scanner.Text())
		}

		return "", err
	}

	return string(markdown), nil
}
<commit_msg>Remove stray debugging print<commit_after>package converters

import (
	"bufio"
	"io/ioutil"
	"log"
	"os/exec"
	"regexp"
	"strings"
)

type PostData struct {
	Meta struct {
		Title    string
		Subtitle string
		Author   string
		Date     string
	}

	Content    string
	ImagePaths []string
}

// Title => Title
func stripAnchorSpans(in string) string {
	re := regexp.MustCompile("]+?>(.*)")
	return re.ReplaceAllString(in, "${1}")
}

// 'foo' => foo
func cleanTitle(in string) string {
	re := regexp.MustCompile("^'?(.*?)'?$")
	return re.ReplaceAllString(in, "${1}")
}

func extractImagePaths(content string) []string {
	re := regexp.MustCompile(`!\[.*?\]\((.*?)\)`)

	matches := []string{}

	for _, match := range re.FindAllStringSubmatch(content, -1) {
		matches = append(matches, match[1])
	}

	return matches
}

// ExtractPostData converts a markdown string into PostData
func ExtractPostData(markdown string) PostData {
	var postData PostData

	lines := strings.Split(markdown, "\n")
	for i := range lines {
		lines[i] = stripAnchorSpans(lines[i])
	}

	// Where does the metadata end and content start?
	idx := 0

	// Grab and parse the metadata block, if it exists
	if lines[0] == "---" {
		for ; idx < len(lines); idx += 1 {
			line := lines[idx]

			// End of block
			if line == "..." {
				break
			}

			kv := strings.SplitN(line, ": ", 2)
			if len(kv) < 2 {
				continue
			} else if kv[1] == "|" {
				kv[1] = ""

				// Roll up multiline values
				for idx += 1; lines[idx] == "" || strings.HasPrefix(lines[idx], " "); idx += 1 {
					kv[1] += strings.TrimSpace(lines[idx])
				}
			}

			switch kv[0] {
			case "title":
				postData.Meta.Title = cleanTitle(kv[1])

			case "subtitle":
				postData.Meta.Subtitle = cleanTitle(kv[1])
			}
		}
	} else {
		// If we don't have a real title, take the first non blank line.
		for _, line := range lines {
			if line != "" {
				postData.Meta.Title = line
			}
		}
	}

	postData.Content = strings.Join(lines[idx:], "\n")
	postData.ImagePaths = extractImagePaths(postData.Content)

	return postData
}

// Suckily, pandoc can't read .docx from streams, so we have to use a file
// interface.
func ConvertDocx(inputFile string, mediaDir string) (string, error) {
	args := []string{
		// from docx
		"-f", "docx",
		// to markdown
		"-t", "markdown",
		// standalone file (including meta)
		"-s",
		"--extract-media", mediaDir,
		"-i", inputFile,
	}

	cmd := exec.Command("pandoc", args...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("failed to open pandoc stdout: %v\n", err)
		return "", err
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Printf("failed to open pandoc stderr: %v\n", err)
		return "", err
	}

	if err := cmd.Start(); err != nil {
		log.Printf("failed to run pandoc: %v\n", err)
		return "", err
	}

	markdown, err := ioutil.ReadAll(stdout)
	if err != nil {
		log.Printf("failed reading from pandoc")
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		log.Printf("pandoc exited with an error: %v\n", err)

		// Make sure we print out the error output
		scanner := bufio.NewScanner(stderr)

		for scanner.Scan() {
			log.Println(scanner.Text())
		}

		return "", err
	}

	return string(markdown), nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"log"
	"os/exec"
	"strings"
)

type Runner struct {
	printer     PrintResetter
	current     *exec.Cmd
	template    string
	placeholder string
}

func (r *Runner) runWithInput(input []byte, kill <-chan bool) {
	cmd := r.cmdWithInput(string(input))

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	ch := r.readCmdStdout(stdout)

	err = cmd.Start()
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case str, ok := <-ch:
			if !ok {
				cmd.Wait()
				r.printer.Reset()
				return
			}
			r.printer.Print(str)
		case <-kill:
			cmd.Process.Kill()
			cmd.Wait()
			r.printer.Reset()
			return
		}
	}
}

func (r *Runner) cmdWithInput(input string) *exec.Cmd {
	line := strings.Replace(r.template, "{{}}", input, -1)
	splitted := strings.Split(line, " ")

	return exec.Command(splitted[0], splitted[1:len(splitted)]...)
}

func (r *Runner) readCmdStdout(stdout io.ReadCloser) <-chan string {
	ch := make(chan string)
	cmdreader := bufio.NewReader(stdout)

	go func() {
		for {
			line, err := cmdreader.ReadBytes('\n')
			if err != nil || err == io.EOF {
				break
			}
			ch <- string(line)
		}
		close(ch)
	}()

	return ch
}
<commit_msg>Actually use runner.placeholder<commit_after>package main

import (
	"bufio"
	"io"
	"log"
	"os/exec"
	"strings"
)

type Runner struct {
	printer     PrintResetter
	current     *exec.Cmd
	template    string
	placeholder string
}

func (r *Runner) runWithInput(input []byte, kill <-chan bool) {
	cmd := r.cmdWithInput(string(input))

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	ch := r.readCmdStdout(stdout)

	err = cmd.Start()
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case str, ok := <-ch:
			if !ok {
				cmd.Wait()
				r.printer.Reset()
				return
			}
			r.printer.Print(str)
		case <-kill:
			cmd.Process.Kill()
			cmd.Wait()
			r.printer.Reset()
			return
		}
	}
}

func (r *Runner) cmdWithInput(input string) *exec.Cmd {
	line := strings.Replace(r.template, r.placeholder, input, -1)
	splitted := strings.Split(line, " ")

	return exec.Command(splitted[0], splitted[1:len(splitted)]...)
}

func (r *Runner) readCmdStdout(stdout io.ReadCloser) <-chan string {
	ch := make(chan string)
	cmdreader := bufio.NewReader(stdout)

	go func() {
		for {
			line, err := cmdreader.ReadBytes('\n')
			if err != nil || err == io.EOF {
				break
			}
			ch <- string(line)
		}
		close(ch)
	}()

	return ch
}
<|endoftext|>


<commit_before>// This package implements a provisioner for Packer that uses
// Chef to provision the remote machine, specifically with chef-solo (that is,
// without a Chef server).
package chefsolo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

const (
	RemoteStagingPath    = "/tmp/provision/chef-solo"
	RemoteFileCachePath  = "/tmp/provision/chef-solo"
	RemoteCookbookPath   = "/tmp/provision/chef-solo/cookbooks"
	DefaultCookbooksPath = "cookbooks"
)

var Ui packer.Ui

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	CookbookPaths       []string `mapstructure:"cookbook_paths"`
	ExecuteCommand      string   `mapstructure:"execute_command"`
	InstallCommand      string   `mapstructure:"install_command"`
	RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"`
	Json                map[string]interface{}
	PreventSudo         bool     `mapstructure:"prevent_sudo"`
	RunList             []string `mapstructure:"run_list"`
	SkipInstall         bool     `mapstructure:"skip_install"`
	StagingDir          string   `mapstructure:"staging_directory"`

	tpl *packer.ConfigTemplate
}

type Provisioner struct {
	config Config
}

type ConfigTemplate struct {
	CookbookPaths string
}

type ExecuteTemplate struct {
	ConfigPath string
	JsonPath   string
	Sudo       bool
}

type InstallChefTemplate struct {
	Sudo bool
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
	}

	if p.config.InstallCommand == "" {
		p.config.InstallCommand = "curl -L https://www.opscode.com/chef/install.sh | {{if .Sudo}}sudo {{end}}bash"
	}

	if p.config.RunList == nil {
		p.config.RunList = make([]string, 0)
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = "/tmp/packer-chef-solo"
	}

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	for _, path := range p.config.CookbookPaths {
		pFileInfo, err := os.Stat(path)

		if err != nil || !pFileInfo.IsDir() {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Bad cookbook path '%s': %s", path, err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.SkipInstall {
		if err := p.installChef(ui, comm); err != nil {
			return fmt.Errorf("Error installing Chef: %s", err)
		}
	}

	if err := p.createStagingDir(ui, comm); err != nil {
		return fmt.Errorf("Error creating staging directory: %s", err)
	}

	// TODO(mitchellh): Upload cookbooks

	configPath, err := p.createConfig(ui, comm)
	if err != nil {
		return fmt.Errorf("Error creating Chef config file: %s", err)
	}

	jsonPath, err := p.createJson(ui, comm)
	if err != nil {
		return fmt.Errorf("Error creating JSON attributes: %s", err)
	}

	if err := p.executeChef(ui, comm, configPath, jsonPath); err != nil {
		return fmt.Errorf("Error executing Chef: %s", err)
	}

	return nil
}

func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator) (string, error) {
	ui.Message("Creating configuration file 'solo.rb'")

	cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths))
	for i, path := range p.config.RemoteCookbookPaths {
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{
		CookbookPaths: strings.Join(cookbook_paths, ","),
	})
	if err != nil {
		return "", err
	}

	remotePath := filepath.Join(p.config.StagingDir, "solo.rb")
	if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) {
	ui.Message("Creating JSON attribute file")

	jsonData := make(map[string]interface{})

	// Copy the configured JSON
	for k, v := range p.config.Json {
		jsonData[k] = v
	}

	// Set the run list if it was specified
	if len(p.config.RunList) > 0 {
		jsonData["run_list"] = p.config.RunList
	}

	jsonBytes, err := json.MarshalIndent(jsonData, "", "  ")
	if err != nil {
		return "", err
	}

	// Upload the bytes
	remotePath := filepath.Join(p.config.StagingDir, "node.json")
	if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes)); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createStagingDir(ui packer.Ui, comm packer.Communicator) error {
	ui.Message(fmt.Sprintf("Creating staging directory: %s", p.config.StagingDir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", p.config.StagingDir),
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}

	return nil
}

func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error {
	command, err := p.config.tpl.Process(p.config.InstallCommand, &ExecuteTemplate{
		ConfigPath: config,
		JsonPath:   json,
		Sudo:       !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	ui.Message(fmt.Sprintf("Executing Chef: %s", command))

	cmd := &packer.RemoteCmd{
		Command: command,
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
	ui.Message("Installing Chef...")

	command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{
		Sudo: !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	cmd := &packer.RemoteCmd{Command: command}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf(
			"Install script exited with non-zero exit status %d", cmd.ExitStatus)
	}

	return nil
}

var DefaultConfigTemplate = `
cookbook_path [{{.CookbookPaths}}]
`
<commit_msg>provisioner/chef-solo: upload cookbooks<commit_after>// This package implements a provisioner for Packer that uses
// Chef to provision the remote machine, specifically with chef-solo (that is,
// without a Chef server).
package chefsolo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"os"
	"path/filepath"
	"strings"
)

const (
	RemoteStagingPath    = "/tmp/provision/chef-solo"
	RemoteFileCachePath  = "/tmp/provision/chef-solo"
	RemoteCookbookPath   = "/tmp/provision/chef-solo/cookbooks"
	DefaultCookbooksPath = "cookbooks"
)

var Ui packer.Ui

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	CookbookPaths       []string `mapstructure:"cookbook_paths"`
	ExecuteCommand      string   `mapstructure:"execute_command"`
	InstallCommand      string   `mapstructure:"install_command"`
	RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"`
	Json                map[string]interface{}
	PreventSudo         bool     `mapstructure:"prevent_sudo"`
	RunList             []string `mapstructure:"run_list"`
	SkipInstall         bool     `mapstructure:"skip_install"`
	StagingDir          string   `mapstructure:"staging_directory"`

	tpl *packer.ConfigTemplate
}

type Provisioner struct {
	config Config
}

type ConfigTemplate struct {
	CookbookPaths string
}

type ExecuteTemplate struct {
	ConfigPath string
	JsonPath   string
	Sudo       bool
}

type InstallChefTemplate struct {
	Sudo bool
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
	}

	if p.config.InstallCommand == "" {
		p.config.InstallCommand = "curl -L https://www.opscode.com/chef/install.sh | {{if .Sudo}}sudo {{end}}bash"
	}

	if p.config.RunList == nil {
		p.config.RunList = make([]string, 0)
	}

	if p.config.StagingDir == "" {
		p.config.StagingDir = "/tmp/packer-chef-solo"
	}

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	for _, path := range p.config.CookbookPaths {
		pFileInfo, err := os.Stat(path)

		if err != nil || !pFileInfo.IsDir() {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Bad cookbook path '%s': %s", path, err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	if !p.config.SkipInstall {
		if err := p.installChef(ui, comm); err != nil {
			return fmt.Errorf("Error installing Chef: %s", err)
		}
	}

	if err := p.createDir(ui, comm, p.config.StagingDir); err != nil {
		return fmt.Errorf("Error creating staging directory: %s", err)
	}

	cookbookPaths := make([]string, 0, len(p.config.CookbookPaths))
	for i, path := range p.config.CookbookPaths {
		targetPath := fmt.Sprintf("%s/cookbooks-%d", p.config.StagingDir, i)
		if err := p.uploadDirectory(ui, comm, targetPath, path); err != nil {
			return fmt.Errorf("Error uploading cookbooks: %s", err)
		}

		cookbookPaths = append(cookbookPaths, targetPath)
	}

	configPath, err := p.createConfig(ui, comm, cookbookPaths)
	if err != nil {
		return fmt.Errorf("Error creating Chef config file: %s", err)
	}

	jsonPath, err := p.createJson(ui, comm)
	if err != nil {
		return fmt.Errorf("Error creating JSON attributes: %s", err)
	}

	if err := p.executeChef(ui, comm, configPath, jsonPath); err != nil {
		return fmt.Errorf("Error executing Chef: %s", err)
	}

	return nil
}

func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
	if err := p.createDir(ui, comm, dst); err != nil {
		return err
	}

	// Make sure there is a trailing "/" so that the directory isn't
	// created on the other side.
	if src[len(src)-1] != '/' {
		src = src + "/"
	}

	return comm.UploadDir(dst, src, nil)
}

func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) {
	ui.Message("Creating configuration file 'solo.rb'")

	cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks))
	for i, path := range p.config.RemoteCookbookPaths {
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	for i, path := range localCookbooks {
		i = len(p.config.RemoteCookbookPaths) + i
		cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
	}

	configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{
		CookbookPaths: strings.Join(cookbook_paths, ","),
	})
	if err != nil {
		return "", err
	}

	remotePath := filepath.Join(p.config.StagingDir, "solo.rb")
	if err := comm.Upload(remotePath, bytes.NewReader([]byte(configString))); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createJson(ui packer.Ui, comm packer.Communicator) (string, error) {
	ui.Message("Creating JSON attribute file")

	jsonData := make(map[string]interface{})

	// Copy the configured JSON
	for k, v := range p.config.Json {
		jsonData[k] = v
	}

	// Set the run list if it was specified
	if len(p.config.RunList) > 0 {
		jsonData["run_list"] = p.config.RunList
	}

	jsonBytes, err := json.MarshalIndent(jsonData, "", "  ")
	if err != nil {
		return "", err
	}

	// Upload the bytes
	remotePath := filepath.Join(p.config.StagingDir, "node.json")
	if err := comm.Upload(remotePath, bytes.NewReader(jsonBytes)); err != nil {
		return "", err
	}

	return remotePath, nil
}

func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir string) error {
	ui.Message(fmt.Sprintf("Creating directory: %s", dir))
	cmd := &packer.RemoteCmd{
		Command: fmt.Sprintf("mkdir -p '%s'", dir),
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status.")
	}

	return nil
}

func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error {
	command, err := p.config.tpl.Process(p.config.InstallCommand, &ExecuteTemplate{
		ConfigPath: config,
		JsonPath:   json,
		Sudo:       !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	ui.Message(fmt.Sprintf("Executing Chef: %s", command))

	cmd := &packer.RemoteCmd{
		Command: command,
	}

	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf("Non-zero exit status: %d", cmd.ExitStatus)
	}

	return nil
}

func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
	ui.Message("Installing Chef...")

	command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{
		Sudo: !p.config.PreventSudo,
	})
	if err != nil {
		return err
	}

	cmd := &packer.RemoteCmd{Command: command}
	if err := cmd.StartWithUi(comm, ui); err != nil {
		return err
	}

	if cmd.ExitStatus != 0 {
		return fmt.Errorf(
			"Install script exited with non-zero exit status %d", cmd.ExitStatus)
	}

	return nil
}

var DefaultConfigTemplate = `
cookbook_path [{{.CookbookPaths}}]
`
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tester

import (
	"fmt"
	"os"
	"path/filepath"

	"k8s.io/klog/v2"

	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	Ginkgo *ginkgo.Tester
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}
	existingPath := os.Getenv("PATH")
	os.Setenv("PATH", fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath))
	return nil
}

func (t *Tester) Execute() error {
	if err := t.pretestSetup(); err != nil {
		return err
	}
	return t.Ginkgo.Execute()
}

func NewDefaultTester() *Tester {
	return &Tester{
		Ginkgo: ginkgo.NewDefaultTester(),
	}
}

func Main() {
	t := NewDefaultTester()
	if err := t.Execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", err)
	}
}
<commit_msg>Add troubleshooting statements<commit_after>/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tester

import (
	"fmt"
	"os"
	"path/filepath"

	"k8s.io/klog/v2"

	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	Ginkgo *ginkgo.Tester
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}

	existingPath := os.Getenv("PATH")
	newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
	klog.Info("Setting PATH=", newPath)
	return os.Setenv("PATH", newPath)
}

func (t *Tester) Execute() error {
	if err := t.pretestSetup(); err != nil {
		return err
	}
	return t.Ginkgo.Execute()
}

func NewDefaultTester() *Tester {
	return &Tester{
		Ginkgo: ginkgo.NewDefaultTester(),
	}
}

func Main() {
	t := NewDefaultTester()
	if err := t.Execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tester

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/octago/sflags/gen/gpflag"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/klog/v2"
	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"

	api "k8s.io/kops/pkg/apis/kops/v1alpha2"
	"k8s.io/kops/tests/e2e/pkg/kops"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	*ginkgo.Tester

	kopsCluster        *api.Cluster
	kopsInstanceGroups []*api.InstanceGroup
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}

	existingPath := os.Getenv("PATH")
	newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
	klog.Info("Setting PATH=", newPath)
	return os.Setenv("PATH", newPath)
}

// parseKubeconfig will get the current kubeconfig, and extract the specified field by jsonpath.
func parseKubeconfig(jsonPath string) (string, error) {
	args := []string{
		"kubectl", "config", "view", "--minify", "-o", "jsonpath={" + jsonPath + "}",
	}
	c := exec.Command(args[0], args[1:]...)
	var stdout bytes.Buffer
	c.Stdout = &stdout
	var stderr bytes.Buffer
	c.Stderr = &stderr
	if err := c.Run(); err != nil {
		klog.Warningf("failed to run %s; stderr=%s", strings.Join(args, " "), stderr.String())
		return "", fmt.Errorf("error querying current config from kubectl: %w", err)
	}

	s := strings.TrimSpace(stdout.String())
	if s == "" {
		return "", fmt.Errorf("kubeconfig did not contain " + jsonPath)
	}
	return s, nil
}

// The --host flag was required in the kubernetes e2e tests, until https://github.com/kubernetes/kubernetes/pull/87030
// We can likely drop this when we drop support / testing for k8s 1.17
func (t *Tester) addHostFlag() error {
	server, err := parseKubeconfig(".clusters[0].cluster.server")
	if err != nil {
		return err
	}
	klog.Infof("Adding --host=%s", server)
	t.TestArgs += " --host=" + server
	return nil
}

// hasFlag detects if the specified flag has been passed in the args
func hasFlag(args string, flag string) bool {
	for _, arg := range strings.Split(args, " ") {
		if !strings.HasPrefix(arg, "-") {
			continue
		}

		arg = strings.TrimLeft(arg, "-")
		if arg == flag || strings.HasPrefix(arg, flag+"=") {
			return true
		}
	}
	return false
}

func (t *Tester) getKopsCluster() (*api.Cluster, error) {
	if t.kopsCluster != nil {
		return t.kopsCluster, nil
	}

	currentContext, err := parseKubeconfig(".current-context")
	if err != nil {
		return nil, err
	}

	kopsClusterName := currentContext

	cluster, err := kops.GetCluster(kopsClusterName)
	if err != nil {
		return nil, err
	}
	t.kopsCluster = cluster

	return cluster, nil

}

func (t *Tester) getKopsInstanceGroups() ([]*api.InstanceGroup, error) {
	if t.kopsInstanceGroups != nil {
		return t.kopsInstanceGroups, nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return nil, err
	}

	igs, err := kops.GetInstanceGroups(cluster.Name)
	if err != nil {
		return nil, err
	}
	t.kopsInstanceGroups = igs

	return igs, nil

}
func (t *Tester) addProviderFlag() error {
	if hasFlag(t.TestArgs, "provider") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	provider := ""
	switch cluster.Spec.CloudProvider {
	case "aws", "gce":
		provider = cluster.Spec.CloudProvider
	case "digitalocean":
	default:
		klog.Warningf("unhandled cluster.spec.cloudProvider %q for determining ginkgo Provider", cluster.Spec.CloudProvider)
	}

	klog.Infof("Setting --provider=%s", provider)
	t.TestArgs += " --provider=" + provider
	return nil
}

func (t *Tester) addZoneFlag() error {
	// gce-zone is indeed used for AWS as well!
	if hasFlag(t.TestArgs, "gce-zone") {
		return nil
	}

	zoneNames, err := t.getZones()
	if err != nil {
		return err
	}

	// gce-zone only expects one zone, we just pass the first one
	zone := zoneNames[0]
	klog.Infof("Setting --gce-zone=%s", zone)
	t.TestArgs += " --gce-zone=" + zone

	// TODO: Pass the new gce-zones flag for 1.21 with all zones?

	return nil
}

func (t *Tester) addMultiZoneFlag() error {
	if hasFlag(t.TestArgs, "gce-multizone") {
		return nil
	}

	zoneNames, err := t.getZones()
	if err != nil {
		return err
	}

	klog.Infof("Setting --gce-multizone=%t", len(zoneNames) > 1)
	t.TestArgs += fmt.Sprintf(" --gce-multizone=%t", len(zoneNames) > 1)

	return nil
}

func (t *Tester) addRegionFlag() error {
	// gce-zone is used for other cloud providers as well
	if hasFlag(t.TestArgs, "gce-region") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	// We don't explicitly set the provider's region in the spec so we need to extract it from vairous fields
	var region string
	switch cluster.Spec.CloudProvider {
	case "aws":
		zone := cluster.Spec.Subnets[0].Zone
		region = zone[:len(zone)-1]
	case "gce":
		region = cluster.Spec.Subnets[0].Region
	default:
		klog.Warningf("unhandled region detection for cloud provider: %v", cluster.Spec.CloudProvider)
	}

	klog.Infof("Setting --gce-region=%s", region)
	t.TestArgs += " --gce-region=" + region
	return nil
}

func (t *Tester) addClusterTagFlag() error {
	if hasFlag(t.TestArgs, "cluster-tag") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	clusterName := cluster.ObjectMeta.Name
	klog.Infof("Setting --cluster-tag=%s", clusterName)
	t.TestArgs += " --cluster-tag=" + clusterName

	return nil
}

func (t *Tester) addProjectFlag() error {
	if hasFlag(t.TestArgs, "gce-project") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	projectID := cluster.Spec.Project
	if projectID == "" {
		return nil
	}
	klog.Infof("Setting --gce-project=%s", projectID)
	t.TestArgs += " --gce-project=" + projectID

	return nil
}

func (t *Tester) getZones() ([]string, error) {
	cluster, err := t.getKopsCluster()
	if err != nil {
		return nil, err
	}

	igs, err := t.getKopsInstanceGroups()
	if err != nil {
		return nil, err
	}

	zones := sets.NewString()
	// Gather zones on AWS
	for _, subnet := range cluster.Spec.Subnets {
		if subnet.Zone != "" {
			zones.Insert(subnet.Zone)
		}
	}
	// Gather zones on GCE
	for _, ig := range igs {
		for _, zone := range ig.Spec.Zones {
			zones.Insert(zone)
		}
	}
	zoneNames := zones.List()

	if len(zoneNames) == 0 {
		klog.Warningf("no zones found in instance groups")
		return nil, nil
	}
	return zoneNames, nil
}

func (t *Tester) addNodeOSArchFlag() error {
	igs, err := t.getKopsInstanceGroups()
	if err != nil {
		return err
	}
	for _, ig := range igs {
		if strings.Contains(ig.Spec.Image, "arm64") {
			klog.Info("Setting --node-os-arch=arm64")
			t.TestArgs += " --node-os-arch=arm64"
			break
		}
	}
	return nil
}

func (t *Tester) execute() error {
	fs, err := gpflag.Parse(t)
	if err != nil {
		return fmt.Errorf("failed to initialize tester: %v", err)
	}

	help := fs.BoolP("help", "h", false, "")
	if err := fs.Parse(os.Args); err != nil {
		return fmt.Errorf("failed to parse flags: %v", err)
	}

	if *help {
		fs.SetOutput(os.Stdout)
		fs.PrintDefaults()
		return nil
	}

	if err := t.pretestSetup(); err != nil {
		return err
	}

	if err := t.addHostFlag(); err != nil {
		return err
	}

	if err := t.addProviderFlag(); err != nil {
		return err
	}

	if err := t.addZoneFlag(); err != nil {
		return err
	}

	if err := t.addClusterTagFlag(); err != nil {
		return err
	}

	if err := t.addRegionFlag(); err != nil {
		return err
	}

	if err := t.addMultiZoneFlag(); err != nil {
		return err
	}

	if err := t.addProjectFlag(); err != nil {
		return err
	}

	if err := t.setSkipRegexFlag(); err != nil {
		return err
	}

	if err := t.addNodeOSArchFlag(); err != nil {
		return err
	}

	return t.Test()
}

func NewDefaultTester() *Tester {
	t := &Tester{}
	t.Tester = ginkgo.NewDefaultTester()
	return t
}

func Main() {
	t := NewDefaultTester()
	if err := t.execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", err)
	}
}
<commit_msg>Allow api-server taint in e2e tests<commit_after>/*
Copyright 2021 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tester

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/octago/sflags/gen/gpflag"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/klog/v2"
	"sigs.k8s.io/kubetest2/pkg/testers/ginkgo"

	api "k8s.io/kops/pkg/apis/kops/v1alpha2"
	"k8s.io/kops/tests/e2e/pkg/kops"
)

// Tester wraps kubetest2's ginkgo tester with additional functionality
type Tester struct {
	*ginkgo.Tester

	kopsCluster        *api.Cluster
	kopsInstanceGroups []*api.InstanceGroup
}

func (t *Tester) pretestSetup() error {
	kubectlPath, err := t.AcquireKubectl()
	if err != nil {
		return fmt.Errorf("failed to get kubectl package from published releases: %s", err)
	}

	existingPath := os.Getenv("PATH")
	newPath := fmt.Sprintf("%v:%v", filepath.Dir(kubectlPath), existingPath)
	klog.Info("Setting PATH=", newPath)
	return os.Setenv("PATH", newPath)
}

// parseKubeconfig will get the current kubeconfig, and extract the specified field by jsonpath.
func parseKubeconfig(jsonPath string) (string, error) {
	args := []string{
		"kubectl", "config", "view", "--minify", "-o", "jsonpath={" + jsonPath + "}",
	}
	c := exec.Command(args[0], args[1:]...)
	var stdout bytes.Buffer
	c.Stdout = &stdout
	var stderr bytes.Buffer
	c.Stderr = &stderr
	if err := c.Run(); err != nil {
		klog.Warningf("failed to run %s; stderr=%s", strings.Join(args, " "), stderr.String())
		return "", fmt.Errorf("error querying current config from kubectl: %w", err)
	}

	s := strings.TrimSpace(stdout.String())
	if s == "" {
		return "", fmt.Errorf("kubeconfig did not contain " + jsonPath)
	}
	return s, nil
}

// The --host flag was required in the kubernetes e2e tests, until https://github.com/kubernetes/kubernetes/pull/87030
// We can likely drop this when we drop support / testing for k8s 1.17
func (t *Tester) addHostFlag() error {
	server, err := parseKubeconfig(".clusters[0].cluster.server")
	if err != nil {
		return err
	}
	klog.Infof("Adding --host=%s", server)
	t.TestArgs += " --host=" + server
	return nil
}

// hasFlag detects if the specified flag has been passed in the args
func hasFlag(args string, flag string) bool {
	for _, arg := range strings.Split(args, " ") {
		if !strings.HasPrefix(arg, "-") {
			continue
		}

		arg = strings.TrimLeft(arg, "-")
		if arg == flag || strings.HasPrefix(arg, flag+"=") {
			return true
		}
	}
	return false
}

func (t *Tester) getKopsCluster() (*api.Cluster, error) {
	if t.kopsCluster != nil {
		return t.kopsCluster, nil
	}

	currentContext, err := parseKubeconfig(".current-context")
	if err != nil {
		return nil, err
	}

	kopsClusterName := currentContext

	cluster, err := kops.GetCluster(kopsClusterName)
	if err != nil {
		return nil, err
	}
	t.kopsCluster = cluster

	return cluster, nil

}

func (t *Tester) getKopsInstanceGroups() ([]*api.InstanceGroup, error) {
	if t.kopsInstanceGroups != nil {
		return t.kopsInstanceGroups, nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return nil, err
	}

	igs, err := kops.GetInstanceGroups(cluster.Name)
	if err != nil {
		return nil, err
	}
	t.kopsInstanceGroups = igs

	return igs, nil

}
func (t *Tester) addProviderFlag() error {
	if hasFlag(t.TestArgs, "provider") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	provider := ""
	switch cluster.Spec.CloudProvider {
	case "aws", "gce":
		provider = cluster.Spec.CloudProvider
	case "digitalocean":
	default:
		klog.Warningf("unhandled cluster.spec.cloudProvider %q for determining ginkgo Provider", cluster.Spec.CloudProvider)
	}

	klog.Infof("Setting --provider=%s", provider)
	t.TestArgs += " --provider=" + provider
	return nil
}

func (t *Tester) addZoneFlag() error {
	// gce-zone is indeed used for AWS as well!
	if hasFlag(t.TestArgs, "gce-zone") {
		return nil
	}

	zoneNames, err := t.getZones()
	if err != nil {
		return err
	}

	// gce-zone only expects one zone, we just pass the first one
	zone := zoneNames[0]
	klog.Infof("Setting --gce-zone=%s", zone)
	t.TestArgs += " --gce-zone=" + zone

	// TODO: Pass the new gce-zones flag for 1.21 with all zones?

	return nil
}

func (t *Tester) addMultiZoneFlag() error {
	if hasFlag(t.TestArgs, "gce-multizone") {
		return nil
	}

	zoneNames, err := t.getZones()
	if err != nil {
		return err
	}

	klog.Infof("Setting --gce-multizone=%t", len(zoneNames) > 1)
	t.TestArgs += fmt.Sprintf(" --gce-multizone=%t", len(zoneNames) > 1)

	return nil
}

func (t *Tester) addRegionFlag() error {
	// gce-zone is used for other cloud providers as well
	if hasFlag(t.TestArgs, "gce-region") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	// We don't explicitly set the provider's region in the spec so we need to extract it from vairous fields
	var region string
	switch cluster.Spec.CloudProvider {
	case "aws":
		zone := cluster.Spec.Subnets[0].Zone
		region = zone[:len(zone)-1]
	case "gce":
		region = cluster.Spec.Subnets[0].Region
	default:
		klog.Warningf("unhandled region detection for cloud provider: %v", cluster.Spec.CloudProvider)
	}

	klog.Infof("Setting --gce-region=%s", region)
	t.TestArgs += " --gce-region=" + region
	return nil
}

func (t *Tester) addClusterTagFlag() error {
	if hasFlag(t.TestArgs, "cluster-tag") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	clusterName := cluster.ObjectMeta.Name
	klog.Infof("Setting --cluster-tag=%s", clusterName)
	t.TestArgs += " --cluster-tag=" + clusterName

	return nil
}

func (t *Tester) addProjectFlag() error {
	if hasFlag(t.TestArgs, "gce-project") {
		return nil
	}

	cluster, err := t.getKopsCluster()
	if err != nil {
		return err
	}

	projectID := cluster.Spec.Project
	if projectID == "" {
		return nil
	}
	klog.Infof("Setting --gce-project=%s", projectID)
	t.TestArgs += " --gce-project=" + projectID

	return nil
}

func (t *Tester) getZones() ([]string, error) {
	cluster, err := t.getKopsCluster()
	if err != nil {
		return nil, err
	}

	igs, err := t.getKopsInstanceGroups()
	if err != nil {
		return nil, err
	}

	zones := sets.NewString()
	// Gather zones on AWS
	for _, subnet := range cluster.Spec.Subnets {
		if subnet.Zone != "" {
			zones.Insert(subnet.Zone)
		}
	}
	// Gather zones on GCE
	for _, ig := range igs {
		for _, zone := range ig.Spec.Zones {
			zones.Insert(zone)
		}
	}
	zoneNames := zones.List()

	if len(zoneNames) == 0 {
		klog.Warningf("no zones found in instance groups")
		return nil, nil
	}
	return zoneNames, nil
}

func (t *Tester) addNodeOSArchFlag() error {
	igs, err := t.getKopsInstanceGroups()
	if err != nil {
		return err
	}
	for _, ig := range igs {
		if strings.Contains(ig.Spec.Image, "arm64") {
			klog.Info("Setting --node-os-arch=arm64")
			t.TestArgs += " --node-os-arch=arm64"
			break
		}
	}
	return nil
}

func (t *Tester) addNonBlockingTaintsFlag() {
	if hasFlag(t.TestArgs, "non-blocking-taints") {
		return
	}
	nbt := "node-role.kubernetes.io/master,node-role.kubernetes.io/api-server"
	klog.Infof("Setting --non-blocking-taints=%s", nbt)
	t.TestArgs += fmt.Sprintf(" --non-blocking-taints=%v", nbt)
}

func (t *Tester) execute() error {
	fs, err := gpflag.Parse(t)
	if err != nil {
		return fmt.Errorf("failed to initialize tester: %v", err)
	}

	help := fs.BoolP("help", "h", false, "")
	if err := fs.Parse(os.Args); err != nil {
		return fmt.Errorf("failed to parse flags: %v", err)
	}

	if *help {
		fs.SetOutput(os.Stdout)
		fs.PrintDefaults()
		return nil
	}

	if err := t.pretestSetup(); err != nil {
		return err
	}

	if err := t.addHostFlag(); err != nil {
		return err
	}

	if err := t.addProviderFlag(); err != nil {
		return err
	}

	if err := t.addZoneFlag(); err != nil {
		return err
	}

	if err := t.addClusterTagFlag(); err != nil {
		return err
	}

	if err := t.addRegionFlag(); err != nil {
		return err
	}

	if err := t.addMultiZoneFlag(); err != nil {
		return err
	}

	if err := t.addProjectFlag(); err != nil {
		return err
	}

	if err := t.setSkipRegexFlag(); err != nil {
		return err
	}

	if err := t.addNodeOSArchFlag(); err != nil {
		return err
	}
	t.addNonBlockingTaintsFlag()

	return t.Test()
}

func NewDefaultTester() *Tester {
	t := &Tester{}
	t.Tester = ginkgo.NewDefaultTester()
	return t
}

func Main() {
	t := NewDefaultTester()
	if err := t.execute(); err != nil {
		klog.Fatalf("failed to run ginkgo tester: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

var (
	g_train = flag.Bool("train", false, "switch to run the training during validation")

	trainfile = "training.csv"
	testfile  = "test.csv"
)

func printf(format string, args ...interface{}) (int, error) {
	return fmt.Fprintf(os.Stderr, format, args...)
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, `Usage: hml-validate zipfile-or-directory [test.csv [training.csv]]

where:
  - test.csv is a test file (taken from $PWD if not given.)
  - training.csv is a training file (taken from $PWD if not given.)
    training.csv is needed iff -train is enabled.

ex:
 $ hml-validate my-team
 $ hml-validate my-team/
 $ hml-validate my-team.zip
 $ hml-validate my-team.tar.gz
 $ hml-validate my-team /path/to/test.csv
 $ hml-validate my-team /path/to/test.csv /path/to/training.csv

options:
`,
		)
		flag.PrintDefaults()

		fmt.Fprintf(os.Stderr, "\nNeed more help ?\n => https://www.kaggle.com/c/higgs-boson/forums\n")
	}

	flag.Parse()

	printf("::: higgsml-validate...\n")
	if flag.NArg() < 1 {
		printf("**error** hml-validate needs the path to a zip file\n")
		flag.Usage()
		os.Exit(1)
	}

	if !*g_train {
		trainfile = ""
	}

	if flag.NArg() > 1 {
		testfile = flag.Arg(1)
	}
	if flag.NArg() > 2 {
		testfile = flag.Arg(1)
		trainfile = flag.Arg(2)
	}

	for _, file := range []*string{&testfile, &trainfile} {
		// printf("file[%d]=%q\n", i, *file)
		if *file == "" {
			continue
		}
		if !filepath.IsAbs(*file) {
			name, err := filepath.Abs(*file)
			if err == nil {
				*file = name
			}
		}
		_, err := os.Lstat(*file)
		if err != nil {
			printf("**error** no such file [%s]\n", *file)
			flag.Usage()
			os.Exit(1)
		}
		// printf("file[%d]=%q\n", i, *file)
	}

	rc := run()
	os.Exit(rc)
}

func run() int {

	dir, err := ioutil.TempDir("", "higgsml-validate-")
	if err != nil {
		printf("**error** creating tmpdir: %v\n", err)
		return 1
	}
	defer os.RemoveAll(dir)

	fname := flag.Arg(0)

	fi, err := os.Lstat(fname)
	if err != nil {
		printf("**error** stat-ing [%s]: %v\n", fname, err)
		return 1
	}

	if fi.IsDir() {
		err = process_dir(dir, fname)
		if err != nil {
			printf("**error** processing directory [%s]: %v\n", fname, err)
			return 1
		}
	} else {
		err = process_archive(dir, fname)
		if err != nil {
			printf("**error** processing archive [%s]: %v\n", fname, err)
			return 1
		}
	}

	v, err := NewValidator(dir, *g_train)
	if err != nil {
		printf("**error** validating: %v\n", err)
		return 1
	}

	// printf("validate: %#v\n", v)
	err = v.Run()
	if err != nil {
		printf("**error** running validation: %v\n", err)
		return 1
	}

	return 0
}

func process_dir(outdir, indir string) error {
	return copytree(filepath.Join(outdir, filepath.Base(indir)), indir)
}

func process_archive(dir, fname string) error {
	var err error
	printf("Archive: %s\n", fname)

	r, err := zip.OpenReader(fname)
	if err != nil {
		printf("**error** %v\n", err)
		return err
	}
	defer r.Close()

	// printf("comment: %q\n", r.Comment)

	err = unzip(dir, r)
	if err != nil {
		printf("**error** unzipping [%s] under [%s]: %v\n", fname, dir, err)
		return err
	}
	return err
}

func unzip(tmpdir string, r *zip.ReadCloser) error {

	var err error

	for _, f := range r.File {
		printf("  inflating: %s\n", f.Name)
		rc, err := f.Open()
		if err != nil {
			printf("**error** opening [%s]: %v\n", f.Name, err)
			return err
		}
		defer rc.Close()

		ofname := filepath.Join(tmpdir, f.Name)
		// printf("extracting into: [%s] (%v)\n", ofname, f.Mode())
		odir := filepath.Dir(ofname)
		err = os.MkdirAll(odir, 0755)
		if err != nil {
			printf("**error** creating output dir [%s]: %v\n", odir, err)
			return err
		}
		w, err := os.Create(ofname)
		if err != nil {
			printf("**error** creating output file [%s]: %v\n", ofname, err)
			return err
		}
		defer w.Close()

		_, err = io.Copy(w, rc)
		if err != nil {
			printf("**error** copying to [%s]: %v\n", ofname, err)
			return err
		}

		err = w.Chmod(f.Mode())
		if err != nil {
			printf("**error** setting chmod [%v] for file [%s]: %v\n", f.Mode(), ofname, err)
			return err
		}

		err = rc.Close()
		if err != nil {
			printf("**error** closing input file [%s]: %v\n", f.Name, err)
			return err
		}

		err = w.Close()
		if err != nil {
			printf("**error** closing output file [%s]: %v\n", ofname, err)
			return err
		}
	}

	return err
}
<commit_msg>hml-validate: handle directories in zip.File<commit_after>package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

var (
	g_train = flag.Bool("train", false, "switch to run the training during validation")

	trainfile = "training.csv"
	testfile  = "test.csv"
)

func printf(format string, args ...interface{}) (int, error) {
	return fmt.Fprintf(os.Stderr, format, args...)
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, `Usage: hml-validate zipfile-or-directory [test.csv [training.csv]]

where:
  - test.csv is a test file (taken from $PWD if not given.)
  - training.csv is a training file (taken from $PWD if not given.)
    training.csv is needed iff -train is enabled.

ex:
 $ hml-validate my-team
 $ hml-validate my-team/
 $ hml-validate my-team.zip
 $ hml-validate my-team.tar.gz
 $ hml-validate my-team /path/to/test.csv
 $ hml-validate my-team /path/to/test.csv /path/to/training.csv

options:
`,
		)
		flag.PrintDefaults()

		fmt.Fprintf(os.Stderr, "\nNeed more help ?\n => https://www.kaggle.com/c/higgs-boson/forums\n")
	}

	flag.Parse()

	printf("::: higgsml-validate...\n")
	if flag.NArg() < 1 {
		printf("**error** hml-validate needs the path to a zip file\n")
		flag.Usage()
		os.Exit(1)
	}

	if !*g_train {
		trainfile = ""
	}

	if flag.NArg() > 1 {
		testfile = flag.Arg(1)
	}
	if flag.NArg() > 2 {
		testfile = flag.Arg(1)
		trainfile = flag.Arg(2)
	}

	for _, file := range []*string{&testfile, &trainfile} {
		// printf("file[%d]=%q\n", i, *file)
		if *file == "" {
			continue
		}
		if !filepath.IsAbs(*file) {
			name, err := filepath.Abs(*file)
			if err == nil {
				*file = name
			}
		}
		_, err := os.Lstat(*file)
		if err != nil {
			printf("**error** no such file [%s]\n", *file)
			flag.Usage()
			os.Exit(1)
		}
		// printf("file[%d]=%q\n", i, *file)
	}

	rc := run()
	os.Exit(rc)
}

func run() int {

	dir, err := ioutil.TempDir("", "higgsml-validate-")
	if err != nil {
		printf("**error** creating tmpdir: %v\n", err)
		return 1
	}
	defer os.RemoveAll(dir)

	fname := flag.Arg(0)

	fi, err := os.Lstat(fname)
	if err != nil {
		printf("**error** stat-ing [%s]: %v\n", fname, err)
		return 1
	}

	if fi.IsDir() {
		err = process_dir(dir, fname)
		if err != nil {
			printf("**error** processing directory [%s]: %v\n", fname, err)
			return 1
		}
	} else {
		err = process_archive(dir, fname)
		if err != nil {
			printf("**error** processing archive [%s]: %v\n", fname, err)
			return 1
		}
	}

	v, err := NewValidator(dir, *g_train)
	if err != nil {
		printf("**error** validating: %v\n", err)
		return 1
	}

	// printf("validate: %#v\n", v)
	err = v.Run()
	if err != nil {
		printf("**error** running validation: %v\n", err)
		return 1
	}

	return 0
}

func process_dir(outdir, indir string) error {
	return copytree(filepath.Join(outdir, filepath.Base(indir)), indir)
}

func process_archive(dir, fname string) error {
	var err error
	printf("Archive: %s\n", fname)

	r, err := zip.OpenReader(fname)
	if err != nil {
		printf("**error** %v\n", err)
		return err
	}
	defer r.Close()

	// printf("comment: %q\n", r.Comment)

	err = unzip(dir, r)
	if err != nil {
		printf("**error** unzipping [%s] under [%s]: %v\n", fname, dir, err)
		return err
	}
	return err
}

func unzip(tmpdir string, r *zip.ReadCloser) error {

	var err error

	for _, f := range r.File {
		printf("  inflating: %s\n", f.Name)
		if f.FileInfo().IsDir() {
			continue
		}
		rc, err := f.Open()
		if err != nil {
			printf("**error** opening [%s]: %v\n", f.Name, err)
			return err
		}
		defer rc.Close()

		ofname := filepath.Join(tmpdir, f.Name)
		// printf("extracting into: [%s] (%v)\n", ofname, f.Mode())
		odir := filepath.Dir(ofname)
		err = os.MkdirAll(odir, 0755)
		if err != nil {
			printf("**error** creating output dir [%s]: %v\n", odir, err)
			return err
		}
		w, err := os.Create(ofname)
		if err != nil {
			printf("**error** creating output file [%s]: %v\n", ofname, err)
			return err
		}
		defer w.Close()

		_, err = io.Copy(w, rc)
		if err != nil {
			printf("**error** copying to [%s]: %v\n", ofname, err)
			return err
		}

		err = w.Chmod(f.Mode())
		if err != nil {
			printf("**error** setting chmod [%v] for file [%s]: %v\n", f.Mode(), ofname, err)
			return err
		}

		err = rc.Close()
		if err != nil {
			printf("**error** closing input file [%s]: %v\n", f.Name, err)
			return err
		}

		err = w.Close()
		if err != nil {
			printf("**error** closing output file [%s]: %v\n", ofname, err)
			return err
		}
	}

	return err
}
<|endoftext|>